Architecture Overview
Monorepo Structure
flowchart LR
subgraph apps["apps/"]
desktop["desktop/<br/>Tauri + Vite + React"]
web["web/<br/>Next.js 14 App Router"]
homepage["homepage/<br/>Next.js 14 Marketing"]
end
subgraph packages["packages/"]
shared["shared/<br/>Types & Utilities"]
api_client["api-client/<br/>Axios Client"]
end
subgraph infrastructure["infrastructure/"]
lib["lib/<br/>CDK Stack"]
lambda["lambda/<br/>7 Lambda Functions"]
scripts_infra["scripts/<br/>Build Scripts"]
end
subgraph scripts["scripts/"]
deploy["deploy.sh"]
end
desktop --> shared & api_client
web --> shared & api_client
api_client --> shared
Apps
| App |
Framework |
Deployment |
Purpose |
desktop |
Tauri + Vite + React 18 |
Tauri package |
Offline-first task tracker with IndexedDB (Dexie.js), Zustand state, bi-directional sync |
web |
Next.js 14 (App Router) |
Cloudflare Pages |
Admin portal for managing tasks, time, customers, billing, integrations |
homepage |
Next.js 14 |
Cloudflare Pages |
Marketing site with contact form for Bytes and Books |
Packages
| Package |
Purpose |
shared |
TypeScript types and utility functions shared across all apps (zero dependencies) |
api-client |
Axios-based HTTP client wrapping all API endpoints |
Infrastructure
| Directory |
Purpose |
lib/task-time-stack.ts |
Single CDK stack defining all AWS resources |
lambda/ |
7 Lambda function directories, each independently bundled |
scripts/build-lambdas.cjs |
esbuild script that bundles each Lambda directory |
Deployment Topology
flowchart TB
subgraph cloudflare["Cloudflare Pages"]
web_cf["Web Portal<br/>(task-and-time-portal)"]
homepage_cf["Homepage<br/>(bytes-and-books-homepage)"]
docs_cf["Documentation<br/>(task-time-docs)"]
end
subgraph aws["AWS (us-east-1)"]
apigw["API Gateway<br/>(REST)"]
cognito["Cognito User Pool<br/>(task-time-users)"]
lambdas["7 Lambda Functions<br/>(Node.js 20.x, 512-1024MB)"]
dynamo["10 DynamoDB Tables<br/>(PAY_PER_REQUEST)"]
ses["SES"]
eventbridge["EventBridge"]
end
subgraph tauri["Tauri"]
desktop_app["Desktop App<br/>(macOS / Windows / Linux)"]
end
subgraph external["External Services"]
xero["Xero Accounting"]
slack["Slack"]
claude["Claude AI (Haiku)"]
sentry["Sentry<br/>(4 projects)"]
end
web_cf & desktop_app -->|HTTPS + JWT| apigw
apigw --> cognito
apigw --> lambdas
lambdas --> dynamo & ses
eventbridge --> lambdas
lambdas --> xero & slack & claude
web_cf & homepage_cf & desktop_app & lambdas --> sentry
Build Pipeline
flowchart LR
A["pnpm test"] --> B["pnpm build<br/>(all packages)"]
B --> C["pnpm build:lambdas"]
C --> D["Sentry Releases<br/>(4 projects)"]
D --> E["Upload Source Maps"]
E --> F["Deploy Web<br/>(Cloudflare Pages)"]
E --> G["Deploy Homepage<br/>(Cloudflare Pages)"]
E --> H["CDK Deploy<br/>(AWS)"]
E --> I["Package Desktop<br/>(Tauri)"]
F & G & H & I --> J["Finalize Sentry"]
The full pipeline runs via pnpm deploy:all which executes scripts/deploy.sh. Individual components can be deployed independently:
- Web:
pnpm build:web && cd apps/web && pnpm deploy
- Homepage:
pnpm build:homepage && cd apps/homepage && pnpm deploy
- Infrastructure:
pnpm build:lambdas && cd infrastructure && pnpm cdk deploy
- Desktop:
pnpm package:desktop
- Docs:
pnpm docs:deploy
Lambda Functions
All Lambdas run Node.js 20.x with 512MB memory (except slack-integration at 1024MB), 30-second timeout, and Sentry error tracking.
| Lambda |
Trigger |
Tables (Write) |
Tables (Read) |
External |
task-sync |
API Gateway |
tasks |
— |
Cognito |
time-entry-sync |
API Gateway |
time-entries, time-bills, pillars |
tasks, customers, customer-users, xero-tokens |
Xero |
customer-sync |
API Gateway |
customers, customer-users, pillars, customer-focus, time-bills, time-entries, tasks |
— |
Cognito, SES |
status-check |
EventBridge |
tasks |
— |
— |
active-timer-sync |
API Gateway |
active-timers |
— |
— |
xero-sync |
API Gateway |
xero-tokens |
— |
Xero |
slack-integration |
API Gateway (Slack) |
tasks, slack-channel-mappings |
customers, pillars |
Slack, Claude AI, Cognito |
Key Patterns
- Enrichment: Time entries and bills support
?enrich=true to include related task, customer, user, and pillar names
- TimeBill auto-generation: Created when timer stops; groups by (pillar, customer, day); rounds up to nearest 15 minutes
- Xero sync: Non-blocking; approved bills → Xero time entries; rate hierarchy: pillar > customer > project
- Slack task creation: Slash command or message action → Claude Haiku title → modal → task (status: intake)
- Status auto-transitions: EventBridge-triggered Lambda checks
exploded/blocked tasks and transitions when conditions met