Go backend.
Your frontend.
One binary.
A SaaS boilerplate with auth, uploads, migrations, and Docker — wired end to end. Choose Svelte, React, or Vue. The Go backend doesn't know which one you picked.
Free — MIT licensed. No account required.
What's in the box
Not a TODO list. Working code, wired end to end.
Auth, fully wired
Email/password register & login, Google OAuth, password reset via SMTP, DB-backed sessions, CSRF tokens, rate limiting, account lockout. Working out of the box.
Resumable uploads
Multipart FormData for avatars, TUS protocol for large files — chunked, resumable, progress tracking.
sqlc, no ORM
Write SQL in queries/*.sql, get type-safe Go. Compile-time safety, zero runtime reflection.
Migrations on startup
Goose runs automatically when the binary starts. One table per file, never edit a deployed migration.
Deploy anywhere
Multi-stage Dockerfile, CGO cross-compile via Zig, graceful shutdown, security headers.
Same page, three syntaxes
The Login form in each framework. Same Go backend, same Inertia props, same database.
// Login.svelte
import { useForm } from "@inertiajs/svelte";
const form = useForm({ email: "", password: "" });
function submitForm(e) {
e.preventDefault();
form.post("/login");
}
<form onsubmit={submitForm}>
<input bind:value={form.email} type="email" />
<input bind:value={form.password} type="password" />
{#if form.errors.email}<span>{form.errors.email}</span>{/if}
<button disabled={form.processing}>Sign in</button>
</form>npx create-laju-go@latest my-app// Login.tsx
import { useForm } from "@inertiajs/react";
const { data, setData, post, processing, errors } = useForm({
email: "",
password: "",
});
function submitForm(e) {
e.preventDefault();
post("/login");
}
<form onSubmit={submitForm}>
<input value={data.email}
onChange={e => setData("email", e.target.value)} />
<input value={data.password}
onChange={e => setData("password", e.target.value)} />
{errors.email && <span>{errors.email}</span>}
<button disabled={processing}>Sign in</button>
</form>npx create-laju-go@latest my-app --template react<!-- Login.vue -->
import { useForm } from "@inertiajs/vue3";
const form = useForm({ email: "", password: "" });
function submitForm() {
form.post("/login");
}
<form @submit.prevent="submitForm">
<input v-model="form.email" type="email" />
<input v-model="form.password" type="password" />
<span v-if="form.errors.email">{{ form.errors.email }}</span>
<button :disabled="form.processing">Sign in</button>
</form>npx create-laju-go@latest my-app --template vueWhy this stack
Every choice eliminates a category of complexity. Not adds a feature — removes one.
Go means one binary
No runtime to install on the server. No node_modules in production. No JIT warmup. You scp one file and run it. Fiber on fasthttp is one of the fastest Go web frameworks available — headroom you'll never worry about.
SQLite, zero ops
One file to back up — copy it, done. No database server to run, no connection pool to tune. WAL mode serves tens of thousands of reads per second.
sqlc, no ORM tax
Write SQL, get type-safe Go. Compile-time safety, zero runtime reflection. The SQL is the source of truth — grep queries/ and you have the complete data access surface.
For the full reasoning, read the philosophy page.
FAQ
Questions you might have before running `npx create-laju-go@latest`.
Is it free?
Yes. MIT licensed. No account, no payment, no telemetry. Fork it, own it, ship it.
What's included?
Auth (register, login, Google OAuth, password reset, sessions, CSRF, rate limiting), uploads (avatar multipart + TUS large files), SQLite with sqlc type-safe queries, Goose migrations, three-tier architecture, tests, multi-stage Dockerfile, and your choice of Svelte 5, React 19, or Vue 3 — all with TailwindCSS.
Do I have to use Svelte?
No. Run `npx create-laju-go@latest my-app` and pick Svelte, React, or Vue. Or use `--template react` / `--template vue`. The Go backend stays identical regardless of your frontend choice.
Can I deploy with Docker?
Yes. Multi-stage Dockerfile included, plus a `make build-linux` target that cross-compiles via Zig for CGO/SQLite. Deploy to any VPS, Fly.io, Railway, or anywhere that runs a binary or container.
Why SQLite and not Postgres?
One file, zero ops, WAL mode tuned for concurrency. Enough for most SaaS apps. When you outgrow it, swap the sqlc engine and connection string — the query layer stays the same.
Why no ORM?
sqlc generates type-safe Go from plain SQL. Compile-time safety, zero runtime reflection. You see the exact SQL that runs, at peak performance. No N+1 surprises, no hidden query generation.