Combine clients and businesses under entities, polish the web time clock,
and show live invoice PDF preview with tighter line-item editing.
Co-authored-by: Cursor <cursoragent@cursor.com>
Restrict line item edits to draft invoices, auto-create drafts on clock-out,
and add sendReminderAt scheduling with dashboard due reminders.
Co-authored-by: Cursor <cursoragent@cursor.com>
Extract privacy and terms content into reusable components, replace auth modals with links to /privacy and /terms, add settings legal section, and remove duplicate legal-modal markup.
Co-authored-by: Cursor <cursoragent@cursor.com>
Dashboard pages require authentication and include client components
with hooks that fail during static prerendering on Linux/Docker.
Setting force-dynamic in the layout prevents build-time prerendering
across the entire authenticated dashboard.
https://claude.ai/code/session_014126WHVRT8mftmqkU6dajG
- Remove "Time Clock" from sidebar navigation
- Redirect /dashboard/time-clock to /dashboard/invoices
- Add InvoiceTimerCard to invoice detail page (shown for non-paid invoices)
- Timer started from an invoice is explicitly linked to that invoice at clock-in
- On clock-out, time is added directly to the linked invoice as a line item
- Active timer widget on dashboard now shows which invoice is being tracked
- Backend: clockIn accepts invoiceId; clockOut prefers explicit invoiceId over
searching for the latest draft invoice for the client
https://claude.ai/code/session_014126WHVRT8mftmqkU6dajG
Summary cards now include the in-progress session's hours and earnings,
rounded up to the nearest 15-min increment (matching clock-out billing
logic). A secondary "+Xh est." line appears below each stat when a timer
is active, updating every second as the elapsed counter ticks.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Turbopack disallows ssr:false in Server Components. Extracted the three
recharts dynamic imports into charts-client.tsx ("use client"), which
page.tsx now imports from directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Dynamically import recharts components with ssr:false to prevent
server-side rendering of DOM-dependent charts, eliminating the
width/height -1 warnings and redacted SSR errors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a banner below the page header when a timer is running: shows
description, client, elapsed time (live), a Stop button that auto-links
to the latest invoice, and a Details link to the time clock page.
Query is prefetched server-side so the widget is instant on load.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New beenvoice_time_entry DB table with migration (startedAt/endedAt, hours, rate, clientId)
- tRPC router with clockIn, clockOut, getRunning, getAll, getSummary, create, update, delete
- Dashboard page at /dashboard/time-clock with live elapsed timer, entry list, and manual entry form
- 5 MCP tools: time_clock_in, time_clock_out, time_get_running, time_entries_list, time_entries_create
- Sidebar navigation entry
Timer state is stored in PostgreSQL (endedAt IS NULL = running), suitable for serverless/Coolify deployment.
- Recurring invoices: schedule-based auto-generation with CRUD UI at /dashboard/invoices/recurring and POST /api/cron/generate-recurring cron endpoint
- Public invoice link: generate/revoke shareable /i/[token] page for unauthenticated clients with PDF download
- Live time tracker: localStorage-persisted timer widget in invoice editor that appends a line item on stop (rounds to nearest 0.25h)
- Partial payment tracking: record payments per invoice, auto-mark paid when fully covered, balance due display
- Send reminder: email reminder via Resend with custom message dialog and last-sent indicator
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Implemented `AdministrationContent` component for managing account roles.
- Created `AdministrationPage` to serve as the main entry point for administration tasks.
- Added PDF preview functionality with `PdfPreviewFrame` component for invoice generation.
- Introduced `InputColor` component for advanced color selection with various formats.
- Established color conversion utilities in `color-converter.ts` for handling color formats.
- Defined appearance-related schemas and types in `appearance.ts` for consistent theme management.
- Cleaned up imports and formatted code for better readability in invoices-data-table.tsx.
- Enhanced invoice interface definitions for clarity.
- Improved toast messages for bulk delete and update actions.
- Refactored date formatting and status type retrieval for better readability.
- Simplified template management in templates page, extracting TemplateList component.
- Added registration toggle based on environment variable DISABLE_SIGNUPS.
- Updated navbar to conditionally render registration link based on allowRegistration prop.
- Enhanced error handling and validation in expenses and settings routers.
- Improved PDF export footer handling.
- Updated TRPC react integration for cleaner type imports.
- Deleted the InvoiceView component to streamline the codebase.
- Updated EmailPreview and SendEmailDialog components to include currency and notes fields.
- Enhanced invoice-form to handle default hourly rates and improved item mapping.
- Refactored email template generation to include notes and currency formatting.
- Adjusted API routers for invoices to calculate totals and handle notes and currency correctly.
- Deleted the start.sh script for container management.
- Added AGENTS.md for project guidelines and development principles.
- Introduced new SQL migration files for user appearance preferences and platform settings.
- Implemented appearance provider to manage user interface themes and preferences.
- Created branding utility to define and manage branding-related constants and types.
Co-authored-by: Copilot <copilot@github.com>
- Add taxDeductible boolean to expenses schema + migration 0002
- Update expenses router, form, and list to support tax-deductible flag
- Fix invoice-view tax calculation (was hardcoded $0.00; now uses taxRate)
- New Tax Summary tab in Reports: year selector, income/deductions breakdown,
SE tax + federal income estimates, quarterly bar chart
- CSV export for accountant with income + expense rows and tax summary
https://claude.ai/code/session_012sqEgNQpx676isepeoX4Mi
- Move EXPENSE_CATEGORIES to ~/lib/expense-categories.ts to break
server router import chain from client component
- Use inline import() types in trpc/react.tsx to prevent Turbopack
from including server modules (pg, db) in the client bundle
- Replace next/font/google with system font stacks to fix build
failures in environments without Google Fonts access
https://claude.ai/code/session_012sqEgNQpx676isepeoX4Mi
Migrations:
- drizzle.config.ts: add out: './drizzle' so drizzle-kit generate writes
SQL migration files instead of only supporting push
- drizzle/0000_glossy_magneto.sql: initial migration capturing all 9
current tables (users, accounts, sessions, verification_tokens,
sso_providers, clients, businesses, invoices, invoice_items)
- src/server/db/migrate.ts: programmatic runner using drizzle-orm's
migrate() — tracks applied migrations in __drizzle_migrations,
safe to run on every deploy
- package.json: db:migrate now runs the programmatic runner instead of
drizzle-kit migrate (CLI requires devDeps at runtime)
- start.sh: replace drizzle-kit push with bun src/server/db/migrate.ts
- Dockerfile: copy drizzle/ folder into the runner image so migrations
are available at container startup
Mobile fixes:
- data-table.tsx: pagination buttons grow from 32px to 40px on mobile
(h-10 w-10 md:h-8 md:w-8) to meet 44px touch-target guidelines
- floating-action-bar.tsx: stack left-content + action buttons to column
layout on narrow screens (flex-col sm:flex-row), reduce padding on
mobile (p-3 sm:p-4)
- revenue-chart.tsx: responsive chart height (h-48 md:h-64) so the chart
doesn't consume too much vertical space on small screens
https://claude.ai/code/session_012sqEgNQpx676isepeoX4Mi
- README: fix auth (better-auth), database (PostgreSQL), env vars,
Docker setup, and feature list to reflect actual implementation
- InvoicesDataTable: show status badge + amount inline on mobile
(previously hidden behind sm: breakpoint, leaving mobile users
with no financial or status info at a glance)
- InvoiceItemsTable: hide Date/Hours/Rate columns on mobile and
fold that info into the Description cell as secondary text
- invoice-view.tsx header card: wrap to column layout on mobile
so status/amount/button don't overflow narrow screens; also
improve item rows to show date, hours, and rate as subtext
https://claude.ai/code/session_012sqEgNQpx676isepeoX4Mi
- Create types.ts with proper TypeScript interfaces for dashboard data
- Replace all 'any' types in dashboard/page.tsx with DashboardStats and RecentInvoice
- Fix type safety in invoice-form.tsx:
- Replace 'any' in updateItem with proper union type
- Add generic type parameter to updateField for type safety
- Fix status type assertion (any -> proper union type)
- Replace || with ?? for safer null handling
- All TypeScript compilation errors resolved
- Lint down to 1 warning (false positive for 'loading' variable)
- Remove unused imports from page.tsx, clients/page.tsx, invoices/page.tsx
- Remove unused imports from invoice-form.tsx, invoice-workspace.tsx
- Move CustomTooltip outside component in revenue-chart.tsx (fixes react-hooks/static-components)
- Fix type safety in umami.ts (any -> unknown)
- Fix type safety in sidebar-provider.tsx (add type assertion)
- Add no-op comments to empty fallback functions in animation-preferences-provider.tsx
- Fix type safety in invoice-workspace.tsx (any[] -> typed array)
Note: dashboard/page.tsx still has ~55 type safety warnings related to 'any' types
in stats/invoice data. These are pre-existing and would require significant refactoring
of the dashboard data flow to properly type. TypeScript compilation passes.
- Remove clock icons and hour text from calendar month view, show only activity bars
- Fix calendar week view mobile layout (2-column grid instead of vertical stack)
- Update invoice form skeleton to match actual layout structure
- Add client-side validation for empty invoice item descriptions with auto-scroll to error
- Fix hourly rate defaulting logic with proper type guards
- Update invoice details skeleton to match page structure with PageHeader
- Fix hydration error in sidebar (div inside button -> span)
- Improve dashboard chart color consistency (draft status now matches monthly metrics)
- Fix mobile header layout to prevent text squishing (vertical stack on mobile)
- Add IDs to invoice line items for scroll-into-view functionality
- Remove unused `cn` import from theme-selector - Remove unused `Slot`
import from badge - Remove unused `X` icon import from switch - Replace
empty interface extends with type alias in input - Replace empty
interface extends with type alias in textarea - Add "secondary" variant
to button type props - Replace "brand" variant with "default" in
client-list and invoice cards
Bump Next.js from 15.4.5 to 15.5.6 and update related dependencies.
Also upgrade other packages to latest compatible versions including: -
Radix UI components (all minor version updates) - Tiptap editor (3.0.7 →
3.11.0) - React and React DOM (19.1.1 → 19.2.0) - TanStack Query (5.84.0
→ 5.90.10) - TypeScript and ESLint ecosystem - Tailwind CSS (4.1.11 →
4.1.17) - Various other patch and minor updates
Additionally add theme support with next-themes and multiple color
schemes (light, dark, sunset, forest).
- Persist prefersReducedMotion and animationSpeedMultiplier in user
profile - Provide UI controls to toggle reduce motion and adjust
animation speed globally - Centralize animation preferences via provider
and useAnimationPreferences hook - Apply preferences to charts’
animations (duration, enabled/disabled) - Inline script in layout to
apply preferences early and avoid FOUC - Update CSS to respect user
preference with reduced motion overrides and variable animation speeds
The message body wasn't needed since the subject line adequately
describes the changes: refactoring the data export handling into a
separate callback function and fixing extra whitespace in CSS class
names.