- TypeScript 97.3%
- JavaScript 1.4%
- Shell 0.8%
- CSS 0.2%
- Dockerfile 0.2%
- Other 0.1%
| .claude | ||
| apps | ||
| beenvoice.icon | ||
| packages | ||
| scripts | ||
| .dockerignore | ||
| .gitignore | ||
| AGENTS.md | ||
| bun.lock | ||
| docker-compose.coolify-garage.yml | ||
| docker-compose.coolify.yml | ||
| docker-compose.dev.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| LICENSE | ||
| package.json | ||
| README.md | ||
| tsconfig.base.json | ||
| turbo.json | ||
beenvoice
Beenvoice is a freelancer and small-business invoicing platform with a Next.js web application/API and an Expo mobile companion. The repository is a Bun workspace orchestrated by Turborepo.
Workspace map
beenvoice/
├── apps/
│ ├── web/ # Next.js dashboard, tRPC API, PostgreSQL/Drizzle
│ ├── mobile/ # Expo Router mobile app and iOS widgets
│ └── worker/ # PostgreSQL-backed scheduler and background jobs
├── packages/
│ ├── domain/ # Platform-neutral shared rules and parsing
│ └── email/ # Resend and SMTP/Mailpit delivery adapter
├── Dockerfile
├── docker-compose*.yml
├── package.json
└── turbo.json
The mobile app consumes the same tRPC API and Better Auth sessions as the web app. It imports the server router type at compile time, while runtime-safe shared behavior lives in @beenvoice/domain.
Quick start
bun install
cp apps/web/.env.example apps/web/.env.local
cp apps/mobile/.env.example apps/mobile/.env
bun run --filter @beenvoice/web docker:up
bun run --filter @beenvoice/web db:push
bun run dev
bun run dev starts Next.js on port 3000, Expo Metro on port 8082, and the background worker. For a physical iPhone, set EXPO_PUBLIC_API_URL in apps/mobile/.env to a host the device can reach and configure the web app's canonical/auth URLs consistently.
Useful workspace commands:
bun run typecheck
bun run lint
bun run test
bun run build
bun run check
bun run email:preview # sends a PDF-bearing message to local Mailpit
Run an app-specific command with a workspace filter:
bun run --filter @beenvoice/web db:migrate
bun run --filter @beenvoice/mobile ios
bun run --filter @beenvoice/mobile ios:release:upload
Production Docker deployment
Keep production web configuration in apps/web/.env, then run from the repository root:
git pull
./scripts/docker-deploy.sh
The root Dockerfile installs the frozen Bun workspace lockfile and exposes separate final (web) and worker targets. The Compose stack starts both; the web container runs migrations before serving requests and the worker tolerates that short startup race.
/api/health keeps its database readiness check (200 when ready, 503 otherwise)
and includes build.version from the web package and build.commit captured by
Next during compilation. docker-deploy.sh passes the full checkout revision as
BUILD_COMMIT; manual Docker or Gitea builds should pass
--build-arg BUILD_COMMIT=<full 40-character SHA>. Coolify's SOURCE_COMMIT build
argument is also accepted and forwarded by the production Compose files.
No Gitea Actions workflow is configured in this repository.
Only valid full SHAs are published, with explicit BUILD_COMMIT taking precedence
over SOURCE_COMMIT. A production build without one reports unknown; development
reports dev. Runtime environment variables and later checkout changes cannot
relabel the compiled release. The SHA identifies the source revision, not whether
the build checkout was clean. The response exposes no other configuration.
Run bun run --filter @beenvoice/web test:health for readiness and identity
regressions. For a production standalone smoke artifact, set BUILD_STANDALONE=1
and BUILD_COMMIT during bun run --filter @beenvoice/web build, then run
bun run --filter @beenvoice/web test:health:standalone <version> <commit>.
The smoke check copies the artifact outside the checkout, overrides all runtime
identity inputs, uses an unreachable local fixture database, and stops the server.
The optional standalone artifact does not change the normal Docker release layout.
Documentation
- Web setup
- Web architecture
- Mobile setup
- Mobile architecture
- Worker architecture
- Shared domain package
- Email delivery package
Product concepts
- Clients with optional default hourly rates
- Businesses and sender branding
- Draft, sent, paid, and overdue invoices
- Time tracking and invoice attachment
- Recurring invoices, expenses, payments, and templates
- Public invoice links and API-key-authenticated automation