A personal timekeeping webapp built for a 1099 tax accountant managing multiple clients. Features timer-based and manual time entry, weekly report generation with daily breakdowns, and email delivery of approved reports.
Live: clockwork-opal.vercel.app
- Timer & Manual Entry — Start/stop timer per client or log hours manually. One active timer at a time; starting a new one auto-stops the previous.
- Weekly Timesheet — Grid view of hours grouped by day and client, with week-to-week navigation.
- Report Generation — Auto-generate weekly summaries from time entries. Review, approve, and send to employer via email.
- Client Management — Color-coded clients with short codes for quick identification.
- Interactive Tutorial — 5-step guided tour with spotlight overlays that walks new users through the full workflow.
- Onboarding Wizard — First-time setup for profile, employer info, and initial client with inline validation.
- Dark/Light/System Theme — Persisted per-user in the database.
- Responsive Animations — Page transitions, staggered entrances, and timer pulse via Framer Motion.
| Layer | Technology |
|---|---|
| Framework | Next.js 14 (App Router), React 18, TypeScript |
| Styling | Tailwind CSS, shadcn/ui (New York style, Stone base) |
| Animation | Framer Motion |
| Database | Supabase (PostgreSQL + Row Level Security) |
| Auth | Supabase Auth (Google OAuth + email/password) |
| Bot Protection | Cloudflare Turnstile |
| mailto: links with pre-formatted report body | |
| Testing | Vitest + Testing Library, Playwright (E2E) |
| Deployment | Vercel (frontend), Supabase Cloud (backend) |
The app uses Next.js App Router with Server Components by default and Client Components only where interactivity is needed. All data mutations go through Server Actions with Zod validation, auth checks, and path revalidation.
src/
├── app/(auth)/ # Auth-gated routes with shared layout (sidebar, tutorial)
├── components/
│ ├── ui/ # shadcn/ui primitives
│ └── features/ # Domain-organized components (timer, clients, entries, review, tutorial, etc.)
├── lib/
│ ├── actions/ # Server actions (CRUD, timer, reports, profile)
│ ├── supabase/ # Client factories (browser, server, middleware)
│ └── utils/ # Date helpers, report builder
└── types/ # Auto-generated Supabase types
Data Model: 4 tables with RLS — profiles, clients, time_entries, weekly_reports.
- Node.js 18+
- pnpm
- Docker (for local Supabase)
# Clone and install
git clone https://github.com/mrw1986/clockwork.git
cd clockwork
pnpm install
# Start local Supabase
pnpm supabase start
# Copy env template and fill in values
cp .env.local.example .env.local
# Generate types
pnpm supabase gen types typescript --local > src/types/database.ts
# Run dev server
pnpm devNEXT_PUBLIC_SUPABASE_URL= # From supabase start output
NEXT_PUBLIC_SUPABASE_ANON_KEY= # From supabase start output
SUPABASE_SERVICE_ROLE_KEY= # From supabase start output
NEXT_PUBLIC_TURNSTILE_SITE_KEY= # Cloudflare Turnstile site key
TURNSTILE_SECRET_KEY= # Cloudflare Turnstile secret key
pnpm dev # Dev server (localhost:3000)
pnpm build # Production build
pnpm lint # ESLint
pnpm vitest run # Unit/component tests
pnpm test:e2e # Playwright E2E testsMIT