Development Guide
This guide shows you how to build your own SaaS application on top of FastSvelte.
Building Your Application
FastSvelte includes an AI Note Improver demo to showcase the platform's capabilities. Here's how to replace it with your own application:
Step 1: Plan Your Application
Define your core business entities and features:
- What is your main domain model? (e.g., Projects, Tasks, Documents, etc.)
- What actions can users perform? (Create, edit, share, export, etc.)
- What billing model will you use? (Per-seat, usage-based, tiered, etc.)
Step 2: Design Your Database Schema
Create Sqitch migrations for your domain:
Edit deploy/your_feature.sql:
-- Example: Replace notes with your domain
CREATE TABLE IF NOT EXISTS fastsvelte.project (
id SERIAL PRIMARY KEY,
organization_id INTEGER NOT NULL REFERENCES fastsvelte.organization(id),
user_id INTEGER NOT NULL REFERENCES fastsvelte."user"(id),
name TEXT NOT NULL,
description TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_project_org ON fastsvelte.project(organization_id);
CREATE INDEX idx_project_user ON fastsvelte.project(user_id);
Deploy your migration:
Step 3: Implement Backend Logic
Follow FastSvelte's layered architecture (use the note implementation as a template):
1. Create models (backend/app/model/your_model.py):
from pydantic import BaseModel
from datetime import datetime
class Project(BaseModel):
id: int
organization_id: int
user_id: int
name: str
description: str | None
created_at: datetime
updated_at: datetime
class ProjectCreate(BaseModel):
name: str
description: str | None = None
2. Create repository (backend/app/data/repo/your_repo.py):
from app.data.db_config import DbConfig
from app.model.your_model import Project
class ProjectRepo:
def __init__(self, db_config: DbConfig):
self.db_config = db_config
self.schema = db_config.schema
async def create_project(self, org_id: int, user_id: int, data: ProjectCreate) -> int:
query = f"""
INSERT INTO {self.schema}.project (organization_id, user_id, name, description)
VALUES ($1, $2, $3, $4)
RETURNING id
"""
return await self.db_config.fetch_val(query, org_id, user_id, data.name, data.description)
async def get_by_id(self, project_id: int) -> Project | None:
query = f"SELECT * FROM {self.schema}.project WHERE id = $1"
row = await self.db_config.fetch_one(query, project_id)
return Project(**row) if row else None
3. Create service (backend/app/service/your_service.py):
from app.data.repo.your_repo import ProjectRepo
from app.model.your_model import Project, ProjectCreate
class ProjectService:
def __init__(self, project_repo: ProjectRepo):
self.project_repo = project_repo
async def create_project(self, org_id: int, user_id: int, data: ProjectCreate) -> Project:
project_id = await self.project_repo.create_project(org_id, user_id, data)
project = await self.project_repo.get_by_id(project_id)
return project
4. Create API routes (backend/app/api/route/your_route.py):
from fastapi import APIRouter, Depends
from app.service.your_service import ProjectService
from app.model.your_model import Project, ProjectCreate
from app.util.auth_util import CurrentUser, get_current_user
router = APIRouter(prefix="/api/project", tags=["project"])
@router.post("", response_model=Project)
async def create_project(
data: ProjectCreate,
current_user: CurrentUser = Depends(get_current_user),
project_service: ProjectService = Depends()
):
return await project_service.create_project(
current_user.organization_id,
current_user.id,
data
)
5. Register in DI container (backend/app/config/container.py):
# Add to Container class
self.project_repo = providers.Factory(ProjectRepo, db_config=self.db_config)
self.project_service = providers.Singleton(ProjectService, project_repo=self.project_repo)
# Add to wiring_config
wiring_config = containers.WiringConfiguration(
modules=[
"app.api.route.your_route", # Add this
# ... existing modules
]
)
6. Register route (backend/app/main.py):
7. Run the backend server to test your new API:
Step 4: Build Frontend UI
1. Create API client types:
2. Create Svelte pages (replace frontend/src/routes/(protected)/notes/ with your feature):
<!-- frontend/src/routes/(protected)/projects/+page.svelte -->
<script lang="ts">
import { projectApi } from '$lib/api/gen/projects';
import { onMount } from 'svelte';
let projects = $state([]);
onMount(async () => {
const response = await projectApi.listProjects();
projects = response.data;
});
</script>
<h1>My Projects</h1>
{#each projects as project}
<div>{project.name}</div>
{/each}
Step 5: Remove Demo Code
If you've finished setting up your project, clean up the note demo:
# Remove note files
rm backend/app/model/note_model.py
rm backend/app/service/note_service.py
rm backend/app/service/note_organizer_service.py
rm backend/app/api/route/note_route.py
rm -rf frontend/src/routes/(protected)/notes
# Remove note migrations
cd db
sqitch revert --to @HEAD^ # Or manually remove note-related migrations
# Remove OpenAI dependency if not needed
# Edit backend/requirements.in and remove openai
Common Development Workflows
When making changes, follow the DB → Backend → Frontend flow:
Database Changes
cd db
sqitch add feature_name -n "Description"
# Edit deploy/, revert/, verify/ SQL files
./sqitch.sh dev deploy
Backend Changes
cd backend
source .venv/bin/activate
# Add or remove dependencies
# Edit requirements.dev.in (for development) or requirements.in (for production), then:
pip-compile --no-strip-extras requirements.dev.in
pip install -r requirements.dev.txt
# Run linter
ruff check .
# Run tests
pytest
# Start server (auto-reloads on code changes)
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
Frontend Changes
After backend API changes, regenerate the API client:
cd frontend
# Generate TypeScript client (backend must be running)
npm run generate
# Run linter and formatter
npm run format # Prettier
npm run check # Type checking
# Run tests
npm run test # All tests
npm run test:unit # Unit tests only
npm run test:e2e # E2E tests only
# Start dev server (hot-reloads on code changes)
npm run dev
Next Steps
- Tutorials - Step-by-step guides for common tasks
- Architecture Overview - Understand the codebase structure
- Troubleshooting - Common issues and solutions
- Deployment - Deploy to production