A full-stack web application built with SvelteKit and Bun, featuring user authentication and a simple counter functionality.
svelte-bun is a modern full-stack web application that demonstrates best practices for building web apps with cutting-edge technologies. It showcases:
This project serves as a reference implementation for building modern web applications and can be used as a starting point for new projects.
@neondatabase/serverless (for Cloudflare Workers/Pages)postgres (for local development)git clone https://github.com/mbe24/svelte-bun.git
cd svelte-bun
bun install
# or
npm install
Copy the example environment file and configure your credentials:
cp .env.example .env
Edit the .env file and update the credentials (use secure passwords in production):
POSTGRES_USER=postgres
POSTGRES_PASSWORD=your_secure_password_here
POSTGRES_DB=sveltekit_db
DATABASE_URL=postgresql://postgres:your_secure_password_here@localhost:5432/sveltekit_db
Optional: PostHog Analytics
To enable analytics, logging, and exception tracking with PostHog:
.env file:# PostHog tracking (both server and client-side)
# PostHog API keys are safe to expose publicly - they're designed for browser use
POSTHOG_API_KEY=your_posthog_api_key_here
# PostHog Events API Host (for HTTP requests, page views, custom events)
# US: https://app.posthog.com or https://us.posthog.com
# EU: https://eu.posthog.com
POSTHOG_HOST=https://app.posthog.com
# PostHog OTLP Logs API Host (for logs, exceptions, telemetry) - OPTIONAL
# If not set, automatically derived from POSTHOG_HOST
# US: https://us.i.posthog.com
# EU: https://eu.i.posthog.com
# POSTHOG_OTLP_HOST=https://us.i.posthog.com
Note: The POSTHOG_OTLP_HOST is optional. If not provided, it will be automatically derived from POSTHOG_HOST (e.g., app.posthog.com maps to us.i.posthog.com).
This enables:
logMessage() and logException() (Logs tab)For Cloudflare Workers deployment, add these variables in your Cloudflare Pages environment settings.
See docs/POSTHOG_SETUP.md for complete setup instructions and usage examples.
Optional: Upstash Redis Rate Limiting
To enable rate limiting for counter actions (3 actions per 10 seconds):
.env file:# Upstash Redis for rate limiting
UPSTASH_REDIS_REST_URL=https://your-redis-instance.upstash.io
UPSTASH_REDIS_REST_TOKEN=your_secret_token_here
For Cloudflare Pages deployment:
UPSTASH_REDIS_REST_TOKEN to Cloudflare Pages environment variablesUPSTASH_REDIS_REST_URL in wrangler.tomlSee docs/UPSTASH_REDIS_SETUP.md for complete setup instructions.
Note: If Upstash Redis is not configured, the application will work normally without rate limiting.
⚠️ Security Note: Never commit the .env file to version control. It contains sensitive credentials and is already excluded via .gitignore.
For more details on security configuration, see docs/SECURITY.md.
Make sure PostgreSQL is running, then generate and run migrations:
# Generate migrations from schema
bun run db:generate
# Run migrations
bun run db:push
bun run dev
# or
npm run dev
Open http://localhost:5173 in your browser.
bun run dev - Start the development serverbun run build - Build the application for productionbun run preview - Preview the production buildbun run check - Run TypeScript and Svelte checksbun run db:generate - Generate Drizzle migrationsbun run db:push - Push schema changes to the databasebun run db:studio - Open Drizzle Studio (database GUI)bun test - Run unit testsThis application is optimized for deployment on Cloudflare Pages with automatic edge runtime compatibility.
Key Features:
Prerequisites:
Quick Start:
Create a free Neon PostgreSQL database
Get your connection string from Neon dashboard
Follow the detailed guide in docs/DEPLOY.md
Critical: Add DATABASE_URL to Cloudflare Pages Settings → Environment variables (both Production and Preview)
Push to GitHub - automatic deployment via GitHub Actions
⭐ Run migrations by visiting this URL in your browser:
https://your-app.pages.dev/api/admin/migrate
Click the "Run Database Migration" button - that's it!
Alternative methods:
curl -X POST https://your-app.pages.dev/api/admin/migratenpm run db:push with DATABASE_URL set⚠️ Important:
/api/admin/migrate in your browser and click the button to fix this!See docs/DEPLOY.md for complete step-by-step instructions, including separate database setup for preview/production environments.
Important: Before running Docker Compose, create a .env file with your credentials:
cp .env.example .env
# Edit .env with your actual credentials
Make sure your .env file includes:
POSTGRES_USER=postgres
POSTGRES_PASSWORD=your_secure_password_here
POSTGRES_DB=sveltekit_db
DATABASE_URL=postgresql://postgres:your_secure_password_here@db:5432/sveltekit_db
Note: Use @db:5432 (not @localhost:5432) in DATABASE_URL for Docker Compose.
Then start the services:
# Build and start all services
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose down
The application will be available at http://localhost:3000.
For more details on security configuration, see docs/SECURITY.md.
# Build the image
docker build -t svelte-bun-app .
# Run the container (replace with your actual credentials)
docker run -p 3000:3000 \
-e DATABASE_URL=postgresql://username:password@host:5432/sveltekit_db \
svelte-bun-app
svelte-bun/
├── src/
│ ├── lib/
│ │ ├── auth/ # Authentication utilities
│ │ └── db/ # Database schema and connection
│ ├── routes/
│ │ ├── api/ # API endpoints
│ │ │ ├── auth/ # Authentication endpoints
│ │ │ └── counter/ # Counter endpoints
│ │ ├── login/ # Login page
│ │ ├── register/ # Registration page
│ │ ├── counter/ # Counter page (protected)
│ │ └── +page.svelte # Home page
│ ├── app.d.ts # TypeScript definitions
│ ├── app.html # HTML template
│ └── hooks.server.ts # Server hooks for authentication
├── drizzle/ # Database migrations
├── drizzle.config.ts # Drizzle configuration
├── docker-compose.yml # Docker Compose configuration
├── Dockerfile # Docker image configuration
└── package.json # Project dependencies
id (serial, primary key)username (text, unique, not null)password (text, not null) - bcrypt hashedcreated_at (timestamp, default now)id (text, primary key)user_id (integer, foreign key to users)expires_at (timestamp, not null)id (serial, primary key)user_id (integer, foreign key to users, unique)value (integer, default 0)updated_at (timestamp, default now)POST /api/auth/register - Register a new userPOST /api/auth/login - Login with username and passwordPOST /api/auth/logout - Logout and delete sessionGET /api/counter - Get current counter value (requires authentication)POST /api/counter - Increment or decrement counter (requires authentication){ "action": "increment" | "decrement" }When configured, the application automatically logs all HTTP requests to PostHog with the following information:
Logs & Exceptions:
logMessage() and logException() functions to send logs via OTLPhttps://app.posthog.com → https://us.i.posthog.com/i/v1/logs, https://eu.posthog.com → https://eu.i.posthog.com/i/v1/logs)Configuration:
POSTHOG_API_KEY and optionally POSTHOG_HOST in your environment variablesEvent Format (HTTP Requests):
{
distinctId: "user_123" or "ip_address" or "anonymous",
event: "http_request",
properties: {
method: "GET",
path: "/api/counter",
status: 200,
duration_ms: 45,
user_agent: "Mozilla/5.0...",
authenticated: true,
user_id: 123
}
}
OTLP Log Format (Exceptions & Custom Logs):
Sent to PostHog's /i/v1/logs endpoint with Authorization header containing the API key.
bun test
# Install Playwright browsers
bunx playwright install
# Run E2E tests
bun run test:e2e
For detailed information about security configuration:
DATABASE_URL in your .env file is correctsveltekit_db existsvite.config.ts or use the --port flag:bun run dev -- --port 3001
docker system prune -aContributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
git checkout -b feature/amazing-feature)git commit -m 'Add some amazing feature')git push origin feature/amazing-feature)Apache License 2.0