From aebbcf5b472d7e4fa12cd756b343f1092677e894 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Sun, 19 Apr 2026 16:52:25 -0400 Subject: [PATCH] docs: add AI agent bootstrap / quickstart document Concise onboarding doc covering: project overview, critical rules (IDAA privacy, no-rm, svelte-check), env/deploy cheat sheet, Svelte 5 runes patterns, V3 API patterns, naming conventions, real past mistakes, source layout, and reading order for deeper dives. Co-Authored-By: Claude Sonnet 4.6 --- .../BOOTSTRAP__AI_Agent_Quickstart.md | 300 ++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 documentation/BOOTSTRAP__AI_Agent_Quickstart.md diff --git a/documentation/BOOTSTRAP__AI_Agent_Quickstart.md b/documentation/BOOTSTRAP__AI_Agent_Quickstart.md new file mode 100644 index 00000000..b25b0e5e --- /dev/null +++ b/documentation/BOOTSTRAP__AI_Agent_Quickstart.md @@ -0,0 +1,300 @@ +# Aether SvelteKit — AI Agent Bootstrap / Quickstart +> **Read this first.** This doc is the fast path to being productive on this project. +> It covers the rules, patterns, and gotchas that matter most. +> Deep dives are in the linked docs at the bottom. + +--- + +## 1. What This Project Is + +**Aether** is an event management platform built by One Sky IT (Scott Idem). +This repo is the frontend: **Svelte 5 (runes mode) + SvelteKit v2**. + +The backend is a separate repo (`aether_api_fastapi`) — a FastAPI + MariaDB app +running in Docker. The frontend talks to it exclusively via the V3 REST API. + +**Key clients:** +- **Conference organizers** — Presentation Management (pres_mgmt), Launcher, Badges +- **Exhibitors** — Leads capture +- **IDAA** — International Doctors in Alcoholics Anonymous (private medical/recovery community) + +**Stack at a glance:** + +| Layer | Technology | +|---|---| +| Framework | Svelte 5 (runes mode) + SvelteKit v2 | +| Styling | Tailwind CSS v4 + Flowbite (Skeleton UI being phased out) | +| State | `$state`/`$derived` runes + Dexie.js IndexedDB (`liveQuery`) | +| Icons | Lucide (`@lucide/svelte`) | +| Editors | CodeMirror 6 (primary), Edra/TipTap (secondary) | +| Native | Electron app for onsite launcher (`src/lib/electron/electron_relay.ts`) | +| Backend | FastAPI + MariaDB, V3 API (`/v3/crud/`, `/v3/lookup/`) | +| Auth | Custom headers: `x-aether-api-key` + `x-account-id` (no Bearer tokens) | + +--- + +## 2. Critical Rules — Read Before Touching Any Code + +### Privacy (Sev-1 class failures if violated) +- **IDAA content is ALWAYS private.** All routes under `/idaa/` require authentication. + A previous AI agent accidentally made IDAA bulletin board data publicly accessible. + This is the single most serious class of mistake on this project. When in doubt — it's private. +- **Journals** are private personal data. Always authenticated. + +### File Safety +- **Never use `rm`** to delete files. Move to `~/tmp/gemini_trash` instead. +- Never commit `.env` files, API keys, or passwords. + +### Before Every Commit +- Run `npx svelte-check` — zero errors, zero warnings. No exceptions. +- Atomic commits: one component or one fix per commit. + +### Before Starting Any Task +- Read `documentation/TODO__Agents.md` — it has active tasks, known bugs, and context + about what was recently changed and why. + +### V3 API — Never Include the Object ID in PATCH Body Fields +The ID is in the URL. Including it in `data_kv` causes a `400: Unknown column in SET`. +```ts +// WRONG — causes 400 error: +update_ae_obj__event_file({ event_file_id, data_kv: { event_file_id, file_purpose: 'final' } }) + +// CORRECT: +update_ae_obj__event_file({ event_file_id, data_kv: { file_purpose: 'final' } }) +``` + +--- + +## 3. Environment & Deploy Cheat Sheet + +There are **two separate `.env` systems** — do not confuse them: + +| System | File | Controls | +|---|---|---| +| `aether_container_env/.env` | Docker orchestration | Ports, `AE_CFG_ID`, replicas, paths | +| `aether_app_sveltekit/.env.*` | Vite/SvelteKit build | `PUBLIC_*` API vars baked into the JS bundle | + +**The 4 commands you run and which env file each uses:** + +| Command | Env file read | +|---|---| +| `npm run dev` | `aether_app_sveltekit/.env.local` (Vite dev server, localhost:5173) | +| `npm run build:docker:dev` | `aether_app_sveltekit/.env.dev` (baked into local Docker image) | +| `npm run deploy:remote:test` | `/srv/apps/test_aether_app_sveltekit/.env.test` on Linode | +| `npm run deploy:remote:prod` | `/srv/apps/prod_aether_app_sveltekit/.env.prod` on Linode | + +**The `.env.*` files are gitignored** (only `.default` templates are tracked). They must be +placed manually on each server during initial setup. On the workstation you only need +`.env.local` and `.env.dev`. The Linode servers each have exactly one env file for their environment. + +**What goes in every SvelteKit env file** (same 8 vars, different values per env): +```env +PUBLIC_AE_API_PROTOCOL=https +PUBLIC_AE_API_SERVER= +PUBLIC_AE_API_BAK_SERVER= +PUBLIC_AE_API_PORT=443 +PUBLIC_AE_API_PATH= +PUBLIC_AE_API_SECRET_KEY= +PUBLIC_AE_CRUD_SUPER_KEY= +PUBLIC_AE_BOOTSTRAP_KEY= +PUBLIC_AE_NO_ACCOUNT_ID=No_Account_ID_Here +``` + +--- + +## 4. Svelte 5 Runes Mode — Key Patterns & Gotchas + +This codebase is **fully Svelte 5 runes mode**. No Svelte 4 syntax. + +### The basics +```svelte + +``` + +### What NOT to use (Svelte 4 patterns — do not introduce) +```ts +// ❌ No writable() stores for component state +import { writable } from 'svelte/store'; + +// ❌ No reactive declarations +$: doubled = count * 2; + +// ❌ No onDestroy for cleanup — use $effect return instead +onDestroy(() => cleanup()); +``` + +### `$bindable()` vs `$state()` +- Use `$bindable()` when the parent needs two-way binding on a prop. +- Use `$state()` for local component state with no external binding. + +### Store reactivity trap (important for `$effect`) +The app uses `svelte-persisted-store` (Svelte 4 contract) for `$ae_loc`, `$ae_api`, +`$ae_sess`, etc. In Svelte 5 `$effect`, reading **any field** of a Svelte 4 store +subscribes to the **entire store**. This means unrelated writes to `$ae_loc` +(e.g. iframe height, SWR reload) will re-trigger your effect. Be conservative about +what you read from these stores inside `$effect` blocks. See `PROJECT__Stores_Svelte5_Migration.md` +for the long-term fix plan. + +### `{#await}` blocks +```svelte +{#await somePromise} + +{:then result} +
{result}
+{:catch error} + +{/await} +``` + +--- + +## 5. V3 API Patterns + +### SWR (Stale-While-Revalidate) — the standard load pattern +Return cached Dexie data immediately, refresh from API in background. +```ts +async function load_ae_obj_id__my_obj({ api_cfg, obj_id }) { + // 1. Return stale cache immediately (fast) + const cached = await db.my_obj.get(obj_id); + if (cached) my_obj_state = cached; + + // 2. Fetch fresh from API in background + _refresh_my_obj_background({ api_cfg, obj_id }); +} +``` + +### ID convention — never use `_id_random` fields +The V3 API uses random string IDs (e.g. `event_file_id = "aBc123"`). The `*_id_random` +fields are legacy aliases. Always use the short form: +```ts +// ✅ Correct +event_file_obj.event_file_id + +// ❌ Wrong — legacy alias, don't use +event_file_obj.event_file_id_random +``` + +### PATCH — only field values in the body +```ts +// The obj_id goes in the URL (handled by update_ae_obj__* function). +// Only the fields you want to update go in data_kv. +await events_func.update_ae_obj__event_file({ + api_cfg: $ae_api, + event_file_id: 'aBc123', // → becomes the URL path param + data_kv: { file_purpose: 'final' } // → only changed fields +}); +``` + +### Auth headers (set automatically by `api.ts`) +``` +x-aether-api-key: +x-account-id: +``` + +--- + +## 6. Naming Conventions + +| Pattern | Example | Used for | +|---|---|---| +| `ae_comp__*` | `ae_comp__event_badge.svelte` | Route-level components | +| `ae__comp__*` | `ae_events_comp__session_list.svelte` | Module-scoped components | +| `element_*` | `element_input_files_tbl.svelte` | Reusable library primitives | +| `lq__*` | `lq__journal_obj` | Read-only liveQuery | +| `lqw__*` | `lqw__journal_obj` | Writable form snapshot liveQuery | +| `ae___.ts` | `ae_journals__journal.ts` | Object type + functions | +| `db_.ts` | `db_journals.ts` | Dexie instance per module | + +The **canonical pattern reference** is the Journals module (`src/lib/ae_journals/`). +When building anything new, model it after Journals. + +--- + +## 7. Mistakes Agents Have Made on This Project + +These are real incidents — know them before you start. + +1. **IDAA BB exposed publicly** — an agent removed an auth guard from the bulletin board + route. All IDAA content must be behind authentication. Always check route guards when + touching `/idaa/` routes. + +2. **`event_file_id` in PATCH body (400 error)** — including the object ID in `data_kv` + when calling `update_ae_obj__*`. The V3 API tries to `SET event_file_id = ...` which + fails because it's a view alias, not a DB column. See Section 2 above. + +3. **Bad `.d.ts` declaration silently hid 1368 errors** — a `declare module` in `app.d.ts` + (a script-context file) replaced the entire `@lucide/svelte` type exports instead of + merging. `svelte-check` showed 0 errors, masking real problems. If `svelte-check` + suddenly drops to 0 errors, verify it's not because a bad declaration wiped a module. + +4. **Coarse store reactivity loop** — an `$effect` that read `$ae_loc.some_field` was + re-triggering repeatedly because unrelated writes to `$ae_loc` (e.g. SWR config reload) + fired the effect. In Svelte 5, any read of a Svelte 4 store inside `$effect` subscribes + to the whole store. Scope what you read carefully. + +5. **`file_purpose == 'admin'` not hidden in Launcher** — the `hide_draft` prop hid + `outline` and `draft` files but not `admin` files. Gaps like this happen when a new + enum value is added to a field without auditing all the places that filter on it. + +6. **Deleting files with `rm`** — always move to `~/tmp/gemini_trash`. A deleted file may + contain context that's not recoverable from git if it was gitignored. + +--- + +## 8. Source Layout (Quick Reference) + +``` +src/lib/ + ae_api/ — API helpers (V3 preferred) + ae_core/ — Account, User, Person, Site, hosted files + ae_events/ — Events, sessions, presenters, badges, locations, files + ae_journals/ — Journals (canonical/frontier model — copy patterns from here) + ae_idaa/ — IDAA custom module (PRIVATE — always authenticated) + elements/ — Reusable UI: V3 field editor, data store, CodeMirror, QR scanner + electron/ — Native Electron bridge (electron_relay.ts) + stores/ — ae_stores.ts, ae_events_stores.ts, ae_idaa_stores.ts + +src/routes/ + /core/ — Admin (accounts, people, sites, users) + /events/[id]/ + /(pres_mgmt)/ — Presentation management + /(launcher)/ — Event launcher (kiosk display) + /(badges)/ — Badge printing + /(leads)/ — Exhibitor leads + /journals/ — Journals + /idaa/ — IDAA module (PRIVATE) + /hosted_files/ — File management +``` + +--- + +## 9. Reading Order for Deeper Dives + +Start here, then go deeper as needed: + +| What you need | Read | +|---|---| +| Active tasks + known bugs | `documentation/TODO__Agents.md` ← always first | +| Dev workflow + commit rules | `documentation/GUIDE__Development.md` | +| V3 API reference | `documentation/GUIDE__AE_API_V3_for_Frontend.md` | +| Dexie / liveQuery patterns | `documentation/GUIDE__SvelteKit2_Svelte5_DexieJS.md` | +| Svelte 5 patterns + pitfalls | `documentation/GEMINI__Svelte_and_Me.md` | +| Permissions + auth levels | `documentation/AE__Permissions_and_Security.md` | +| Electron / native launcher | `documentation/PROJECT__AE_Events_Launcher_Native_integration.md` | +| Store migration plan | `documentation/PROJECT__Stores_Svelte5_Migration.md` | +| Exhibitor Leads module | `documentation/MODULE__AE_Events_Exhibitor_Leads.md` | +| Naming conventions | `documentation/AE__Naming_Conventions.md` |