beenvoice | invoicing made simple https://beenvoice.app
  • TypeScript 97.3%
  • JavaScript 1.4%
  • Shell 0.8%
  • CSS 0.2%
  • Dockerfile 0.2%
  • Other 0.1%
Find a file
2026-10-11 02:41:41 -04:00
.claude Convert Beenvoice to a Turborepo monorepo 2026-08-16 22:13:42 -04:00
apps Expose immutable build identity in health responses 2026-10-11 02:41:41 -04:00
beenvoice.icon Initialize Beenvoice workspace 2026-08-16 21:42:57 -04:00
packages Expose immutable build identity in health responses 2026-10-11 02:41:41 -04:00
scripts Expose immutable build identity in health responses 2026-10-11 02:41:41 -04:00
.dockerignore Convert Beenvoice to a Turborepo monorepo 2026-08-16 22:13:42 -04:00
.gitignore Initialize Beenvoice workspace 2026-08-16 21:42:57 -04:00
AGENTS.md Convert Beenvoice to a Turborepo monorepo 2026-08-16 22:13:42 -04:00
bun.lock Replace custom MCP OAuth with Better Auth provider 2026-10-07 17:51:55 -04:00
docker-compose.coolify-garage.yml Make Coolify service ports configurable 2026-08-17 01:14:39 -04:00
docker-compose.coolify.yml Expose immutable build identity in health responses 2026-10-11 02:41:41 -04:00
docker-compose.dev.yml Make scheduling and dates timezone-safe 2026-08-17 18:15:39 -04:00
docker-compose.yml Expose immutable build identity in health responses 2026-10-11 02:41:41 -04:00
Dockerfile Expose immutable build identity in health responses 2026-10-11 02:41:41 -04:00
LICENSE Convert Beenvoice to a Turborepo monorepo 2026-08-16 22:13:42 -04:00
package.json Add Mailpit email transport 2026-08-17 16:35:14 -04:00
README.md Expose immutable build identity in health responses 2026-10-11 02:41:41 -04:00
tsconfig.base.json Convert Beenvoice to a Turborepo monorepo 2026-08-16 22:13:42 -04:00
turbo.json Expose immutable build identity in health responses 2026-10-11 02:41:41 -04:00

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

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