- 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
The previous baseline blindly recorded all migrations as applied.
Now on startup the script validates every recorded migration against
the actual schema; any entry whose schema changes don't exist is
deleted so migrate() will re-run that migration.
This unblocks the existing deployment where 0001 was recorded as done
but beenvoice_client.currency was never actually added.
https://claude.ai/code/session_012sqEgNQpx676isepeoX4Mi
Previously the baseline marked ALL migrations as done, causing 0001 to
be skipped even on databases that didn't have the currency column yet.
Now each migration is checked against a sentinel column/table before
being seeded into the tracking table. Migrations whose changes don't
exist yet are left out so migrate() runs them normally.
https://claude.ai/code/session_012sqEgNQpx676isepeoX4Mi
When switching from db:push to db:migrate on an existing database,
the migration table is empty so Drizzle tries to re-run all migrations,
failing with "relation already exists".
Detect this case (tables exist but no migration history) and seed the
__drizzle_migrations tracking table with all current migrations so
Drizzle treats them as already applied. Future migrations run normally.
https://claude.ai/code/session_012sqEgNQpx676isepeoX4Mi
- Remove drizzle/*.sql and drizzle/*-journal from .dockerignore so
migration files are included in the Docker build context
- Restore next/font/google imports (removed prematurely due to local
IP being 403'd by Google Fonts; production builds should work fine)
- Update CSS font fallbacks to use proper system font stacks
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
- Add cache invalidation after invoice create/update mutations
- Properly invalidate both getById and getAll queries
- Prevents stale data from being displayed after saving
- Fixes flaky behavior where updates didn't appear immediately
- 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 unused imports from invoice-form.tsx, sidebar.tsx, dashboard-shell.tsx
- Remove unused imports from dashboard.ts and calendar.tsx
- Fix unused parameter in invoice-calendar-view.tsx with underscore prefix
- Fix type-only import for DayButton in calendar.tsx
- All typecheck errors resolved
- Remaining lint errors are in unmodified files (pre-existing)
- 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).