← All docs
Internal

Backlog

Living list of things the product needs. Ordered roughly by impact. Shipped items move to "Recently shipped" at the bottom.

Backlog

Living list of things the product needs. Ordered roughly by impact. Shipped items move to "Recently shipped" at the bottom.


Loops to close — status

The "loop-incomplete, not feature-incomplete" framing held up. All three primary loops now close with visible receipts.

Loop Status Notes
1 — "I have a site" ✅ done Compile + S3 + CloudFront + ACM + Route53 all live. Build-on-publish per env. Auto-invalidation.
2 — "I can publish content" ✅ done Media uploads land in S3, served via CloudFront at media.preview.staticowl.com. Picker wired. Publish-moment modal with live URL.
3 — "I can trust it" ✅ done Drafts route, scheduler worker, version history modal with restore, publish receipts persisted on BuildEvent nodes.
Continuous AI guide ✅ done Shell-level Guide button; system prompt detects SETUP vs REFINE mode based on site state.

Closure-with-receipts principle is still the lens. Every new surface needs immediate (toast/modal) + persistent (a settings row, an activity log entry, a status field). Don't ship silent success.


Next up (pick one and say go)

Each item is ordered inside so a fresh session can pick it up without archaeology. "Touches" lists files/AWS resources so the scope is transparent.

-1. Artifact pipeline ops (next session)

Architecture is locked. The build pipeline writes content-addressed artifacts to S3 + sharded manifests when STATICOWL_ARTIFACTS_BUCKET is set. The Lambda@Edge resolver code is bundled in packages/build/src/aws/lambda-edge-resolver.js. Next session needs to do the actual ops:

After that lands, the architectural promise ("atomic blue/green deploys, content-addressed artifacts, full replay") is operational end-to-end.

0. AI co-author trio (deferred — architecture took priority)

Three connected plays that complete the Voice Profile loop. Order matters — auto-learn first (unlocks the others by lowering setup cost).

0a. Voice auto-learn (~half day)

Drop the editor's setup time to zero. Pick 5 best posts → AI infers styleGuide + toneTags + vocabulary.use/avoid → editor reviews and accepts. Today the Voice Profile UI is a blank textarea staring at people.

0b. Localization fanout (~1 day)

Fills A26 (per-locale variants) from 6 → 9. Builds on the existing Locale model + bulk-rewrite infra + Voice Profile.

0c. AI co-author in editor (~2-3 days, the headline)

Cursor for content. As the editor types, AI watches the cursor + surrounding text + Voice Profile, offers ghost-text completions; Tab to accept, Esc to dismiss. Editor.js plugin + debounced background fetch.

Why this trio together: 0a unlocks 0b and 0c (both lean on a real Voice Profile). 0b uses 0c's infra path. Skipping 0a means most users will never set up Voice and the rest underperforms. Ship them in sequence; 0a + 0b is a single day, 0c follows.

1. Themes catalogue (biggest product bet)

Built-in theme gallery + AI awareness + swap action. The AI guide already proposes a mantra + theme colours, but users have no way to try on a pre-made aesthetic or change theme without losing content.

2. utils.http + utils.env in the transform sandbox

Unblocks real onPublish webhooks. Today transforms can't hit the network or read secrets. Curated surface only.

3. Activity log

Read-only "who did what, when" for the current site. Right now every meaningful action (publish, deploy, invite, role change) is stamped on a node somewhere — no consolidated view.

4. Typed SDK / codegen

Given a site's schema, emit a TypeScript client users drop into their Next/Astro/Vite frontend.

5. Multi-env promote tool ✅ SHIPPED (architecture phase 3)

The Release/Deployment model makes this trivial: same Release object deploys to staging then prod. UI is the per-env selector on Release detail. No envPublishedAt_<toEnv> copying — Deployments point at the same Release. See /admin/#/releases/:id.

