From 068a51b46bae27cd8b9890b9ccb365115e0adf6b Mon Sep 17 00:00:00 2001 From: Sean O'Connor Date: Sun, 16 Aug 2026 21:42:57 -0400 Subject: [PATCH] Initialize Beenvoice workspace --- .claude/launch.json | 11 ++++ .gitignore | 19 ++++++ README.md | 95 +++++++++++++++++++++++++++++ beenvoice.icon/Assets/beenvoice.svg | 11 ++++ beenvoice.icon/icon.json | 66 ++++++++++++++++++++ 5 files changed, 202 insertions(+) create mode 100644 .claude/launch.json create mode 100644 .gitignore create mode 100644 README.md create mode 100644 beenvoice.icon/Assets/beenvoice.svg create mode 100644 beenvoice.icon/icon.json diff --git a/.claude/launch.json b/.claude/launch.json new file mode 100644 index 0000000..fa49961 --- /dev/null +++ b/.claude/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.0.1", + "configurations": [ + { + "name": "beenvoice-web-dev", + "runtimeExecutable": "bash", + "runtimeArgs": ["-c", "cd beenvoice-web && PORT=3010 bun run dev"], + "port": 3010 + } + ] +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..945c5fb --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +node_modules/ +.turbo/ +.next/ +.expo/ +dist/ +coverage/ + +.env +.env.* +!.env.example +!.env.*.example +.ios-release.env + +ios/ +android/ +*.tsbuildinfo +*.log +.DS_Store + diff --git a/README.md b/README.md new file mode 100644 index 0000000..71dc3f0 --- /dev/null +++ b/README.md @@ -0,0 +1,95 @@ +# beenvoice workspace + +Local development layout for the **beenvoice** product: a freelancer/small-business invoicing platform with a Next.js web app and an Expo mobile companion. + +``` +beenvoice-meta/ +├── beenvoice-web/ # Web API + dashboard (Next.js 16, tRPC, PostgreSQL) +├── beenvoice-app/ # Mobile app (Expo, React Native, dev client) +└── beenvoice.icon/ # iOS app icon asset (icon composer) +``` + +Each subdirectory is its own git repository. This folder is a convenience layout for working on both clients against one API. + +| Repo | Remote | +|------|--------| +| Web | [git.soconnor.dev/soconnor/beenvoice-web](https://git.soconnor.dev/soconnor/beenvoice-web) | +| Mobile | [git.soconnor.dev/soconnor/beenvoice-app](https://git.soconnor.dev/soconnor/beenvoice-app) | + +## Quick start (full stack) + +```bash +# 1. API + database +cd beenvoice-web +cp .env.example .env.local # edit DATABASE_URL, AUTH_SECRET, etc. +docker compose -f docker-compose.dev.yml up -d +bun install && bun run db:push +bun run dev # http://localhost:3000 + +# 2. Mobile (simulator) +cd ../beenvoice-app +cp .env.example .env # EXPO_PUBLIC_API_URL=http://localhost:3000 +bun install +bun run ios # Metro on :8082, native dev build +``` + +Physical iPhone: set `EXPO_PUBLIC_API_URL` to your Mac's LAN IP; ensure `beenvoice-web` has `BETTER_AUTH_URL` matching a host the device can reach (trusted origins are derived from `BETTER_AUTH_URL` / `NEXT_PUBLIC_APP_URL`). + +## Production deploy (Docker) + +From `beenvoice-web` with `.env` configured (see [beenvoice-web/README.md](./beenvoice-web/README.md#docker-deployment-app--database)): + +```bash +cd beenvoice-web +git pull +./scripts/docker-deploy.sh # rebuild app image + restart (not docker-compose.dev.yml) +``` + +Plain `docker compose up -d` without `--build` reuses the existing local image and will not pick up code from `git pull`. + +## How the pieces connect + +| Layer | Repo | Transport | Auth | +|-------|------|-----------|------| +| Web UI | `beenvoice-web` | tRPC `/api/trpc` (cookies) | better-auth session | +| Mobile UI | `beenvoice-app` | tRPC `/api/trpc` (cookie header) | better-auth + `@better-auth/expo` → SecureStore | +| Automation | `beenvoice-web` MCP `/api/mcp` | JSON-RPC | API key (`bv_…`) only | +| Public invoices | `beenvoice-web` `/i/[token]` | HTTP | unauthenticated token | + +Mobile imports **tRPC router types** from `beenvoice-web/src/server/api/root` via `tsconfig` path mapping — keep API changes type-checked in both repos. + +## Documentation map + +| Doc | Contents | +|-----|----------| +| [beenvoice-web/README.md](./beenvoice-web/README.md) | Web setup, Docker deploy, scripts | +| [beenvoice-web/docs/ARCHITECTURE.md](./beenvoice-web/docs/ARCHITECTURE.md) | Server architecture (dense) | +| [beenvoice-app/README.md](./beenvoice-app/README.md) | Mobile setup, troubleshooting | +| [beenvoice-app/docs/ARCHITECTURE.md](./beenvoice-app/docs/ARCHITECTURE.md) | Mobile architecture (dense) | +| [beenvoice-web/docs/](./beenvoice-web/docs/) | UI guides (forms, tables, breadcrumbs, email) | + +## Shared domain concepts + +- **Clients** — billable contacts with optional default hourly rate +- **Businesses** — sender profiles (logo, address, Resend email config) +- **Invoices** — draft → sent → paid; line items; PDF + email; public share token +- **Time entries** — clock in/out; one running timer per user; auto-attach to open invoice +- **Recurring invoices**, **expenses**, **payments**, **templates** — full web support; mobile covers a core CRUD subset + +## Environment cheat sheet + +| Variable | Where | Purpose | +|----------|-------|---------| +| `DATABASE_URL` | beenvoice-web | PostgreSQL | +| `AUTH_SECRET`, `BETTER_AUTH_URL` | beenvoice-web | better-auth | +| `EXPO_PUBLIC_API_URL` | beenvoice-app | API base for mobile | +| `DISABLE_SIGNUPS` | beenvoice-web | `true` blocks new registrations | +| `RESEND_*` | beenvoice-web | Invoice / reset email | + +## Ports + +| Service | Default port | +|---------|----------------| +| Next.js (beenvoice-web) | 3000 | +| Postgres (dev compose) | 5432 | +| Metro (beenvoice-app) | **8082** (intentionally not 8081) | diff --git a/beenvoice.icon/Assets/beenvoice.svg b/beenvoice.icon/Assets/beenvoice.svg new file mode 100644 index 0000000..5db0afe --- /dev/null +++ b/beenvoice.icon/Assets/beenvoice.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/beenvoice.icon/icon.json b/beenvoice.icon/icon.json new file mode 100644 index 0000000..ec0270e --- /dev/null +++ b/beenvoice.icon/icon.json @@ -0,0 +1,66 @@ +{ + "fill" : { + "automatic-gradient" : "gray:0.75000,1.00000", + "orientation" : { + "start" : { + "x" : 0.5, + "y" : 0 + }, + "stop" : { + "x" : 0.5, + "y" : 0.7 + } + } + }, + "groups" : [ + { + "layers" : [ + { + "fill-specializations" : [ + { + "value" : { + "solid" : "extended-gray:0.00000,1.00000" + } + }, + { + "appearance" : "dark", + "value" : { + "solid" : "extended-gray:1.00000,1.00000" + } + }, + { + "appearance" : "tinted", + "value" : { + "solid" : "extended-gray:0.50000,1.00000" + } + } + ], + "glass" : true, + "image-name" : "beenvoice.svg", + "name" : "beenvoice", + "position" : { + "scale" : 1.85, + "translation-in-points" : [ + 0, + 0 + ] + } + } + ], + "shadow" : { + "kind" : "neutral", + "opacity" : 0.5 + }, + "translucency" : { + "enabled" : true, + "value" : 0.5 + } + } + ], + "supported-platforms" : { + "circles" : [ + "watchOS" + ], + "squares" : "shared" + } +} \ No newline at end of file