- Shell 34.8%
- Rust 31.1%
- TypeScript 12.5%
- CSS 6.7%
- Svelte 6.1%
- Other 8.8%
| backend | ||
| docs | ||
| frontend | ||
| infra | ||
| mk | ||
| .browserstack.yml | ||
| .dockerignore | ||
| .flake8 | ||
| .gitignore | ||
| CONVENTIONS.md | ||
| Dockerfile | ||
| README.md | ||
Full-Stack Template Tutorial
This repository is a small full-stack starter:
frontend/is a SvelteKit app that builds to static filesbackend/is an Axum app that serves those files and exposes API routes- the final deployment shape is one Rust process behind one public port
Use this tutorial when you are turning the template into a real app.
How the template works
The frontend and backend are separate during development, but they meet at build time:
- build the Svelte app into
frontend/build/ - start the Rust server
- let Rust serve the static bundle and API routes together
The backend also writes runtime configuration to /static/config.json, which the frontend reads through frontend/src/routes/+layout.ts.
Project layout
frontend/ SvelteKit app
backend/ Axum app
docs/ focused notes for specific subsystems
mk/ helper scripts for test, run, and deployment
Dockerfile production image build
Prerequisites
You need:
- Node.js and npm for the frontend
- Rust and Cargo for the backend
- Docker if you want to use the wrapper scripts in
mk/
First-time setup
Install frontend dependencies:
cd frontend
npm install
The backend uses Cargo directly, so there is no separate install step.
Run the template in development
Use two terminals.
Terminal 1: frontend dev server
cd frontend
npm run dev
This starts Vite on http://localhost:5173.
Terminal 2: backend API server
cd backend
APP_NAME="My App" \
APP_DOMAIN="http://localhost:5173" \
APP_API="http://localhost:8000" \
cargo run
This starts Axum on http://localhost:8000.
In development:
- you open the app at
http://localhost:5173 - Vite proxies
/api,/static, and/healthzto the Rust backend - the backend still writes runtime config and serves the API
Run the template in production-like mode locally
This is the simplest way to verify the final shape where Rust serves the built frontend itself.
Step 1: build the frontend
cd frontend
npm run build
This writes the static site into frontend/build/.
Step 2: run the backend
cd backend
APP_NAME="My App" \
APP_DOMAIN="http://localhost:8000" \
APP_API="http://localhost:8000" \
cargo run
Now visit http://localhost:8000.
The backend will automatically serve frontend/build/ unless you override APP_PUBLIC_DIR.
Template environment variables
These are the main variables you will care about:
APP_NAME: display name shown in the frontend and backend responseAPP_DOMAIN: public site origin used for runtime config and CORSAPP_API: API origin exposed to the frontendAPP_HOST_IP: optional host IP surfaced in runtime configAPP_STATIC_DIR: where Rust writesconfig.jsonAPP_PUBLIC_DIR: directory of built frontend files that Rust servesPORT: backend listen port, defaults to8000DEBUG: enables a more permissive development CSP
Most apps can leave APP_STATIC_DIR and APP_PUBLIC_DIR alone.
Turn the template into your app
Use this order.
1. Rename the app
Update the obvious defaults first:
backend/Cargo.tomlpackage name if you want a crate name other thanappAPP_NAMEin your local env or deployment env- the page title and copy in
frontend/src/routes/+page.svelte frontend/static/manifest.webmanifest
2. Add backend endpoints
Start in these files:
backend/src/routes/http.rsfor handlersbackend/src/app.rsfor route registrationbackend/tests/template_routes.rsfor integration coverage
Keep /healthz and /static/config.json; they are useful infrastructure endpoints.
3. Add frontend features
Start in these files:
frontend/src/routes/+page.sveltefor the starter pagefrontend/src/lib/for shared frontend codefrontend/src/routes/for new pages and layouts
The frontend already expects runtime config from /static/config.json and a sample backend response from /api/template.
4. Keep the contract clear
When the frontend needs runtime values, put them in backend config and expose them through /static/config.json instead of hardcoding deployment-specific values into the Svelte app.
Testing
Run the main checks before you treat the template as stable.
Frontend
cd frontend
npm run check
npm run build
npm run test -- --run
Backend
cd backend
cargo test
End-to-end wrapper
./mk/test
That wrapper builds the frontend, builds the Docker image, starts the app container, and runs the Playwright suite.
Docker and deployment
The Dockerfile already follows the intended production shape:
- build the frontend into
/app/build - build the Rust binary
- copy the static frontend into
/root/public - run the Rust binary with
APP_PUBLIC_DIR=/root/public
For a single-host setup, inspect:
mk/runmk/deploy-single-vpsinfra/app.nginx.template
Those scripts are opinionated helpers for building, running, and wiring nginx in front of the app.
Common workflows
I changed frontend code and want to test the final integrated app
cd frontend && npm run build
cd ../backend && cargo run
I only changed backend code and want quick feedback
cd backend
cargo test
cargo run
I want the whole stack validated through Docker
./mk/test
Common mistakes
- forgetting to run
npm installinfrontend/ - running the backend for production-like local testing before building
frontend/build/ - setting
APP_DOMAINandAPP_APIto different origins without meaning to - editing generated build output instead of source files under
frontend/src/orfrontend/static/
More docs
docs/api.mdfor backend routes and runtime configdocs/TESTING.mdfor the validation commandsdocs/service-worker.mdfor offline caching behaviordocs/types.mdfor the JSON payload shapesfrontend/README.mdfor the frontend-only quick reference