Architecture Overview
This document describes the technical architecture of FastSvelte, a fullstack SaaS starter kit built with FastAPI and SvelteKit.
System Architecture
FastSvelte is organized as a monorepo containing four main components:
fastsvelte/
├── backend/ # FastAPI + Python (API server)
├── frontend/ # SvelteKit + TypeScript (Admin dashboard)
├── landing/ # SvelteKit (Marketing website)
├── db/ # PostgreSQL + Sqitch (Database migrations)
└── docs/ # MkDocs documentation
Component Interaction Flow
graph TB
U[Users] --> L[Landing Page]
U --> F[Frontend Dashboard]
F --> B[Backend API]
B --> D[PostgreSQL Database]
B --> E[External Services]
E --> S[Stripe, SendGrid, OAuth]
Backend Architecture (FastAPI)
The backend is structured in layers to separate HTTP handling, business logic, and data access.
Layer Structure
app/
├── main.py # Application entry point
├── config/ # Settings & dependency injection
├── api/ # HTTP layer
│ ├── route/ # API endpoints
│ ├── middleware/ # Request/response middleware
│ └── router.py # Route registration
├── service/ # Business logic layer
├── data/repo/ # Data access layer
├── model/ # Request/response models
├── util/ # Shared utilities
└── exception/ # Custom exceptions
Key Design Patterns
Dependency Injection
The application uses dependency-injector
to manage component dependencies. Services and repositories are injected rather than instantiated directly, which enables easier testing and loose coupling. Configuration is handled in app/config/container.py
.
Repository Pattern
Database operations are encapsulated in repository classes located in app/data/repo/
. These repositories return Pydantic models rather than raw database records. Examples include UserRepo
and OrganizationRepo
.
Service Layer
Business logic resides in service classes in app/service/
. Services coordinate between repositories, handle validation and authorization, and implement application workflows.
Request Flow
flowchart LR
A[HTTP Request] --> B[Route] --> C[Service] --> D[Repository] --> E[Database]
B -.-> F[Validation]
C -.-> G[Business Logic]
Frontend Architecture (SvelteKit)
The frontend is a Single Page Application built with SvelteKit that handles authentication through API calls.
Directory Structure
src/
├── routes/ # SvelteKit file-based routing
│ ├── (auth)/ # Login, signup, password reset
│ ├── (protected)/ # Dashboard, admin pages
│ └── +layout.svelte # Global layout
├── lib/
│ ├── api/ # Generated API client
│ ├── auth/ # Authentication state
│ ├── components/ # Reusable UI components
│ └── utils/ # Shared utilities
└── app.html # Root HTML template
Key Features
1. Session-Based Authentication
- Backend creates HTTP-only session cookies (not JWT tokens)
- With each API call, browser automatically sends the session cookie (see:
frontend/src/lib/api/axios.js
) - Frontend checks authentication by calling
/users/me
endpoint (see:frontend/src/lib/auth/session.ts
) - Auth state managed with Svelte 5 runes in client-side store (see:
frontend/src/lib/auth/auth.svelte.ts
) - When API returns 401, frontend automatically clears auth state and redirects to login (see:
frontend/src/lib/api/axios.js
) - Cross-tab session synchronization via BroadcastChannel API (see:
frontend/src/lib/auth/session.ts
) - Rate-limited authentication checks to prevent excessive API calls (see:
frontend/src/lib/auth/session.ts
)
API Client Generation
The TypeScript API client is generated using Orval, which reads the backend's OpenAPI specification and creates type-safe request functions. This provides compile-time type checking for all API interactions. Generated code is located in src/lib/api/gen/
.
Route Protection
Routes are organized into two groups: (auth)
for public pages like login and signup, and (protected)
for authenticated areas. The (auth)
layout redirects already-authenticated users to the dashboard (see: frontend/src/routes/(auth)/+layout.svelte
). The (protected)
layout calls ensureAuthenticated()
on mount to verify the user's session (see: frontend/src/routes/(protected)/+layout.svelte
).
Both layouts use reactive authStore.isAuthenticated
checks to show appropriate content or loading states. When the API returns a 401 error, the axios interceptor automatically clears the auth state and redirects to login (see: frontend/src/lib/api/axios.js
). The backend validates sessions on every API request, ensuring data security regardless of frontend state.
State Management
// Auth store using Svelte 5 runes
class AuthStore {
user = $state<UserWithRole | null>(null);
isLoading = $state(true);
get isAuthenticated(): boolean {
return this.user !== null;
}
}
Database Architecture
The application uses PostgreSQL with Sqitch for schema version management.
Schema Design
The database schema centers around users and organizations for multi-tenancy. Core tables include user
for authentication, organization
for tenant separation, role
for permissions, and session
for active user sessions. Business logic is supported by tables like plan
for subscriptions, organization_plan
for current subscriptions, settings tables (user_setting
, organization_setting
, system_setting
) for configuration, and invitation
for team member invitations.
Migration Management
Database schema changes are managed through Sqitch migrations in the db/
directory, with deploy/
scripts for forward changes, revert/
scripts for rollbacks, and verify/
scripts for validation.
Multi-Tenancy
The system supports both B2B (multiple users per organization) and B2C (one user per organization) modes. Data isolation is enforced through organization_id
foreign keys. The mode is configured via the FS_MODE
environment variable.
Authentication & Security
Session Management
sequenceDiagram
participant F as Frontend
participant Br as Browser
participant B as Backend
participant D as Database
Note over F,D: User Login Flow
F->>Br: POST /auth/login (credentials)
Br->>B: Forward request
B->>D: Validate user credentials
D-->>B: User data
B->>D: Create session record
B->>B: Generate session token & hash it
B-->>Br: Set HTTP-only cookie + response
Br-->>F: Login success response
Note over F,D: Authenticated Request Flow
F->>Br: API request (withCredentials: true)
Br->>B: Request + session cookie
B->>B: Extract & validate cookie
B->>D: Check session exists & not expired
D-->>B: Session valid
B-->>Br: Protected data response
Br-->>F: Forward response
Note over F,D: Session Validation
F->>Br: GET /users/me (check auth status)
Br->>B: Request + session cookie
B->>D: Validate session
D-->>B: User + role data
B-->>Br: Current user response
Br-->>F: Forward response
F->>F: Update authStore.user
Security Implementation:
Session cookies are configured as HTTP-only with secure and SameSite settings to prevent XSS and CSRF attacks. Session tokens are stored hashed in the database and expire automatically. CORS protection is enabled with configurable allowed origins.
Authorization
The system implements role-based access control with three roles: member
for basic user permissions, org_admin
for organization management, and sys_admin
for system-wide administration.
API endpoints are protected using FastAPI's Depends(get_current_user)
dependency injection pattern. Role validation occurs at the service layer before processing requests.
External Integrations
The application integrates with third-party services for email, payments, and authentication.
Email (SendGrid)
Transactional emails for account verification and password reset are sent via SendGrid. Email templates are managed through the SendGrid dashboard, with environment-specific sender configurations.
Payments (Stripe)
Stripe handles subscription billing, including webhook processing for payment events, plan changes, and usage tracking. The integration supports both subscription and usage-based billing models.
OAuth (Google)
Google OAuth provides social login functionality. The implementation uses secure state parameters to prevent CSRF attacks and synchronizes user profile information from Google accounts.
Development Workflow
Type Safety
Type consistency is maintained from backend to frontend through code generation. Backend Pydantic models define the data structures, FastAPI automatically generates an OpenAPI specification, and Orval converts this specification into TypeScript client functions.
API Generation Flow
The development workflow involves three steps: updating backend models or endpoints, running npm run generate
to regenerate the TypeScript client, and using the generated client in frontend code.
Environment Configuration
The application supports three deployment environments: dev
for local development with Docker containers, beta
for staging and pre-production testing, and prod
for the live application.
Testing Strategy
Backend testing uses pytest for unit tests, repository tests run against a test database, and service tests use mocked dependencies. Frontend testing includes unit tests with Vitest, component tests using Vitest browser mode, and end-to-end tests with Playwright.
Configuration Management
Environment Variables
All configuration uses the FS_
prefix:
# Database
FS_DB_URL="postgres://..."
# Authentication
FS_JWT_SECRET_KEY="..."
# External services
FS_STRIPE_API_KEY="sk_..."
FS_SENDGRID_API_KEY="SG..."
Settings Architecture
The application implements a three-tier settings hierarchy: system settings for global configuration (stored in system_setting
+ system_setting_definition
tables, managed via /admin/settings
), organization settings for per-tenant configuration (using organization_setting
+ organization_setting_definition
tables), and user settings for individual preferences (using user_setting
+ user_setting_definition
tables, managed via /settings/user
).
Settings do not cascade or fallback between levels. Each scope maintains explicit values for security and predictability.