Laju Go
Go Fiber + Inertia.js + SQLite — Svelte, React, or Vue

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.

terminal
$ npx create-laju-go@latest my-app
? Select a frontend framework:
❯ Svelte 5 (default)
React 19
Vue 3
↓ Downloading template...
✓ Dependencies installed
✓ Environment configured
$ cd my-app && npm run dev:all
→ Go: http://localhost:8080
→ Vite: http://localhost:5173
█

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>
Install: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>
Install: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>
Install:npx create-laju-go@latest my-app --template vue
Same Go handlers. Same routes. Same SQLite database. The backend doesn't know which framework you chose — Inertia.js handles the bridge.

Why 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.

Start in one command.

npx create-laju-go@latest my-app

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.