A multi-tenant, full-stack hackathon starter application built with Buffalo (Go), Svelte 5, Tailwind CSS v4, and DaisyUI. This starter is designed for an agentic workflow in which you use its skills to design landing pages and mockups for your site, then it can help build systems architectural specifications, API and database schema design, and then generate the initial implementation for your features (code, migrations, etc.). It even includes some documentation about how to deploy it on Google Cloud, as well as other platforms.
- Multi-tenancy: Users can belong to multiple organizations and switch between them seamlessly.
- Role-Based Access Control (RBAC):
- Super Administrators: Manage organizations and all users across the platform.
- Administrators: Manage users within their specific organization.
- Users: Manage their personal to-do lists within an organization.
- Sample Feature:Ships with a to-do example feature in which todo lists are strictly scoped to both a user and an organization.
- Easy Onboarding: New users can sign up and are automatically joined to the Default Organization.
- Efficient Runtime: Compiles to 25mb go executable (30mb docker image) and runs with no Javascript frontend dependencies (compiles to native JS with Svelte).
Get the application up and running locally in three quick steps:
-
Install Dependencies & Set Up Environment:
# Install backend & frontend dependencies go mod download npm install go install github.com/gobuffalo/cli/cmd/buffalo@latest go install github.com/gobuffalo/buffalo-pop/v3@latest # Copy the sample environment file cp .env.sample .env
-
Prepare the Database: Ensure PostgreSQL is running locally, then initialize and migrate the database:
buffalo pop create -a buffalo pop migrate
-
Start the Development Servers: Launch the Go backend and Svelte/Vite asset compilation in separate terminals:
# Terminal 1: Backend Dev Server (runs on http://localhost:3000) buffalo dev # Terminal 2: Frontend Asset Pipeline (runs on http://localhost:3001) npm run dev
Now open http://localhost:3000 in your browser!
Tip
Default Admin Account: Log in with the pre-seeded Super Administrator credentials:
- Username:
admin@example.com - Password:
password123
- Tech Stack
- Repository Structure
- Prerequisites
- Configuration
- Local Development (Without Docker)
- Running with Docker
- Database Management
- Building for Production
- Stopping the Application
- Running Tests
| Layer | Technology | Version |
|---|---|---|
| Backend framework | Buffalo | v1.1.4 |
| Language | Go | 1.26+ |
| ORM | Pop (gobuffalo/pop/v6) | v6.3 |
| Database | PostgreSQL | 14+ |
| Template engine | Plush | v5 |
| Frontend framework | Svelte | v5 (Runes syntax) |
| Frontend build tool | Vite | v8 |
| CSS framework | Tailwind CSS | v4 |
| UI component library | DaisyUI | v5 |
| Session security | unrolled/secure | v1 |
buffalo-app/
├── actions/ # Go controllers (thin handlers — push logic to models/)
│ ├── app.go # Route definitions and middleware setup
│ ├── home.go # Landing page handler
│ ├── render.go # Buffalo render engine configuration
│ └── vite.go # Vite manifest helper (resolves hashed asset filenames)
├── assets/ # Frontend source files (compiled by Vite, NOT served directly)
│ ├── css/
│ │ └── application.css # Tailwind CSS v4 entry point + DaisyUI plugin
│ └── js/
│ ├── main.js # Vite/Svelte entry point (mounts Svelte into #app)
│ └── components/ # Svelte components
│ └── HelloWorld.svelte
├── cmd/app/
│ └── main.go # Application entrypoint
├── config/
│ └── buffalo-app.toml # Buffalo application metadata
├── grifts/ # Buffalo task scripts (e.g. database seeding)
├── locales/ # i18n translation files
├── migrations/ # Database migration files (Fizz format)
├── models/ # Pop ORM models (Go structs matching DB schema)
│ └── models.go # DB connection setup
├── public/ # Statically served files
│ └── assets/ # Compiled frontend output (generated by `npm run build`)
├── templates/ # Plush server-rendered HTML templates
│ ├── application.plush.html # Base HTML layout (navbar, footer, asset tags)
│ ├── _flash.plush.html # Flash message partial
│ └── home/
│ └── index.plush.html # Landing page
├── .agents/ # AI agent configuration (do not delete)
│ ├── specifications/ # Application spec and story documentation
│ │ ├── application_spec.md
│ │ └── stories/ # Backlog and per-story folders
│ ├── skills/ # Reusable AI agent skills
│ └── knowledge/ # Knowledge items (KIs) about the codebase
├── .buffalo.dev.yml # Buffalo hot-reload watcher config
├── .env # Local environment variables (gitignored)
├── database.yml # Pop database connection config
├── go.mod / go.sum # Go module dependencies
├── package.json # Node dependencies (Svelte, Vite, Tailwind, DaisyUI)
├── svelte.config.js # Svelte preprocessor config
└── vite.config.js # Vite build config (outputs to public/assets/)
| Tool | Install |
|---|---|
| Go 1.26+ | https://go.dev/dl/ |
| Buffalo CLI v0.18+ | go install github.com/gobuffalo/cli/cmd/buffalo@latest |
| Node.js 18+ | https://nodejs.org/ |
| npm 9+ | Included with Node.js |
| PostgreSQL 14+ | https://www.postgresql.org/download/ |
- Git Bash or WSL2 recommended for a Unix-like shell experience.
- All commands below work in PowerShell unless noted.
- Docker Desktop — https://www.docker.com/products/docker-desktop/
All configuration is done via environment variables. Copy the example below into a .env file in the project root (Buffalo loads it automatically):
# Buffalo environment: development | test | production
GO_ENV=development
# Secret used to sign session cookies — CHANGE THIS in production!
SESSION_SECRET=changeme-use-a-random-secret-in-production
# PostgreSQL connection URLs (optional — defaults shown below are used if not set)
# DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/buffalo_app_development?sslmode=disable
# TEST_DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/buffalo_app_test?sslmode=disable| Variable | Required | Default | Description |
|---|---|---|---|
GO_ENV |
No | development |
Runtime environment |
SESSION_SECRET |
Yes (production) | — | Cookie signing secret (min 32 chars) |
DATABASE_URL |
No | postgres://postgres:postgres@127.0.0.1:5432/buffalo_app_development?sslmode=disable |
Primary DB connection |
TEST_DATABASE_URL |
No | Same host, ..._test database |
Used during buffalo test |
ADDR |
No | 127.0.0.1 |
Bind address (0.0.0.0 for Docker) |
PORT |
No | 3000 |
HTTP port |
FORCE_SSL |
No | false |
Force redirect to HTTPS |
The development workflow uses two terminals — one for the Go backend, one for the Vite frontend dev server.
1. Install Go dependencies
go mod download2. Install Node dependencies
npm install3. Start PostgreSQL (if not already running)
# macOS with Homebrew
brew services start postgresql@14
# Linux (systemd)
sudo systemctl start postgresql4. Create the databases
buffalo pop create -a5. Run database migrations
buffalo pop migrate6. Start the backend (Terminal 1)
buffalo dev7. Start the frontend dev server (Terminal 2)
npm run devOpen http://localhost:3000 in your browser. Vite runs on http://localhost:3001 and serves frontend assets with hot module replacement.
Note
Default Seeded Admin User: The database migrations automatically seed a default Super Administrator account:
- Email / Username:
admin@example.com - Password:
password123 - Default Organization:
Default Organization
1. Install Go dependencies
go mod download2. Install Node dependencies
npm install3. Start PostgreSQL
If installed via the PostgreSQL Windows installer, start it from Services (services.msc) or:
# Start via pg_ctl (adjust path to your Postgres installation)
& "C:\Program Files\PostgreSQL\14\bin\pg_ctl.exe" start -D "C:\Program Files\PostgreSQL\14\data"4. Create the databases
buffalo pop create -a5. Run database migrations
buffalo pop migrate6. Start the backend (Terminal 1)
buffalo dev7. Start the frontend dev server (Terminal 2)
npm run devOpen http://localhost:3000 in your browser.
Tip: Windows Defender or antivirus may slow down the Go file watcher. Adding the project folder to the exclusion list improves rebuild speed significantly.
The included Dockerfile performs a two-stage build: it compiles the Go binary (with assets embedded) in a Buffalo builder image and produces a minimal Alpine-based production image.
Note: You must build the frontend assets before
docker build, asbuffalo build --staticembedspublic/assets/into the binary.
npm install
npm run builddocker build -t todoflow:latest .docker run -d \
--name todoflow \
-p 3000:3000 \
-e GO_ENV=production \
-e SESSION_SECRET=your-super-secret-here \
-e DATABASE_URL="postgres://user:password@host:5432/buffalo_app_production?sslmode=disable" \
todoflow:latestOpen http://localhost:3000.
docker exec todoflow /bin/app migrateCreate a docker-compose.yml in the project root:
version: '3.8'
services:
db:
image: postgres:14-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
app:
build: .
ports:
- "3000:3000"
environment:
GO_ENV: production
ADDR: 0.0.0.0
SESSION_SECRET: changeme-replace-in-production
DATABASE_URL: postgres://postgres:postgres@db:5432/buffalo_app_production?sslmode=disable
depends_on:
- db
volumes:
pgdata:Then run:
npm run build # build frontend assets first
docker compose up --build # start app + database
docker compose exec app /bin/app migrate # run migrations# Create all databases defined in database.yml
buffalo pop create -a
# Drop all databases
buffalo pop drop -a
# Run pending migrations
buffalo pop migrate
# Rollback the last migration
buffalo pop migrate down
# Generate a new migration (Fizz format)
buffalo pop generate fizz <migration_name>
# Reset: drop, create, migrate
buffalo pop reset# 1. Build frontend assets
npm run build
# 2. Build the Go binary (embeds public/assets/ into the binary)
buffalo build -o bin/app
# 3. Run the binary
GO_ENV="production" SESSION_SECRET="<secret>" DATABASE_URL="<url>" ./bin/appOn Windows, the binary will be
bin\app.exe. Run it from PowerShell:$env:GO_ENV="production"; $env:SESSION_SECRET="<secret>"; $env:DATABASE_URL="<url>"; .\bin\app.exe
When compiled, the application binary includes all database migrations embedded directly into the executable. You do not need the physical migration source files on disk in production.
To run migrations in your production environment, pass the migrate argument to the compiled binary:
# On Linux/macOS
./bin/app migrate
# On Windows (PowerShell)
.\bin\app.exe migrateTo roll back the last applied migration:
# On Linux/macOS
./bin/app migrate down
# On Windows (PowerShell)
.\bin\app.exe migrate downNote
Avoid using developer-facing subcommands like app pop migrate or app db migrate in production. Those commands are intended for local development and expect your physical database configuration and source code files to exist on disk in the current working directory. The standalone migrate and migrate down commands are optimized for production and run seamlessly from any directory.
By default, the application is configured to import all DaisyUI themes, which adds unused styling rules and theme variables to the compiled production CSS file.
To optimize and significantly reduce your CSS bundle size for production, you can restrict DaisyUI to load only the themes your application actually uses (e.g., light and dark):
- Open assets/css/application.css.
- Modify the
@plugin "daisyui"block to list only your desired theme(s) instead ofall:
/* Before: Imports all 30+ DaisyUI themes */
@plugin "daisyui" {
themes: all;
}
/* After: Imports only your selected themes (e.g. light and dark) */
@plugin "daisyui" {
themes: light, dark;
}- Rebuild your frontend assets to compile the optimized CSS:
npm run buildThis application is configured for continuous deployment using Google Cloud Build and Cloud Run, backed by Cloud SQL (PostgreSQL).
- Google Cloud Project: You need an active GCP project with billing enabled.
- Enable APIs: Enable the following APIs in your project:
- Cloud Run API (
run.googleapis.com) - Cloud Build API (
cloudbuild.googleapis.com) - Secret Manager API (
secretmanager.googleapis.com) - Cloud SQL Admin API (
sqladmin.googleapis.com)
- Cloud Run API (
- Cloud SQL Instance: Create a PostgreSQL instance in Cloud SQL and a database for the application. Make sure the Cloud Run service account has the Cloud SQL Client role.
Use Google Secret Manager to securely store your environment variables:
- Create Secrets:
- Create a secret named
TODOFLOW_SESSION_SECRET(e.g., a random 32+ character string). - Create a secret named
TODOFLOW_DATABASE_URLwith your Cloud SQL connection string.- Format:
postgres://<user>:<password>@<host>:5432/<database>?sslmode=disable - Note: If connecting via Cloud SQL Auth Proxy or Unix sockets, adjust the URL accordingly (e.g.,
postgres://<user>:<password>@/buffalo_app_production?host=/cloudsql/<PROJECT_ID>:<REGION>:<INSTANCE_NAME>).
- Format:
- Create a secret named
- Grant Access: Ensure the compute service account (used by Cloud Run) has the Secret Manager Secret Accessor role for both secrets.
The repository includes a cloudbuild.yaml file configured to:
- Run Migrations: Deploy and execute a temporary Cloud Run Job from source to run the database migrations (
/bin/app migrate). - Deploy Application: Deploy the main Cloud Run Service from source.
Both steps use gcloud run deploy --source ., which securely builds the container using Cloud Build (utilizing the multi-stage Dockerfile) and deploys it automatically.
To trigger a manual deployment using Cloud Build:
gcloud builds submit --config cloudbuild.yaml .You can also set up a Cloud Build Trigger to automatically deploy when you push to the main branch.
- Backend (
buffalo dev): PressCtrl+Cin Terminal 1. - Frontend (
npm run dev): PressCtrl+Cin Terminal 2.
# Stop and remove the container
docker stop todoflow && docker rm todoflow
# Docker Compose
docker compose down
# Docker Compose — also remove the database volume (⚠️ destroys data)
docker compose down -vTo run the Go automated test suite successfully, the environment must be set to test when launching the tests.
First, ensure the test database has been created:
# Create all databases defined in database.yml (including test)
buffalo pop create -aOn Unix-based systems, the Buffalo CLI automatically configures GO_ENV=test under the hood:
# Run all Go tests
buffalo test
# Run tests for a specific package
buffalo test ./actions/...On Windows (due to a path-escaping bug in Pop's schema loader) or when running tests inside an IDE (such as VS Code, GoLand, or Cursor), you must migrate the test database manually once and run the tests with standard Go tools, explicitly setting the environment variable:
# Run migrations on the test database
buffalo pop migrate -e test- Linux / macOS / Git Bash:
GO_ENV=test go test ./... - Windows (PowerShell):
$env:GO_ENV="test"; go test ./...
- Windows (Command Prompt):
set GO_ENV=test && go test ./...
The application provides custom Buffalo "grift" tasks for management and administration operations.
If a user gets locked out or you need to manually verify an account and change its password (especially during local development), run the recover_account task:
buffalo task recover_account admin@example.com password123This task will:
- Find the user by their email address.
- Reset and rehash their password to the
<new_password>. - Set their
AccountVerifiedstatus totrue. - Reset their failed login attempt counter.
We welcome contributions to this project! When contributing, please follow these guidelines to maintain code quality and consistency:
- Code Formatting: Always run
gofmt -w .to format Go code. - Error Handling: Check all error returns. Never discard errors with
_. - Pop ORM & Migrations:
- Existing database migrations are immutable. Always generate new ones using
buffalo pop generate fizz <name>. - Always explicitly define single or composite database indexes for foreign keys using
add_indexin Fizz migrations. - When loading related records, use Pop ORM's
.Eager()modifier explicitly as relationship loading is disabled by default.
- Existing database migrations are immutable. Always generate new ones using
- Svelte 5 Runes: Use Svelte 5 runes (
$state,$derived,$effect,$props). Do not use the legacy Options API. - UI/UX Styling:
- Prioritize DaisyUI components (e.g., buttons, cards, forms, tables) and Tailwind utility classes.
- Do not use inline
style="..."attributes. Avoid writing custom CSS unless absolutely necessary.
- CSRF Protection: Always include the
<%= authenticity_token %>in non-GET Plush forms, or pass the token via theX-CSRF-Tokenheader for Svelte/JSON client requests.
- Run all automated tests locally to verify your changes. Refer to the Running Tests section above for environment setup commands.

