Modular, personal life dashboard. The shell is the product. Modules plug into it.
V1 is a web-only, single-user personal tool. The architecture is shell-first: Home aggregates widgets from each module, Inbox is universal capture, ⌘K searches across modules, and every module is a pluggable app behind a contract.
V1 status (2026-07-27)
| Modules in V1 | Thoughts, Tasks, Money, Calendar, Goals, GitHub, File Board, Mood (8, fully working) |
| Money sub-modules | Subscriptions (Netflix, Cursor, etc., with monthly equivalent projection) |
| Cross-module links | ✅ tasks ↔ thoughts (the magic) |
| Code splitting | ✅ initial bundle 76KB gzipped (modules lazy-loaded) |
| ⌘K search | ✅ cross-module (incl. GitHub PRs, File Boards) |
| Theme | ✅ Light / Dark / System (persisted) |
| Settings | ✅ theme, modules list, GitHub PAT (encrypted), export |
| AI | 🔜 V2 (data model is AI-ready) |
| Mobile | 🔜 V2 |
| Sync / offline | 🔜 V2 |
| Auth | ✅ email + password + 6-digit PIN, bootstrap installer pattern, server-side sessions |
| Deploy | 🟡 railway.json + Vercel config in docs |
| Cost | ~$7/mo (Railway Postgres + app) |
Architecture: shell-first
LifeBoard (monorepo pnpm)
├── apps/
│ ├── web/ Vite + React + Tailwind + TanStack Query + TipTap
│ │ ├── src/shell/ ← the PRODUCT
│ │ │ ├── ShellLayout sidebar + main + ⌘K
│ │ │ ├── Sidebar Home, Inbox, modules
│ │ │ ├── HomeView aggregates module widgets
│ │ │ ├── InboxView universal capture
│ │ │ ├── CommandPalette ⌘K search
│ │ │ ├── SettingsView theme, modules, GitHub PAT, data
│ │ │ └── theme.ts zustand + localStorage
│ │ ├── src/modules/ ← PLUGGABLE
│ │ │ ├── registry.ts MODULES array (single source of truth)
│ │ │ ├── thoughts/ View + HomeWidget + search
│ │ │ ├── tasks/ View + HomeWidget + search
│ │ │ ├── money/ View + HomeWidget + SubscriptionsManager
│ │ │ ├── calendar/ View + HomeWidget + search
│ │ │ ├── goals/ View + HomeWidget + search
│ │ │ ├── github/ View + HomeWidget + PAT connect + sync
│ │ │ ├── fileboard/ View + HomeWidget + upload
│ │ │ └── mood/ View + HomeWidget + daily check-in
│ │ ├── src/lib/
│ │ │ ├── module.ts LifeBoardModule contract
│ │ │ └── links.ts cross-module links API
│ │ └── src/components/ shared UI (shadcn-style)
│ └── api/ Hono + Drizzle + Postgres
│ ├── src/index.ts REST endpoints
│ ├── src/money.ts Money module service
│ ├── src/subscriptions.ts charge projection (pure fn)
│ ├── src/github.ts GitHub sync + cache
│ ├── src/fileStorage.ts local blob storage (V1)
│ ├── src/crypto.ts AES-256-GCM seal/open (PAT)
│ └── src/links.ts cross-module links resolver
├── packages/
│ └── db/ Drizzle schema + client (shared)
└── docs/ 25+ design files
Module contract
Every module exports a LifeBoardModule (from apps/web/src/lib/module.ts):
interface LifeBoardModule {
id: string;
name: string;
description: string;
icon: LucideIcon;
version: string;
enabled: boolean;
path: string;
loadView: () => Promise<{ default: ComponentType<ModuleViewProps> }>;
HomeWidget: ComponentType<ModuleHomeWidgetProps>;
search?: (query: string) => Promise<ModuleSearchResult[]>;
}To add a new module:
- Create
apps/web/src/modules/<name>/with aViewand aHomeWidget - Append to
MODULESinregistry.ts
The shell picks it up automatically: sidebar item, home widget, search provider.
Quick start
# 1. Install
pnpm install
# 2. Postgres (Docker)
docker run -d --name lifeboard-pg -p 5432:5432 \
-e POSTGRES_PASSWORD=local -e POSTGRES_USER=local -e POSTGRES_DB=lifeboard \
postgres:16
# 3. Set required env vars
cat >> apps/api/.env <<'EOF'
DATABASE_URL=postgresql://local:local@localhost:5432/lifeboard
LIFEBOARD_SECRET_KEY=$(openssl rand -base64 32)
# Optional in dev; required in production.
# LIFEBOARD_BOOTSTRAP_TOKEN=$(openssl rand -hex 32)
EOF
# 4. Push schema
pnpm --filter @lifeboard/db db:push
# 5. Run
pnpm dev
# web: http://localhost:5173
# api: http://localhost:3000
# 6. First-run setup
# Open http://localhost:5173 — the web app detects an empty users table
# and shows the Setup form. In dev you can skip the bootstrap token;
# in production set LIFEBOARD_BOOTSTRAP_TOKEN and pass it in the form.Scripts
| Script | What |
|---|---|
pnpm dev |
Run web + api in parallel |
pnpm dev:web |
Web only (http://localhost:5173) |
pnpm dev:api |
API only (http://localhost:3000) |
pnpm typecheck |
TS check across all packages |
pnpm build |
Build all apps |
pnpm build:web |
Web only |
pnpm --filter @lifeboard/db db:push |
Push Drizzle schema to Postgres |
Bundle sizes (gzipped)
| Chunk | Size |
|---|---|
| main (shell + chrome) | 76 KB |
| ThoughtsView (with TipTap) | 96 KB |
| MoneyView | 2 KB |
| TasksView | 2 KB |
| LinkPicker | 2 KB |
Initial page load: ~76 KB gzipped (excluding the lazy module chunks). TipTap is only loaded when the user opens the Thoughts module.
What's NOT in V1 (deferred to V2+)
- AI features (no assistant, no brief, no review)
- Mobile (iOS / Android)
- Desktop wrapper
- Sync / multi-device
- Offline / IndexedDB
- Email-to-inbox
- Voice memos
- Browser extension
- Real Clerk auth (dev-mode shim today) — ✅ done; email + password + 6-digit PIN, no external provider
- Real Railway deploy (config in place, deploy not run)
- Multi-currency
- Plaid / Open Finance
- Per-module disable in Settings
- Public API / webhooks
Read order (docs/)
- Product Vision — north star
- Module Catalog — every module, with V1/V2 status
- MVP Roadmap — V1 scope, 2-4 week plan
- Architecture — V1 stack
- Information Architecture — V1 surface
- Data Model — V1 schema
Owner
Luciano lucianodiisouza@hotmail.com. Builds this for personal use. Will share when (if) the tool proves its worth.