# The Day I Finally Understood SvelteKit: From 404 Errors to Architectural Enlightenment You know that feeling when your code works perfectly in development but breaks mysteriously in staging? That moment when you're staring at a `404 Not Found` error, knowing the endpoint exists, wondering if you've somehow entered a parallel universe where your API routes have vanished? That was me, last Tuesday, trying to understand why `http://localhost/auth?/login` was returning a 404 error in staging while working flawlessly in dev. Little did I know, this debugging session would lead me to fundamentally rethink how modern web applications work. ## The Mystery of the Missing Endpoint The error was deceptively simple: ```console POST /v1/auth/oauth-login → 404 Not Found ``` My first instinct was to blame environment variables (it's always environment variables, right?). I dove into Docker logs, checked container networking, verified that all services were running. The backend was receiving requests, the frontend was sending them correctly, but somehow... 404. After an embarrassing amount of time, I finally asked my pair programming partner: "What's the correct auth endpoint path on the backend?" The answer? `/api/v1/auth/oauth-login`, not `/v1/auth/oauth-login`. That missing `/api` prefix sent me down a rabbit hole that would change how I think about web development. ## The BFF Pattern: My First "Aha" Moment As I traced through the code, I discovered something unexpected. The frontend wasn't calling the backend directly. Instead, it was using what my colleague called the "BFF pattern" - Backend for Frontend. ```typescript // What I expected: Browser → FastAPI Backend // What was actually happening: Browser → SvelteKit Server → FastAPI Backend ``` But wait, why add this extra hop? As I dug deeper, I found this intriguing file structure: ```console /routes/ ├── auth/ │ ├── +page.svelte # The login form UI │ └── +page.server.ts # Server-side form handling └── api/ └── [...path]/ └── +server.ts # API proxy to backend ``` ## "What Even Is a Server Anymore?" This is where things got philosophically interesting. I asked: "What's the server URL?" And then it hit me - there's only ONE server URL. The same SvelteKit server that serves HTML pages at `http://localhost/auth` also serves JSON APIs at `http://localhost/api/health`. My mental model shattered and reformed: **Traditional React App:** - Static server serves HTML/JS - Separate API server handles data - CORS headers everywhere - Two deployment targets **Traditional Server-Side App:** - Server renders HTML - No client-side interactivity - Full page reloads - Limited user experience **SvelteKit (The Hybrid):** - One server for everything - Server renders HTML with embedded interactivity - Same server handles API calls - No CORS needed for same-origin ## The Form Actions Revelation Then I discovered SvelteKit's form actions, and my brain exploded a little: ```typescript // +page.server.ts export const actions = { login: async ({ request, cookies }) => { // This runs on the server when form submits const data = await request.formData(); if (loginFails) { return fail(400, { error: "Invalid credentials" }); } throw redirect(303, "/dashboard"); } }; ``` ```svelte
{#if form?.error}