Production‑ready starter with Firebase Authentication (email/password + Google), secure session cookies, centralized route guards, and a server‑first data approach (no client Firestore). Ships with TailwindCSS, dark/light theme, and a small component library.
src/hooks.server.js
git clone <this-repo>
cd svelte-boilerplate
npm install
cp env.example .env
# fill in all values in .env (see below)
npm run dev
Visit http://localhost:5173
.
Create a .env
file (never commit it). Client‑side variables must be prefixed with VITE_
.
VITE_FIREBASE_API_KEY=
VITE_FIREBASE_AUTH_DOMAIN=
VITE_FIREBASE_PROJECT_ID=
VITE_FIREBASE_STORAGE_BUCKET=
VITE_FIREBASE_MESSAGING_SENDER_ID=
VITE_FIREBASE_APP_ID=
# Optional but supported by the codebase
VITE_FIREBASE_MEASUREMENT_ID=
You can find these in Firebase Console → Project settings → Your apps → Web app.
These are used only on the server to verify tokens and create session cookies. Keep them secret.
FIREBASE_PROJECT_ID=
FIREBASE_CLIENT_EMAIL=
# If your private key contains newlines, either keep them as real newlines
# or escape them as \n (the code handles both):
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
The Admin credentials come from Firebase Console → Project settings → Service accounts → Generate new private key. Do not expose this key to the client.
npm run dev # start dev server
npm run build # production build
npm run preview # preview production build locally
npm run lint # check formatting and linting
npm run format # format code with Prettier
email/password
or Google
).POST /api/auth/login
.session
cookie.users/{uid}
) using the Admin SDK.src/hooks.server.js
reads the cookie on every request and sets event.locals.user
./app
; other paths redirect to /app
./verify-email
./
, /login
, /account
, /reset-password
; other paths redirect to /login
.Endpoints:
POST /api/auth/login
– verifies ID token, creates the session cookie, and upserts the profilePOST /api/auth/logout
– clears the session cookie/
landing/login
– email/password and Google login/verify-email
– prompt to verify address and resend link/reset-password
– send reset email/app
– protected area after verification+server.js
routes or +layout.server.js
).users/{uid}
so first‑time sign‑ins get a profile document.src/routes/api/...
and use adminDb
from $lib/server/firebase-admin
.Example (server):
// src/routes/api/widgets/+server.js
import { json } from '@sveltejs/kit';
import { adminDb } from '$lib/server/firebase-admin';
export async function GET() {
const snapshot = await adminDb.collection('widgets').get();
return json(snapshot.docs.map((d) => ({ id: d.id, ...d.data() })));
}
signInWithEmailAndPassword
, signInWithPopup
, sendPasswordResetEmail
, sendEmailVerification
.Example (dynamic import in a click handler):
<script>
let email = $state('');
let password = $state('');
async function handleLogin() {
const { login } = await import('$lib/firebase/auth');
await login(email, password);
}
</script>
<button onclick={handleLogin}>Log in</button>
tailwind.config.js
and styles in src/lib/styles/
.src/lib/components/parts/
and src/lib/components/blocks/
.Works out of the box on platforms supported by @sveltejs/adapter-auto
(Vercel, Netlify, Node, etc.).
VITE_…
and server‑only FIREBASE_…
).Cookie security is already configured to be secure
in production.
FIREBASE_PRIVATE_KEY
newlines are correct (see above).session
cookie is set after login.