soconnor 480c50981d Unify entities navigation, redesign time clock, and add invoice PDF preview.
Combine clients and businesses under entities, polish the web time clock,
and show live invoice PDF preview with tighter line-item editing.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 01:08:23 -04:00
2026-06-11 12:01:19 -04:00

beenvoice Logo

beenvoice — Invoicing Made Simple

Modern invoicing for freelancers and small businesses: clients, businesses, invoices, time tracking, expenses, recurring billing, PDF/email delivery, and optional SSO.

Architecture (dense): docs/ARCHITECTURE.md
Mobile companion: ../beenvoice-app/README.md

Stack at a glance

Layer Tech
App Next.js 16 App Router, React 19
API tRPC 11 + SuperJSON
DB PostgreSQL, Drizzle ORM
Auth better-auth (email/password, Authentik OIDC, Expo mobile)
UI shadcn/ui, Tailwind v4
Email / PDF Resend, @react-pdf/renderer
Package manager Bun

Features

  • 🔐 Authentication — better-auth: email/password, password reset, optional Authentik OIDC, Expo mobile sessions
  • ⏱ Time clock — running timer, one per user; clock-out can append invoice line items
  • 🤖 MCP API/api/mcp for automation via API keys (bv_…)
  • 👥 Client Management - Create, edit, and manage client information
  • 🏢 Business Profiles - Manage your business details, logo, and email settings
  • 📄 Professional Invoices - Generate detailed invoices with line items
  • 📅 Timesheet View - Calendar-based time entry with month and week views
  • 📧 Email Delivery - Send invoices via email using Resend
  • 📥 PDF Export - Download invoices as professional PDFs
  • 📊 CSV Import - Bulk import invoice data from CSV files
  • 💰 Flexible Pricing - Set custom rates and calculate totals automatically
  • 📱 Responsive Design - Works seamlessly on desktop, tablet, and mobile
  • 🎨 Modern UI - Clean, professional interface built with shadcn/ui
  • Type-Safe - Full TypeScript support with tRPC for API calls
  • 💾 PostgreSQL Database - Robust relational database with Drizzle ORM

🚀 Tech Stack

  • Frontend: Next.js 16 with App Router
  • Backend: tRPC for type-safe API calls
  • Database: Drizzle ORM with PostgreSQL
  • Authentication: better-auth with email/password and Authentik OIDC SSO
  • UI Components: shadcn/ui with Tailwind CSS v4
  • Email: Resend for transactional email delivery
  • PDF: @react-pdf/renderer for invoice PDF generation
  • Package Manager: Bun

📦 Installation

Prerequisites

  • Node.js 18+ or Bun
  • Docker & Docker Compose (for local PostgreSQL)
  • Git

Quick Start

  1. Clone the repository

    git clone https://github.com/yourusername/beenvoice.git
    cd beenvoice
    
  2. Install dependencies

    bun install
    
  3. Set up environment variables

    cp .env.example .env.local
    

    Edit .env.local and add your configuration:

    # Database
    DATABASE_URL="postgresql://postgres:password@localhost:5432/beenvoice"
    DB_DISABLE_SSL="true"
    
    # Authentication
    AUTH_SECRET="your-secret-key-here"
    BETTER_AUTH_URL="http://localhost:3000"
    
    # Application
    NEXT_PUBLIC_APP_URL="http://localhost:3000"
    NODE_ENV="development"
    
    # Email (optional for local dev)
    RESEND_API_KEY="your-resend-api-key"
    RESEND_DOMAIN="yourdomain.com"
    
  4. Start the development database

    docker compose -f docker-compose.dev.yml up -d db
    
  5. Push the database schema

    bun run db:push
    
  6. Start the development server

    bun run dev
    
  7. Open your browser Navigate to http://localhost:3000

🏗️ Project structure

See docs/ARCHITECTURE.md for routers, schema, auth, and MCP.

beenvoice/
├── src/app/           # Pages + /api (auth, trpc, mcp, cron, public PDF)
├── src/server/api/    # tRPC routers
├── src/server/db/     # Drizzle schema + pool
├── src/components/    # UI + domain components
├── src/lib/           # auth, PDF, email, branding
├── drizzle/           # SQL migrations
└── docs/              # Architecture + UI guides

🎯 Usage

Getting Started

  1. Register an Account

    • Visit the sign-up page
    • Enter your name, email, and password
  2. Set Up Your Business

    • Navigate to Business Settings
    • Add your business name, contact info, and logo
    • Configure email settings for invoice delivery (Resend API key + domain)
  3. Add Your First Client

    • Navigate to the Clients page
    • Click "Add New Client"
    • Fill in client details (name, email, phone, address)
  4. Create an Invoice

    • Go to the Invoices page
    • Click "Create New Invoice"
    • Select a client and optionally a business profile
    • Add line items with descriptions, dates, hours, and rates
    • Use the Timesheet tab for calendar-based time entry
    • Save and send or download as PDF

