> ## Documentation Index
> Fetch the complete documentation index at: https://docs.primo.build/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture

> How Primo works under the hood.

Understanding Primo's architecture helps with self-hosting, troubleshooting, and contributing to the project.

## System Overview

**Single Application:**

* SvelteKit frontend + PocketBase backend, all in one binary
* SQLite database stores code and content
* Files (images, uploads) stored in filesystem (or optional S3)
* No microservices, no separate database server
* Minimal operational overhead

**What This Means:**

* One process to run and monitor
* SQLite file contains code/content, filesystem has assets
* Simple backups (database + storage in `pb_data` directory)
* Easy to reason about and debug

## Data Flow

<Columns cols={2}>
  <Card title="Development Workflow">
    <div class="flex justify-center">
      ```mermaid theme={null}
        flowchart TB
          a["1\. Developer writes Svelte block code in CodeMirror"] -->
          b["2\. Code saved to SQLite (site_symbols table)"] -->
          c["3\. Live preview compiles code in browser"] -->
          d["4\. Fields configured and saved to database"] -->
          f["Block available to editors"]
      ```
    </div>
  </Card>

  <Card title="Publishing Workflow">
    <div class="flex justify-center">
      ```mermaid theme={null}
        flowchart TB
          a["1\. User clicks Publish"] -->
          b["2\. Svelte compiler processes all blocks"] -->
          c["3\. Generates static HTML/CSS/JS for each page"] -->
          d["4\. Files written to pb_data/storage/sites/[hostname]/"] -->
          f["Site served as static files"]
      ```
    </div>
  </Card>
</Columns>

## Key Components

### PocketBase

**Role:** Backend, database, auth, file storage, realtime

* SQLite database management
* User authentication and permissions
* File uploads and serving (local filesystem and optinally S3)
* Realtime subscriptions for live updates
* Custom API routes

**Files:**

* Database: `pb_data/data.db`
* Storage: `pb_data/storage/`
* Backups: `pb_data/backups/`

<Info>
  PocketBase can be configured to use S3-compatible storage (AWS S3, Cloudflare R2, etc.) instead of local filesystem for uploaded files. This is useful for scaling.
</Info>

### Svelte Compiler

**Role:** Transforms block code into production JavaScript

**Where it runs:**

* **In the browser** using Web Workers (not server-side)
* Rollup worker for JavaScript bundling
* PostCSS worker for CSS processing

**When it runs:**

* On publish: Compiles all blocks to static files
* In preview: Compiles blocks for live preview
* Not during content edits (content changes don't trigger compilation)

**Process:**

1. Fetches block HTML/CSS/JS from database
2. Injects content variables from fields
3. Compiles in browser worker (parallel processing)
4. Generates static HTML for each page

<Tip>
  Browser-based compilation means no server CPU usage during builds. All compilation happens client-side, making the server lightweight and scalable.
</Tip>

### CodeMirror

**Role:** Code editor for developers

**Features:**

* Syntax highlighting for HTML, CSS, JavaScript
* Autocompletion for field variables
* Error detection
* Keyboard shortcuts (`Cmd/Ctrl + 1/2/3` to switch panes)

### TipTap

**Role:** Rich text editor for content

**Features:**

* WYSIWYG editing with formatting toolbar
* Markdown shortcuts
* Paste from Word/Google Docs
* Link editing

## File Structure

```
pb_data/
├── data.db                     # SQLite database (code, content, config)
├── storage/
│   ├── sites/
│   │   └── [hostname]/         # Published static sites
│   │       ├── index.html      # Home page
│   │       ├── _symbols/       # Compiled JavaScript bundles
│   │       ├── _uploads/       # Media files
│   │       └── [page]/         # Individual page HTML files
│   └── _pbc_xxxxxxxxxx/        # Uploaded files managed per collection
└── backups/                    # Backups
```

## Database Schema

**Key Collections:**

* `sites`: Site configuration and settings
* `site_symbols`: Block code (HTML, CSS, JS)
* `site_symbol_fields`: Field definitions for blocks
* `site_symbol_entries`: Field values/content
* `page_types`: Page type configurations
* `pages`: Individual pages
* `page_sections`: Block instances on pages
* `page_section_entries`: Content for block instances

**Why This Structure:**

* Blocks (symbols) are reusable across pages
* Content (entries) is separate from code (symbols)
* Pages reference blocks via sections
* Supports multi-locale content (entries have locale field)

## How Publishing Works

### Static Site Generation

**Step 1: Compile blocks**

* Fetch all blocks used on the site
* Compile each block's Svelte code
* Generate optimized JavaScript bundles
* Upload bundles

**Step 2: Generate pages**

* For each page, fetch content from database
* Inject content into compiled blocks
* Render to static HTML
* Upload pages

**Step 3: Update static site**

* Copy new and updated JavaScript bundles to `_symbols/`
* Copy new and updated media files to `_uploads/`
* Copy new and updated pages to `[page]/index.html`
* Clean up unused files

**Result:**

* Static HTML files for every page
* Shared JavaScript bundles
* Fast, CDN-friendly output
* No database queries on page load

## Preview vs Published

**Preview (in editor):**

* Compiles blocks on-demand
* Shows unsaved changes
* Uses iframe for isolation
* Hot module replacement for fast updates

**Published (live site):**

* Pre-compiled static files
* No build step on request
* Served directly from file system
* Fast, cacheable responses

## Realtime Updates

Primo uses PocketBase's realtime subscriptions for live collaboration:

**What syncs in realtime:**

* Block code/content changes
* Page structure updates
* User activity indicators
* Field value updates

**How it works:**

* SSE connection to PocketBase
* Receive updates as they happen
* UI updates automatically

## Performance Characteristics

**Database:**

* SQLite is fast for read-heavy workloads
* Single-file makes backups trivial
* No network latency (in-process database)
* Scales to millions of rows

**Publishing:**

* Compile time grows linearly with page count
* \~3-20 seconds for most sites
* Compilation is parallelized in browser workers
* Limited by user's browser/device, not server
* Static output is extremely fast to serve

**Editor:**

* CodeMirror handles large files well
* Preview compilation is cached
* Realtime updates are throttled
* UI stays responsive during saves

## Self-Hosting Considerations

**System Requirements:**

* Docker
* 1GB RAM minimum
* Persistent disk storage

**Scaling:**

* Compilation happens client-side (no server CPU for builds)
* Server only needs to serve API requests and static files
* Horizontal scaling not needed (static output can be served from CDN)
* Database size grows with content (\~1MB per 50 pages)
* Use S3 storage to better integrate with content delivery networks

**Backups:**

* SQLite file contains code/content (`pb_data/data.db`)
* Storage directory contains uploaded files (`pb_data/storage/`)
* Backup both database + storage directory
* Or create and download backup from PocketBase
* If using S3, you only need to backup the database

## Technology Stack Summary

**Frontend:**

* SvelteKit 2
* Svelte 5 (with runes)
* TailwindCSS
* CodeMirror 6
* TipTap 2

**Backend:**

* Golang
* PocketBase
* SQLite 3

**Build Tools:**

* Vite

## Next Steps

<CardGroup cols={2}>
  <Card title="Installation" icon="download" href="/getting-started/installation">
    Set up Primo for development or production.
  </Card>

  <Card title="Core Concepts" icon="lightbulb" href="/getting-started/core-concepts">
    Understand Primo's mental model.
  </Card>
</CardGroup>
