import bpy


class BoilerPlateData(bpy.types.PropertyGroup):
    counter: bpy.props.IntProperty(name="Count", default=1, min=0)


class BoilerPlate_OT_Operator(bpy.types.Operator):
    bl_idname = "boilerplate.operator"
    bl_label = ""
    bl_description = "Set the frame to the playback range"

    def execute(self, context):
        context.scene.BoilerPlateData.counter += 1
        return {'FINISHED'}


class BoilerPlate_PT_MainPanel(bpy.types.Panel):
    bl_label = "Boiler Plate"
    bl_idname = "BoilerPlateData_PT_boiler_plate"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "BoilerPlate"
    
    def draw(self, context):
        layout = self.layout

        settings = layout.box()
        row = settings.row()
        row.operator("boilerplate.operator", icon="ADD", text="Add")
        row.prop(context.scene.BoilerPlateData, "counter")

# The order is important
classes = (
    BoilerPlateData,
    BoilerPlate_OT_Operator,
    BoilerPlate_PT_MainPanel,
)


def register():
    for cls in classes:
        bpy.utils.register_class(cls)
    bpy.types.Scene.BoilerPlateData = bpy.props.PointerProperty(type=BoilerPlateData)


def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)
        
if __name__ == "__main__":
    register()