Features Overview

Client Management

  • Create and edit client profiles
  • Store contact information and addresses
  • Set default hourly rates per client
  • Search and filter client list

Invoice Creation

  • Select from existing clients and business profiles
  • Add multiple line items with drag-and-drop reordering
  • Set custom rates per item
  • Automatic total calculations with configurable tax rate
  • Timesheet calendar view for date-based time tracking
  • Professional invoice formatting

Invoice Delivery

  • Send invoices via email directly from the app
  • Rich text email composer with preview
  • Resend and re-deliver sent invoices
  • Track invoice status: Draft → Sent → Paid (+ Overdue)

User Interface

  • Clean, modern design
  • Fully responsive — desktop, tablet, and mobile
  • Intuitive navigation with breadcrumbs
  • Toast notifications for feedback
  • Dark mode support

🔧 Development

Available Scripts

# Development
bun run dev          # Start development server (Turbo)
bun run build        # Build for production
bun run start        # Start production server

# Database
bun run db:push      # Push schema changes to database
bun run db:migrate   # Run migrations
bun run db:studio    # Open Drizzle Studio
bun run db:generate  # Generate new migration

# Docker
bun run docker:up    # Start deployment compose stack
bun run docker:dev:up # Start development compose stack with exposed PostgreSQL
bun run docker:down  # Stop Docker services

# Code Quality
bun run lint         # Run ESLint
bun run lint:fix     # Fix ESLint issues
bun run format:write # Format code with Prettier
bun run typecheck    # Run TypeScript type checking

Docker Compose

Use the base compose file for deployment. It keeps PostgreSQL internal to the compose network:

docker compose up -d

For local development, use the dev compose file to expose PostgreSQL on ${POSTGRES_PORT:-5432}:

docker compose -f docker-compose.dev.yml up -d

Set DISABLE_SIGNUPS=true to block new email/password account registration.

Database Schema

The application uses the following core tables:

  • users - User accounts and authentication
  • sessions - Active user sessions
  • clients - Client information and contact details
  • businesses - Business profiles with email/logo settings
  • invoices - Invoice headers with client and business relationships
  • invoice_items - Individual line items with pricing and position ordering

API surface

  • tRPC/api/trpc — primary API for web and mobile (session cookies)
  • MCP/api/mcp — JSON-RPC tools for integrations (API key only)
  • REST auth/api/auth/register, forgot/reset password (mobile + custom flows)
  • Public/i/[token], /api/i/[token]/pdf

All business logic lives in src/server/api/routers/. Input validation via Zod.

🎨 Customization

Styling

The app uses Tailwind CSS v4 with a custom design system:

  • Primary Color: Green (#16a34a)
  • Font: Geist for professional typography
  • Components: shadcn/ui component library
  • Spacing: 4px grid system

Branding

Update the logo and colors in:

  • src/components/logo.tsx - Main logo component
  • src/styles/globals.css - Color variables
  • src/app/layout.tsx - Font configuration

🚀 Deployment

You can deploy this application to any platform that supports Next.js and PostgreSQL (Docker, Coolify, Railway, etc.).

  1. Build the application:

    bun run build
    
  2. Set up production environment variables (see .env.local example above, adjusting URLs and secrets for production)

  3. Run database migrations:

    bun run db:push
    
  4. Start the server:

    bun start
    

Environment Variables

Required for production:

DATABASE_URL="postgresql://user:password@host:5432/dbname"
AUTH_SECRET="your-long-random-secret"
BETTER_AUTH_URL="https://your-domain.com"
NEXT_PUBLIC_APP_URL="https://your-domain.com"
NODE_ENV="production"

# Email (required for invoice sending)
RESEND_API_KEY="re_xxxxxxxxxxxx"
RESEND_DOMAIN="yourdomain.com"

# Optional: Authentik SSO
AUTHENTIK_ISSUER="https://your-authentik-instance/application/o/beenvoice/"
AUTHENTIK_CLIENT_ID="your-client-id"
AUTHENTIK_CLIENT_SECRET="your-client-secret"

Other Platforms

The app can be deployed to any platform that supports Next.js:

  • Coolify: Deploy with Docker Compose support
  • Railway: Connect your GitHub repository (includes managed PostgreSQL)
  • DigitalOcean App Platform: Deploy with automatic scaling

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Development Guidelines

  • Follow TypeScript best practices
  • Use shadcn/ui components for consistency
  • Implement proper error handling
  • Follow the existing code style (Prettier + ESLint configs provided)

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

📞 Support


Built for freelancers and small businesses who deserve better invoicing tools.

S
Description
beenvoice web app (Next.js)
Readme 3.1 MiB
Languages
TypeScript 97.4%
CSS 1.7%
JavaScript 0.5%
Shell 0.3%