Architecture
How ReadySite's five layers compose into applications.
Layer Overview
┌─────────────────────────────────────────────┐
│ Your Application │
│ (controllers + models + views) │
├────────┬──────────┬──────────┬──────────────┤
│ Assist │ Frontend │ Platform │ │
│ ant │ (React) │ (Cloud) │ │
├────────┴──────────┴──────────┤ │
│ Application (MVC) │ │
├──────────────────────────────┤ │
│ Database (SQLite) │ │
└──────────────────────────────┘ │
Each layer is independent. Use only what you need:
| Layer | Import | When to Use |
|---|---|---|
| Database | pkg/database |
Always — data persistence |
| Application | pkg/application |
Always — HTTP + templates |
| Frontend | pkg/frontend |
Rich interactivity (editors, charts) |
| Platform | pkg/platform |
Cloud deployment automation |
| Assistant | pkg/assistant |
AI features |
Database Layer
Type-safe SQLite with Go generics.
var DB = engines.NewAuto()
var Posts = database.Manage(DB, new(Post))
Engine Selection
engines.NewAuto() selects based on environment:
DB_URL + DB_TOKEN → Remote replica (Turso/libSQL)
DB_PATH only → Local file
Neither → In-memory
Collection[E]
Generic repository providing CRUD:
Insert → generates UUID, creates record
Get → find by ID
First → single result matching WHERE
Search → multiple results matching WHERE
All → all records
Update → save changes
Delete → remove record
Count → count matching records
All queries use ? parameterized placeholders. SQL uses PascalCase column names matching Go struct fields.
Application Layer
MVC web framework with HTMX/HATEOAS.
Request Lifecycle
HTTP Request
→ Route matching (Go 1.22 ServeMux)
→ Bouncer check (optional guard)
→ Template execution OR handler method
→ Controller.Handle(r) creates per-request copy
→ Template calls controller methods (e.g., {{blog.Posts}})
→ Response written
Key Components
| Component | Purpose |
|---|---|
App |
Central coordinator — views, controllers, routing |
Controller |
Handles HTTP, provides template methods |
Bouncer |
Route guard (auth checks, rate limits) |
Stream |
SSE streaming for real-time updates |
Emailer |
Send templated emails (Resend or logger) |
Template Resolution
views/
├── layouts/ → Pre-loaded at startup
├── partials/ → Pre-loaded, {{template "name.html" .}}
├── static/ → Served as static files
└── **/*.html → Loaded on-demand by filename
Templates reference by filename only: {{template "card.html" .}} not {{template "partials/card.html" .}}.
Frontend Layer
React islands for complex interactivity within server-rendered pages.
Server-Rendered HTML (HTMX)
├── Forms, navigation, content → HTMX
└── Rich components → React islands
├── Editors
├── Charts
└── Dashboards
How Islands Work
- esbuild bundles
frontend/index.jsat startup - Entry point exports
render,unmount, and named components {{render "ComponentName" props}}places a mount point- Client-side hydration attaches React to mount points
In development, HMR (Hot Module Replacement) updates components without page reload.
Platform Layer
Cloud deployment abstraction.
type Backend interface {
CreateServer(opts ServerOptions) (*Server, error)
GetServer(name string) (*Server, error)
DeleteServer(id string) error
CreateVolume(name string, sizeGB int, region Region) (*Volume, error)
// ...
}
Providers
| Provider | Status | Config |
|---|---|---|
| DigitalOcean | Production | DIGITAL_OCEAN_API_KEY |
| AWS | Available | AWS credentials |
| GCP | Available | GCP credentials |
| Mock | Testing | No config needed |
Deployment Flow
infra.json → cmd/launch → SSH → Docker
1. Create server (if --new)
2. Attach volumes
3. Run setup.sh
4. Build Docker image
5. Upload and start container
6. Health check
Assistant Layer
AI provider abstraction for chat completions.
type Backend interface {
Chat(ctx context.Context, req ChatRequest) (*ChatResponse, error)
Stream(ctx context.Context, req ChatRequest) (*StreamReader, error)
}
Providers
| Provider | Models | Config |
|---|---|---|
| OpenAI | GPT-4o, etc. | API key |
| Anthropic | Claude, etc. | API key |
| Mock | Static responses | None |
Tool Calling Flow
User message → AI provider
← Tool call requests
→ Execute tools locally
→ Send results back to AI
← Final response
Package Dependencies
pkg/assistant (independent)
pkg/frontend (independent)
pkg/platform (independent)
pkg/application → pkg/database
pkg/database (independent)
No circular dependencies. Each package can be used standalone.
Applications
Website CMS (website/)
Full-featured CMS with 14 controllers, AI chat, collections, and page management.
- Uses all 5 layers
- 50+ AI tools for content management
- PocketBase-inspired collections with rule-based ACL
- Mutation tracking for undo/redo
Hosting (hosting/)
Managed hosting platform with magic link auth and Docker orchestration.
- Uses Database, Application, Frontend layers
- React Flow dashboard for site management
- Per-site Docker containers with Caddy reverse proxy
- Free (ephemeral) and Pro (persistent) tiers
ReadySite.org (readysite.org/)
Documentation site and Git repository browser.
- Uses Database, Application layers
- Static docs + dynamic Git file browsing
- Minimal controller set (Home, Docker, Git)
Example (example/)
Minimal reference application.
- Uses Database, Application layers
- Single controller, demonstrates core patterns