Write Python endpoints in SvelteKit and seamlessly deploy them to Vercel.
- Current Features
- Installing
- Testing Locally
- Deploying to Vercel
- Example
- Fork of
sveltekit-modal - Possible future plans
This is very much in beta.
- Write
+server.pyfiles nearly the same way you would write+server.jsfiles - Write server
loadfunctions in+page.server.pyand+layout.server.py - Deploy automatically to Vercel Serverless (Python 3.12 runtime)
-
Open or set up your SvelteKit project
-
Install SvelteKit's Vercel adapter:
pnpm i -D @sveltejs/adapter-vercel -
Install with
pnpm i -D sveltekit-python-vercel -
Update your
vite.config.jsimport { defineConfig } from "vite"; import { sveltekit } from "@sveltejs/kit/vite"; import { sveltekit_python_vercel } from "sveltekit-python-vercel/vite"; export default defineConfig({ plugins: [sveltekit(), ...(await sveltekit_python_vercel())], });
-
Update your
svelte.config.js:import adapter from "@sveltejs/adapter-vercel"; import { vitePreprocess } from "@sveltejs/kit/vite"; /** @type {import('@sveltejs/kit').Config} */ const config = { preprocess: vitePreprocess(), kit: { adapter: adapter(), moduleExtensions: [".js", ".ts", ".py"], // add ".py" to resolve +server.py endpoints }, }; export default config;
-
Update your
vercel.json- The build command first runs
vite build(which generates.vercel/output/via the SvelteKit adapter), then runs our script to write the Python function into that same output directory and patch the routing config. - No
routesorfunctionskeys are needed — routing is handled automatically via the Vercel Build Output API.
{ "buildCommand": "vite build; node ./node_modules/sveltekit-python-vercel/esm/src/vite/sveltekit_python_vercel/bin.mjs" } - The build command first runs
-
Write some
+server.pyendpoints. See the example section below.
uv is recommended for managing your Python environment.
- Run
uv init --python 3.12to create apyproject.tomlpinned to Python 3.12 (the same version Vercel's runtime uses). - Add the required packages:
uv add fastapi uvicorn - Add any other dependencies you need:
uv add numpy pandas ... - Run your dev server inside uv:
uv run pnpm dev
- You should see both the usual SvelteKit server start and the uvicorn server (by default on
http://0.0.0.0:8000) in the console.
Just push to your repository — no extra steps required.
- The
buildCommandinvercel.jsonhandles everything automatically:vite buildruns the SvelteKit build and writes.vercel/output/via@sveltejs/adapter-vercelbin.mjsthen writes your Python endpoints into.vercel/output/functions/using the Build Output API and patches the routing config
- Your
+server.pyfiles and dependency declarations (requirements.txt,pyproject.toml,Pipfile, etc.) are bundled automatically — there is no need to commit an/apifolder or manually generate arequirements.txt. - Python packages are pre-installed into the function bundle at build time using
pip install --target, so they are available in Vercel's raw Python 3.12 Lambda environment without any extra configuration.
-
Frontend:
/src/routes/py/+page.svelte<script> let a = $state(0); let b = $state(0); let total = $state(0); async function pyAddPost() { const res = await fetch("/py", { method: "POST", body: JSON.stringify({ a, b }), headers: { "content-type": "application/json" }, }); total = (await res.json()).sum; } async function pyAddGet() { const res = await fetch(`/py?a=${a}&b=${b}`); total = (await res.json()).sum; } </script> <h1>SvelteKit page with a Python backend</h1> <label>a: <input type="number" bind:value={a} /></label> <label>b: <input type="number" bind:value={b} /></label> <button type="button" onclick={pyAddPost}>POST</button> <button type="button" onclick={pyAddGet}>GET</button> <p>Total: {total}</p>
-
Backend:
/src/routes/py/+server.pyfrom pydantic import BaseModel class NumberSet(BaseModel): a: float b: float async def POST(data: NumberSet): return {"sum": data.a + data.b} async def GET(a: float, b: float): return {"sum": a + b}
GETendpoints receive query parameters directly as function arguments. Type annotations are used for coercion (e.g.a: floatparses?a=3as3.0).- All other HTTP methods receive the request body as JSON. The recommended pattern is a Pydantic model as the single argument — FastAPI handles validation and parsing automatically.
Server-side load functions work in +page.server.py and +layout.server.py. No extra Python package install is required — the runtime is bundled automatically like +server.py.
async def load(event):
if event.params["id"] == "secret":
return ("redirect", 307, "/demo/public")
if event.params["id"] not in ("public", "1", "2"):
return ("error", 404, "Not found")
return {
"title": f"Item {event.params['id']}",
"parent_theme": event.parent.theme if event.parent else None,
}Errors and redirects can also use injected helpers (no import needed):
async def load(event):
if not event.cookies.get("session"):
redirect(307, "/login")
return {"ok": True}Available on event: params, url, route, parent (layout data), data (from a sibling universal load), cookies.
Current limitations: no event.fetch, setHeaders, depends, or page options (prerender, etc.) in .py files yet.
| Tag | When it updates | Install |
|---|---|---|
latest |
GitHub Release created | pnpm add -D sveltekit-python-vercel |
beta |
Every push to main |
pnpm add -D sveltekit-python-vercel@beta |
pr-<n> |
Open/update PR #n (same-repo only) |
pnpm add -D sveltekit-python-vercel@pr-15 |
Beta versions look like 1.0.3-beta.abc1234 (main) or 1.0.3-beta.pr15.abc1234 (PRs).
All publishes run through .github/workflows/publish.yml because npm trusted publishing only allows one workflow filename per package.
If you work on this repo and a consumer app side by side (e.g. test-skpv-deploy):
- Build:
deno run -A dnt.ts $(npm view sveltekit-python-vercel version)(or any version string) - In the consumer:
pnpm add -D sveltekit-python-vercel@link:../sveltekit-python-vercel/npm - Rebuild and restart the consumer dev server after library changes
Commit ^x.y.z or @beta in the consumer for Vercel — link: only works on your machine.
Check out the awesome sveltekit-modal package by @semicognitive, the original way to get your python code running in SvelteKit. Modal even has GPU support for running an entire ML stack within SvelteKit.
- Add hot reloading in dev mode
- Generate endpoints automatically during build (via Vercel Build Output API)
- Auto-bundle requirements.txt / pyproject.toml / Pipfile at build time
- Add form actions
- Add load functions
- Add helper functions to automatically call API endpoints in project
