Timer Plugin Walkthrough
Overview
Section titled “Overview”The Timer plugin is a production plugin that demonstrates all major plugin concepts:
- TAB extensions (time tracking interface)
- ACTION extensions (start/stop timer buttons)
- WIDGET extensions (sidebar active timer display)
- Server integration (tRPC API for persistence)
- Local state management (localStorage for timers)
Plugin Structure
Section titled “Plugin Structure”packages/plugins/timer/├── src/│ ├── components/│ │ ├── TimerTab.tsx # Main tab component│ │ ├── SidebarTimer.tsx # Sidebar widget│ │ └── TimeEntryCard.tsx # Display component│ ├── server/│ │ └── router.ts # tRPC endpoints│ ├── lib/│ │ ├── useTimerState.ts # Timer state hook│ │ └── timer-utils.ts # Helper functions│ ├── manifest.ts # Plugin manifest│ └── index.ts # ExportsManifest Configuration
Section titled “Manifest Configuration”export const timerPlugin = definePlugin({ slug: 'timer', name: 'Time Tracker', version: '1.2.0', description: 'Track time spent on work units and projects', author: 'Aether Team', category: 'productivity', tags: ['time-tracking', 'billing'], businessTypes: ['SERVICE', 'PROJECT'],
extensions: [ // TAB extension - time tracking interface { point: 'work-unit.detail.tabs', plugin: 'timer', priority: 70, extension: { type: ExtensionType.TAB, id: 'time-entries', label: 'Time Tracking', icon: IconClock, component: TimerTab, badge: (context) => context?.timeEntryCount } },
// ACTION extension - toggle timer { point: 'work-unit.header.actions', plugin: 'timer', priority: 80, extension: { type: ExtensionType.ACTION, id: 'timer-toggle', label: 'Start Timer', icon: IconClock, onClick: toggleTimer, } },
// WIDGET extension - sidebar display { point: 'sidebar.widgets', plugin: 'timer', priority: 90, extension: { type: ExtensionType.WIDGET, id: 'sidebar-timer', component: SidebarTimer } } ],
serverRouter: timerRouter,});Key Learnings
Section titled “Key Learnings”- State Management: Hybrid approach using localStorage for real-time updates and database for persistence
- Cross-Component Communication: Event-based updates using
storageevents - Error Handling: Graceful degradation when timers can’t be saved
- Performance: Efficient queries with proper filtering and pagination