A modern invoice management application built with SvelteKit 5, featuring Better Auth authentication, Drizzle ORM (relations API) with Neon database, and CUID2 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
.env
file in the root directory:DATABASE_URL="postgresql://username:password@hostname:port/database" PUBLIC_BASE_URL="http://localhost:5173" BETTER_AUTH_SECRET="your-strong-secret"
-
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 serverbun run build
- Build for productionbun run preview
- Preview production buildbun run check
- Run Svelte checkbun 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 ESLint
- Framework: SvelteKit 5 with Svelte 5 runes
- Database: PostgreSQL with Neon serverless
- ORM: Drizzle ORM with Neon HTTP driver
- Authentication: Better Auth with email/password
- ID Generation: CUID2 for resilient, cursor-friendly IDs
- Deployment: Vercel adapter
- Package Manager: Bun
- Validation: ArkType for runtime-safe form validation
- Bundler: rolldown-vite (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
│ ├── auth-client.ts # Client-side auth utilities
│ ├── db/
│ │ ├── index.ts # Database connection (Neon HTTP)
│ │ ├── schema.ts # Drizzle schema definitions
│ │ ├── seed.ts # Database seeding script
│ │ └── migrate.ts # Migration utilities
│ ├── components/ # Reusable UI components
│ │ ├── ui/ # Bits UI components
│ │ └── ... # Custom components
│ ├── attachments/ # Svelte 5 @attach directives
│ ├── stores/ # Svelte stores (client, invoice, 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 tables use CUID2 for primary keys and include proper foreign key relationships with cascade deletes.
The application uses Drizzle's relations 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
rolldown-vite
by aliasingvite
inpackage.json
(drop-in replacement). If issues arise with third-party plugins, see Vite's rolldown guide forwithFilter
and environment APIs. - ESLint configuration is in
eslint.config.ts
and uses Svelte 5 rules and Prettier integration. Usebun run format
beforebun run lint
. - The project uses Svelte 5's new
@attach
directive for modern component patterns and the Spring class for smooth animations. - Better Auth is configured with CUID2 for user ID generation and includes session caching for performance.
MIT