First cut

This commit is contained in:
kadil
2026-04-17 16:08:31 -05:00
parent d10105ac00
commit 4ee4cb8e7c
58 changed files with 3243 additions and 1 deletions

144
README.md
View File

@@ -1,2 +1,144 @@
# dynamic-sites-simple
# Dynamic Sites
An LLM-powered website editing framework. Edit your site via SMS, a web API, or a visual editor — all driven by natural language.
## Architecture
```
┌─────────────────────────────────────────────────┐
│ Channels │
│ SMS (Telnyx) │ POST /api/edit │ /editor │
└───────┬─────────┴────────┬─────────┴─────┬──────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────┐
│ Orchestrator (Express, port 3001) │
│ │
│ Webhook ──► Idempotency ──► Rate Limit ──► │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ In-Process FIFO Queue (concurrency 1) │
│ │ │ │
│ │ propose: route ► LLM ► proposal │ │
│ │ apply: validate ► writeContentFile│ │
│ └──────────────────────────────────────┘ │
│ │
│ SQLite: idempotency, proposals, rate limits, │
│ audit log │
└───────────────────────┬─────────────────────────┘
│ writes canonical JSON
┌──────────────────┐
│ content/ (JSON) │ ◄── shared volume
│ site-context.json│
└────────┬─────────┘
│ reads with TTL cache
┌──────────────────┐
│ Astro SSR │
│ (port 4321) │
│ Homepage + Editor│
└──────────────────┘
```
## Quick Start
### Prerequisites
- Node.js 22+
- npm
### Local Development
```bash
# Clone and install
npm install
# Start the Astro dev server (port 4321)
npm run dev
# In another terminal, start the orchestrator (port 3001)
npm run dev:server
# Visit http://localhost:4321 — the demo site renders from fixtures
# Visit http://localhost:4321/editor — log in with API_EDIT_SECRET
```
### Environment Variables
Copy `.env.example` to `.env` and set at minimum:
- `API_EDIT_SECRET` — shared secret for API auth and editor login
- `OLLAMA_API_KEY` — required for LLM-powered edits
See `.env.example` for all options.
### Docker
```bash
docker compose build
docker compose up -d
# Site: http://localhost:4321
# Orchestrator: http://localhost:3001/health
```
## Project Structure
```
├── content/ # Canonical JSON content (the "database")
│ ├── sections/ # One JSON file per site section
│ ├── events.json # Upcoming events
│ └── .backups/ # Pre-apply backups (auto-managed)
├── config/
│ └── sms-sites.json # SMS routing allowlist
├── site-context.json # Brand tone, style, LLM prompt context
├── shared/ # Zod schemas + canonical JSON (workspace pkg)
│ └── src/
│ ├── schemas/index.ts # All Zod schemas (the contract)
│ ├── canonical-json.ts # Sorted-key JSON serialization
│ └── repo-validation.ts# Path → schema mapping
├── server/ # Orchestrator (workspace pkg)
│ └── src/
│ ├── index.ts # Entrypoint + graceful shutdown
│ ├── app.ts # Express app factory
│ ├── db.ts # SQLite (idempotency, proposals, audit)
│ ├── logger.ts # Structured logging (pino)
│ ├── queue/ # FIFO queue + job processor
│ ├── routes/ # API edit, SMS webhook, health
│ ├── llm/ # Ollama client with retry/validation
│ ├── sms/ # Telnyx parse, reply, templates
│ └── io/ # Filesystem writer (atomic, with backup)
├── src/ # Astro SSR site
│ ├── pages/
│ │ ├── index.astro # Homepage (renders from content/)
│ │ └── editor.astro # Editor (auth-gated React island)
│ ├── lib/
│ │ ├── site-bundle.ts # Content parser + validator
│ │ └── site-data.ts # Disk reader with TTL cache
│ ├── layouts/
│ │ └── BaseLayout.astro
│ └── components/
│ ├── sections/ # Astro section components
│ └── editor/ # React editor island
├── scripts/ # CLI tools
├── docker-compose.yml # Full stack (web + orchestrator)
├── Dockerfile # SSR site image
└── server/Dockerfile # Orchestrator image
```
## Edit Flow
1. **User sends a natural language message** (SMS, HTTP, or editor)
2. **Route**: LLM determines which content file to edit
3. **Propose**: LLM generates new JSON + plain-language summary
4. **Confirm**: User replies YES/NO (SMS) or clicks confirm (editor/HTTP)
5. **Apply**: Validated JSON is written to disk via atomic write
6. **Live**: Astro SSR picks up the change on next request (TTL cache)
## Key Design Decisions
- **No Redis, no BullMQ**: Simple in-process FIFO queue with concurrency 1
- **No git**: Content persistence is filesystem-only
- **SQLite for everything**: Idempotency, proposals, rate limits, audit log
- **Zod is the contract**: Schemas drive validation at every boundary
- **Atomic writes**: temp file + rename prevents partial writes
- **Pre-write backups**: Last 20 versions per file under `content/.backups/`