For BULK env-snapshot promote (an entire env's state in one go), the Snapshot mechanism (ADR-0019) supports it; UI surface for "promote everything in dev → staging" is a future polish item.

6. i18n surface

LocaleService is stubbed. Content is single-locale. Turn it on.

7. Notifications (in-app)

Bell icon in the shell header with a dropdown showing recent events relevant to the current user: invitation accepted, build failed, publish scheduled and fired, etc.

8. Backups UI

Engine has per-graph backup/restore (POST /graphs/:name/backup, /restore). UI exposes none of it.

9. Schema polish

The Types editor works for basic fields but several things are rough.

10. Site Settings tabbed page

The current modal covers name/URL/mantra/colours — fine for quick edits. A full page gives room for Domain, Build config, Members, API keys scoped to site, Backups, Danger zone (delete + transfer).


Smaller polish wins (grab bag)


Nice-to-haves / speculative


Handoff context

Everything below is what a fresh session needs to pick this up without re-discovery. Read this first before starting any backlog item.

AWS resources (already provisioned, us-east-1)

Resource Identifier Purpose
S3 bucket staticowl-sites Site builds (<slug>/<env>/...) + media (_media/<siteId>/...). Versioning on. Public ACLs blocked.
CloudFront distribution E3OEFOC02CNC4A (d1739x2ab831n0.cloudfront.net) Serves everything. HTTP/2+3, compression, redirect-to-HTTPS.
CloudFront OAC E1IFGQT7QA43Q7 Only principal the bucket policy allows.
CloudFront Function staticowl-rewrite Host-based routing + /_media/ bypass + //index.html. Source checked into chat history.
ACM cert arn:aws:acm:us-east-1:033776104880:certificate/e5676873-0ad9-4415-a610-50cde4937e20 Wildcard *.preview.staticowl.com, DNS-validated.
Route53 zone Z00980471QQ166640MN6O (staticowl.com.) *.preview.staticowl.com A+AAAA aliased to the distribution.
EC2 instance profile graphiquity-engine-profile / role graphiquity-engine-role Inline policy StaticOwlDeploy grants s3:PutObject/GetObject/DeleteObject/ListBucket on the bucket + cloudfront:CreateInvalidation.
EC2 instance i-078edfedf02808d7a 98.83.66.102. Runs the engine + CMS.

Custom domains per site are Phase-2 — would need a per-site CF distribution + ACM cert provisioned via API.

Environment variables the CMS reads

Var Default Notes
GRAPHIQUITY_ENDPOINT http://localhost:3001 Engine writer. All CMS graph calls go here.
GRAPHIQUITY_ENGINE_SECRET (set in ecosystem.config.cjs) Shared secret — HMAC signs every request.
STATICOWL_BUCKET staticowl-sites Site-build + media bucket.
STATICOWL_REGION us-east-1 Bucket region.
STATICOWL_PREVIEW_HOST preview.staticowl.com Used to compute publicUrl as <slug>-<env>.<host>.
STATICOWL_MEDIA_HOST media.preview.staticowl.com Prefix for uploaded media URLs.
STATICOWL_CF_DISTRIBUTION E3OEFOC02CNC4A Default distribution to invalidate after a deploy.
STATICOWL_BUILD_DIR /opt/staticowl/builds Where the compiler writes HTML before S3 upload.
STATICOWL_SCHEDULER (unset → on) Set to off to disable the in-process scheduler.
ANTHROPIC_API_KEY (set in ecosystem) AI guide uses Sonnet 4.6 with Haiku 4.5 fallback.

File layout (CMS)

packages/
  core/src/crud/
    platform-service.ts     ← Site, SiteEnvironment, PublishConfig, DEFAULT_ENVIRONMENTS
    content-service.ts      ← publishToEnv, unpublishFromEnv, listDrafts, getHistory, restoreAt
    transform-service.ts    ← recordRun, listRuns
    transform-runner.ts     ← node:vm sandbox (add utils.http/env here)
    starter-kits.ts         ← Persona → types + sample content
  server/src/
    build/compile.ts        ← walks content, renders via render.ts, writes HTML
    build/deploy.ts         ← S3 sync + CF invalidation
    build/render.ts         ← shared with preview endpoint (identical HTML)
    routes/build.ts         ← POST /api/build, /build/last, /build/history
    routes/content.ts       ← tree + preview + history + publish + unpublish + restore
    routes/sites.ts         ← AI guide chat/apply + reseed + theme swap (TODO)
    routes/transforms.ts    ← CRUD + /_run + /:id/run + /:id/runs
    scheduler.ts            ← in-process 60s worker for publishAt_<env>
  ui-next/public/js/
    shell/shell.js          ← NAV, persona filtering, Guide button
    shell/onboarding.js     ← persona picker
    shell/bug-reporter.js   ← bug/feature/question submit
    views/content-tree.js   ← /content
    views/content-editor.js ← /content/new, /content/:type/:id
    views/drafts.js         ← /content/_drafts  (must load before content-list.js)
    views/builds.js         ← /builds, /builds/:id
    views/transforms.js     ← /transforms editor + Recent runs tab
    views/site-guide.js     ← /sites/:id/guide (chat + plan pane)
    views/sites.js          ← /sites (list + create modal + settings modal)

Key naming conventions (don't break these)

Deploy

Current scaffolding worth calling out


Recently shipped (newest first)

2026-04-26 — Versioned site compiler architecture (multi-push)

The biggest architectural shift in the project to date. The CMS is now a versioned site compiler underneath the editorial UI.

ADRs locked (in docs/adr/):

Core services shipped:

Server routes:

UI surfaces:

Build pipeline:

Lambda@Edge resolver:

Test coverage: 242/242 passing across 24 test files. New code paths in core (ReleaseService, ReviewService, manifest, selectors, observability, determinism, migration) all unit-tested with mock graph client.

Marketing: docs/positioning.md rewritten for three audiences (editor / engineer / compliance). Four killer demos enumerated.

2026-04-22 — phase 1 Loops + observability

Earlier (Phase 0)

See docs/positioning.md + docs/user-stories.md for the before-state and the competitive comparison.