readysite / docs / architecture.md
6.4 KB
architecture.md

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

  1. esbuild bundles frontend/index.js at startup
  2. Entry point exports render, unmount, and named components
  3. {{render "ComponentName" props}} places a mount point
  4. 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
← Back