A modern invoice management application built with SvelteKit 5, featuring Better Auth authentication, Drizzle ORM with Neon database, and Bun UUIDv7 for resilient ID generation.
- Bun (recommended) or Node.js 18+
- Neon account for PostgreSQL database
- Vercel account for deployment (optional)
-
Clone and install dependencies:
git clone <repository-url> cd dollar-holler bun install
-
Set up environment variables: Create a
.envfile in the root directory for local development:DATABASE_URL="postgresql://username:password@hostname:port/database" PUBLIC_BASE_URL="http://localhost:5173" BETTER_AUTH_SECRET="your-strong-secret" PUBLIC_EDEN_URL="localhost:5173"
For production, use
.env.production(and/or your Vercel project settings) and set:PUBLIC_BASE_URL="https://dollar-holler.vercel.app" PUBLIC_EDEN_URL="localhost:4173"
-
Set up the database:
# Generate migrations bun run db:generate # Run migrations bun run db:migrate # Seed the database with sample data bun run db:seed
-
Start the development server:
bun run dev
-
Optional: Preview production build
bun run build && bun run preview
bun run dev- Start development server (Vite 8 beta)bun run build- Build for productionbun run preview- Preview production buildbun run check- Run Ultracite checksbun run check:watch- Run Svelte check in watch modebun run db:generate- Generate Drizzle migrationsbun run db:migrate- Run database migrationsbun run db:seed- Seed database with sample databun run db:studio- Open Drizzle Studiobun run db:push- Push schema directly to the databasebun run format- Format source with Prettierbun run lint- Run Prettier check and ESLintbun run lint:fix- Auto-fix lint and formatting issuesbun run ultracite- Run Ultracite linting and best-practices checksbun run ultracite:fix- Autofix Ultracite issues where possiblebun run ultracite:upgrade- Re-run Ultracite init/upgrade for this stackbun run fix- Convenience script to run the main fix pipeline
- Framework: SvelteKit 5 with Svelte 5 runes
- API Layer: ElysiaJS for type-safe API routes (exposed via Eden Treaty client)
- Database: PostgreSQL with Neon serverless
- ORM: Drizzle ORM with Neon serverless driver (WebSocket Pool)
- Authentication: Better Auth with email/password
- ID Generation: Bun UUIDv7 for resilient, cursor-friendly IDs
- Deployment: Vercel adapter
- Package Manager: Bun
- Validation: ArkType for runtime-safe form validation
- Bundler: Vite 8 (Vite alias) for faster builds
- UI Components: Bits UI with Tailwind CSS
- Styling: Tailwind CSS 4 with Tailwind Variants
src/
├── lib/
│ ├── auth.ts # Better Auth configuration (UUIDv7 IDs, Neon adapter)
│ ├── auth-client.ts # Client-side auth utilities
│ ├── db/
│ │ ├── index.ts # Database connection (Neon serverless WebSocket pool)
│ │ ├── schema.ts # Drizzle schema definitions
│ │ ├── seed.ts # Database seeding script
│ │ └── migrate.ts # Migration utilities
│ ├── elysia/
│ │ ├── auth-plugin.ts # Better Auth integration plugin
│ │ └── routes/ # API route modules (clients, invoices, settings)
│ ├── components/ # Reusable UI components
│ │ ├── ui/ # Bits UI components
│ │ └── ... # Custom components
│ ├── attachments/ # Svelte 5 @attach directives
│ ├── stores/ # Svelte stores (clients, invoices, line items, settings)
│ ├── utils/ # Helper functions
│ └── validators.ts # ArkType validation schemas
├── routes/ # SvelteKit routes
└── app.html # HTML template
The application uses the following main tables:
user- Better Auth user accountssession- User sessionsaccount- OAuth accountsverification- Email verification tokensclients- Client informationinvoices- Invoice recordsline_items- Invoice line itemssettings- User settings
All primary keys are generated as Bun UUIDv7 strings and include proper foreign key relationships with cascade deletes.
The application uses Drizzle's relations v2 (defineRelations) to simplify nested queries (e.g., db.query.invoices.findMany({ with: { client: true, lineItems: true } })) and avoid manual joins in API routes.
- Modern Authentication: Better Auth with email/password support
- Type-Safe Database: Drizzle ORM with full TypeScript support
- Serverless Ready: Neon HTTP driver for Vercel deployment
- Resilient IDs: CUID2 for cursor-based navigation and better performance
- Recent Data: Seed script generates realistic data from the last 6 months
- Multi-User Support: Data is distributed randomly among users
- Auth Flows: Reset password supported; token is read from URL and validated
- Modern UI: Bits UI components with Tailwind CSS 4
- Svelte 5 Runes: Uses @attach directives and reactive patterns
- Responsive Design: Mobile-first with swipe gestures
The application is configured for Vercel deployment with the Vercel adapter. Ensure your DATABASE_URL and BETTER_AUTH_SECRET environment variables are set in your Vercel project settings.
- Uses
Vite 8by aliasingviteinpackage.json(drop-in replacement). If issues arise with third-party plugins, see Vite's rolldown guide forwithFilterand environment APIs. - ESLint configuration is in
eslint.config.mjsand uses Svelte 5 rules and Prettier integration. Usebun run formatbeforebun run lint. - The project uses Svelte 5's new
@attachdirective for modern component patterns and the Spring class for smooth animations. - Better Auth is configured to use Bun UUIDv7 for user ID generation and includes session caching for performance.
MIT