Tech Stack¶
Meister Bill is built with modern, performance-oriented technologies across all layers.
Overview¶
| Layer | Technology |
|---|---|
| Frontend | Nuxt 4 + Tailwind CSS 4 + DaisyUI 5 |
| Backend/API | Hono on Node.js 24 (Docker image) |
| Shared Types | Zod v4 schemas |
| Package Mgmt | pnpm with workspaces |
| Database | PostgreSQL 18 (Docker locally, hoststack.dev staging/prod) |
| ORM | Prisma 7 |
| Auth | Better Auth (JWT + passkeys) |
| CI/CD | Gitea with act_runner |
Frontend Technologies¶
Nuxt 4¶
- Purpose: Web application framework
- Features: SSR/SSG support, auto-imports, file-based routing
- Location:
apps/web/
Tailwind CSS 4 + DaisyUI 5¶
- Purpose: Utility-first CSS framework with component library
- Features: Responsive design, dark mode, customizable themes
Vue 3¶
- Purpose: Reactive frontend framework
- Features: Composition API, TypeScript support,
<script setup>
Backend Technologies¶
Hono¶
- Purpose: Lightweight web framework
- Features: Fast routing, middleware support, OpenAPI integration
- Location:
apps/api/
Node.js 24 (Docker)¶
- Purpose: Server runtime
- Features: native fetch, native crypto, native test runner
- Deploy: Multi-stage Dockerfile at
apps/api/Dockerfile, image runsnode dist/index.js - Locally:
pnpm --filter @meisterbill/api devwith hot reload
Validation & Type Safety¶
Zod v4¶
- Purpose: Runtime type validation and schema definitions
- Features: TypeScript inference, composable schemas, custom validations
- Location:
schemas/(workspace package) - See: Schema Validation Guide
Database¶
PostgreSQL 18¶
- Purpose: Primary data store
- Features: JSONB support, full-text search, complex queries
- Access: via Prisma 7 (
apps/api/src/db/client.ts) - Schema:
apps/api/prisma/schema.prismais the single source of truth; migrations inapps/api/prisma/migrations/
Prisma 7¶
- Purpose: ORM with auto-generated types from the schema
- Driver adapter:
@prisma/adapter-pgoverpg - Generated client:
apps/api/src/generated/(regenerable viapnpm --filter @meisterbill/api prisma generate)
Authentication¶
Better Auth¶
- Purpose: Email+password auth, JWT issuance, passkey WebAuthn
- Plugins:
jwt(1h access tokens),passkey(@better-auth/passkey) - Client-side:
@simplewebauthn/browserwraps the native WebAuthn API - Verification: JWTs verified locally in API middleware (no DB round-trip per request)
Package Management¶
pnpm Workspaces¶
- Purpose: Monorepo management
- Features: Efficient disk usage, fast installs, workspace protocol
- Configuration:
pnpm-workspace.yaml
Testing Frameworks¶
Vitest¶
- Purpose: Unit testing for frontend
- Used In:
apps/web/,schemas/ - Features: Fast, Vite-native, Jest-compatible API
Jest¶
- Purpose: Unit testing for backend
- Used In:
apps/api/ - Features: Mature, extensive ecosystem, snapshot testing
Playwright¶
- Purpose: End-to-end testing
- Features: Cross-browser support, auto-waiting, trace viewer
State Management¶
XState V5¶
- Purpose: State machine for complex workflows
- Used For: Invoice status, project status, payment workflows
- Benefits: Predictable state transitions, prevents invalid states
Development Tools¶
mise¶
- Purpose: Runtime version management
- Manages: Node.js version (24+)
TypeScript¶
- Purpose: Type-safe JavaScript
- Configuration: Per-workspace
tsconfig.jsonfiles
CI/CD¶
Gitea + act_runner¶
- Purpose: Continuous integration and deployment
- Features: Self-hosted, Docker-based jobs, GitHub Actions compatible
- Configuration:
.gitea/workflows/
Deployment Platform¶
Cloudflare Workers (API)¶
- Purpose: API hosting on edge
- Features: Zero cold starts, 300+ edge locations, auto-scaling
- Environments:
meisterbill-api(production),meisterbill-api-staging(staging) - Config:
apps/api/wrangler.jsonc
Cloudflare Pages (Web)¶
- Purpose: Web application hosting (static + SSR via Functions)
- Features: Global CDN, automatic HTTPS, edge rendering
- Project:
meisterbill-web - Config:
apps/web/wrangler.toml
Additional Services¶
Mailpit (Development)¶
- Purpose: Local email testing
- Interface: http://localhost:8026/
- Use: Testing invoice emails and auth flows
Cloudflare Browser Rendering (PDF Generation)¶
- Purpose: HTML to PDF conversion
- Features: Puppeteer API via Cloudflare Workers
- Use: Generating invoice PDFs (replaces Gotenberg)
- Cost: $0.50 per 1000 renders
Umami Analytics¶
- Purpose: Privacy-friendly web analytics
- Features: GDPR-compliant, self-hosted, no cookies
Performance Optimizations¶
Frontend Bundle Optimization¶
The web application is optimized for fast initial load and Core Web Vitals:
| Optimization | Implementation | Benefit |
|---|---|---|
| Content-Based Chunk Naming | Hash-based filenames for long-term caching | Better caching, CDN optimization |
| CSS Code Splitting | Per-component CSS extraction | Smaller initial CSS payload |
| Terser Minification | Console/debugger removal in production | Smaller bundle size |
| Component Lazy Loading | Lazy prefix for heavy modals |
Load components on-demand |
| Route Rules | Aggressive caching for static pages | Instant repeat visits |
Configuration Details¶
Vite Build Settings (apps/web/nuxt.config.ts):
vite: {
build: {
cssCodeSplit: true,
minify: 'terser',
terserOptions: {
compress: {
drop_console: true, // Remove in production
drop_debugger: true,
},
},
rollupOptions: {
output: {
// Content-based naming for optimal caching
entryFileNames: '_nuxt/[name]-[hash].js',
chunkFileNames: '_nuxt/[name]-[hash].js',
assetFileNames: (assetInfo) => {
const info = assetInfo.name || ''
if (info.endsWith('.css')) return '_nuxt/css/[name]-[hash][extname]'
return '_nuxt/[name]-[hash][extname]'
},
},
},
},
}
Route Caching Strategy:
- Static pages (/, /blog, /glossary, /info): 1-year cache
- Member area: No caching (dynamic content)
- Auth pages: No cache (security)
Lazy Loaded Components:
- LazyCurrencyConversionModal - Heavy currency conversion logic
- LazyImageCropperModal - Image processing functionality
See Also¶
- Development Setup - Getting started with these technologies
- Project Structure - How these technologies are organized
- Testing Guide - Using the testing frameworks
- API Deployment - API deployment details