stnd.buildSTANDARD MANUAL2026-07-15

Garden

The Garden

The expression. Where the Vault becomes public — beautifully.

Pastebin for Prose. The fastest way from thought to a beautiful URL — paste any text (or a roll of photos), get a gorgeous page in ~10 seconds, no account needed. The publication of the Standard ecosystem: built on @stnd/* (packages/README.md), fed by the Vault (vault/README.md), served from the Cloudflare edge. The concept rests on File over Web — everything is defined inside the user’s vault, shaped by the Standard.

A utility, not a platform — like WeTransfer for files. Nature at its best: the organized
chaos — everything can change, anything can happen, the garden can be messy. Beliefs:
speed is respect · beauty is default · friction is the enemy · sustainable by
architecture
(10k users for <$200/mo). The file stays yours; the Garden just shows it
well, then gets out of the way. Lives at standard.garden. The bridges that carry the
Vault to the Garden: garden-obsidian (Obsidian plugin) and garden-mac.

Agent quick context (start here)

Use this section as the fast onboarding layer before touching code.

1. Product in one line

stnd.gd is the production Garden app: paste/publish notes, render beautifully, manage ownership/visibility, and serve at edge scale.

2. Where to work (first map)

Need Go first
Core domain logic (notes, users, permissions) modules/core/
Editor experience modules/editor/
Note rendering routes modules/note/
Search / relation features (Mycelium, related) modules/* + Vectorize integrations in core models/routes
Static assets and edge static config public/
Scheduled cleanup jobs workers/compost/
Minimal Astro-required wiring src/ (keep thin)

3. High-risk zones (read before edits)

  1. Note visibility and ownership logic (public/unlisted/private).
  2. Profile-note behavior (permalink: "/") and slug resolution.
  3. Destructive flows (unpublish/delete, storage cleanup, compost worker).
  4. Auth/billing edge wiring (session assumptions, Stripe/webhook flows).

4. Local commands (daily use)

pnpm install
pnpm dev               # Astro dev server (port 8089)
pnpm dev:all           # Astro + Wrangler SSR context
pnpm build             # production build validation
pnpm db:reset:local    # reset local D1

5. Guardrails for agents

  • Keep committed docs/code in English.
  • Prefer edits inside modules/; keep src/ minimal.
  • Do not add backward-compat shims.
  • Update this README when behavior, architecture, or ops change.
  • Treat edge/data changes as production-sensitive (D1/R2/Vectorize/Workers).

Where it’s at — now

~85% done — the core loop is solid and in production (write -> parse frontmatter -> temperament -> HTML -> edge). The code is clean (approx. 3 TODO/FIXME total). 20 modules active, 1 dormant (_domain-extended), 10 migrations (0000-0009). Automated tests are running in Vitest for core/domain slices (modules/core/models and modules/domain-extended). (First production version deployed on 2026-06-23).

Working today:

  • Anonymous notes (no account, 7-day expiry) · accounts (email OTP, Google) · API keys.
  • Note ownership + visibility (public / unlisted / private — default private).
  • Backlinks (SQL) + related notes (Mycelium — Vectorize embeddings).
  • Ask Garden (RAG / Discussion) — semantic discussion over your notes via Cloudflare Workers AI (llama-3.1-8b-instruct) and Vectorize.
  • The profile note — the root note (permalink: "/") is the garden’s home (frontmatter
    cascades garden-wide design, body renders at /@user). Live since 2026-06-15.
  • Custom-domain home — dogfood francisfontaine.com renders the owner’s garden in place.
  • Export (md / ZIP / whole garden) · RSS per garden · OG images · dynamic theme CSS · CDN.
  • The Obsidian bridge (garden-obsidian) — account connect from the plugin,
    bulk-publish progress modal, the “magic” status icon.
  • Billing configured and operational (Stripe – Checkout + Portal + signed webhook; configured with price price_1TlLadL6cyLS8r6dTMZ3rewZ on 2026-06-23).

The remaining ~20% is the door (anonymous homepage polish — the first 10 seconds), the profile note’s security role, and production ops. See What’s next.

How we got here — history

Built on @stnd/core. The profile-note model shipped 2026-06-15; custom-domain dogfood followed. The Obsidian plugin was reframed as two products under the Standard umbrella — Atelier (local studio: themes, snippets, writing — no account, works offline) and Garden (the web bridge: account, publish, sync). Recent sessions hardened the vertical rhythm (robust to empty <div>s), revived dead launcher commands (manifest launcher: key was unread → migrated to hooks["launcher:action"]), added account-connect from the plugin, the magic status icon, the bulk-publish progress modal, code syntax-highlighting in reading view, and scroll-only header reveal. The note route was also slimmed by moving ::download behavior/styling and header note-action handlers into the note module, and password-gate state resolution into password-gate/server, keeping route files focused on orchestration. Launcher login reliability was hardened by making account-level ::login view registration collision-safe (override: true) so app-specific login views do not break global launcher click handling. The stnd.gd footer brand column now explicitly renders Garden via modules/core/layouts/Footer.astro (<StandardFooter title="Garden">) instead of inheriting broader config naming. The homepage writer now uses full available width (--line-width: 100%) so the editor surface spans the browser layout without changing editor-route behavior. Guide routing/linking was normalized: the index now uses /guide/* canonical links, legacy /docs/* URLs are redirected to current guide permalinks, and guide loaders now target the default structured sections (1-philosophy2-getting-started3-protocols) instead of the narrative 1-chapters content set.

What’s next — open

Editor

  • [ ] Remove the title field… not used anymore and it conflict the note that have one inside

Profile note

  • [x] Role #3 — garden-wide ​```css blocks. Gated on origin isolation → ships with
    custom domains: free CSS only on a custom domain / dedicated subdomain; the shared origin standard.garden/@user keeps sanitized tokens only (arbitrary CSS is an attack surface).

Moderator panel (3 stubs in ModeratorView.svelte)

  • [ ] Notes view
  • [ ] User management
  • [ ] Activity log
  • [ ] all “coming soon”.

Custom domains (_domain-extended) — gated on billing

  • [ ] Real ownership verification (verifyCustomDomain currently just flips a flag).
  • [ ] Cloudflare for SaaS (custom-hostname API) for client domains (never on the CF account).
  • [ ] Reactivate _domain-extended; cookie / origin-isolation hygiene.

Ops to ship

  • [x] Deploy the compost worker (wrangler deploy from workers/compost/, then wrangler tail). (Deployed on 2026-06-23).
  • [x] Apply remote migrations 0008 (rate_limits) + 0009 (seed_showcase). (Verified on 2026-06-23).
  • [x] Stripe — create the product + set keys (docs/stripe-setup.md) to activate billing. (Configured on 2026-06-23).
  • [ ] Passkeys — one FaceID/TouchID test on a real device (code complete in @stnd/account).

The door (the 20% — visibility)

  • [ ] QA the anonymous paste → URL home as a stranger with no session (the first 10 seconds).
  • [ ] stnd.build landing page — the framework’s public face (separate track).

Quality / debt

  • [ ] Tests — none yet. At minimum: slug resolution, note permissions, profile cascade.
  • [ ] content.config.ts — the R2 integration is still a placeholder (guide docs are module-local content under modules/guide/content, not an Astro docs collection).
  • [ ] pnpm test currently fails because Vitest cannot resolve @stnd/account/models/User.js from modules/core/models/User.ts (import resolution mismatch in test runtime).
  • [ ] Update packages after reviewing changelogs.

Plugin UX (Atelier / Garden)

  • [x] Group the 10 flat settings tabs into Atelier / Garden families; move inline nav
    styles to a class; visual separator between the two.
  • [x] Enrich the connected-account card with real server stats (last sync, views).
  • [ ] Magic-icon sub-item: a modal when publishing without the right key.
  • [ ] The magic icon that acts as a status, could be nice to have a dropdown for its use in the parameters,… Hide – Tab bar – Status bar. That way user can have it either very accessible or following the obsidian interface philosophy
  • [ ] Verify the graft: top-level manifest key isn’t dead (same cause as the old launcher:
    bug) — the “Quote Selection” toolbar may not fire. It does fire, but almost to often.. need to talk about it, might be good if it dont trigger on “system button or menu” but only on content that reside inside a .prose
    • [ ] Take a look at the editor floating bar in the editor, should offer the italic bold and etc options.

Bulk publish — “upload my whole photo portfolio with confidence”

Driving criterion = confidence: see it progress · re-run without re-uploading everything · know nothing is missing.

  • [ ] Image dedup by content hash (CDN URL = hash) — fast re-sync, quota preserved.
  • [ ] Throttle aware of rate limits (publish 60/min, attachments 30/min) + retry/backoff on 429.
  • [ ] Resumption — skip notes whose content hash hasn’t changed.
  • [ ] Post-sync reconciliation — diff vault ↔ garden (“487 notes + 2310 images online, 0 missing”).

Misc

  • [ ] Remove image-zoom on mobile
  • [ ] support ==highlight==
  • [ ] power-user “space → next
  • [ ] media / screen separation” syntax
  • [ ] a “Bear”-like theme (software look).
  • [ ] About the editor, since we are vertically sliced, it might be a good idea to disable as many module as needed to have the currently mvp. We could simplify our life to only publish from obsidian for now. So we might just put the editor down for a moment. we allow anonymous import and obsidian thats it, once its verified, bring back edit mode (wich I guess wont take too long)
  • [ ] List and audit all the module in the project to see if everything follow the rules.
  • [ ] Isn’t there a plan to code the necessary code for garden sass domain name from cloudflare?
  • [ ] Confirm the paid plan, what is it… can be fuck cheap to give a chance at the community.. this strategy can be made in function to raise the price if needed. But the idea here to be able to survive from it at some point, Living in the city of quebec, I dont need much but 50k is the minimum we are aiming… it can take years to get there.. it will take years… but it would be nice to make a strategy tho.

Not now (Phase 3)

Telegram bot · email gateway · iOS Share Sheet · AI profile auto-cluster · rich-text editor · generative-AI writing (the anti-mission).


How it works — reference

Tech stack

  • Frontend — Astro (static-first + islands) + Svelte 5 (runes only: $state/$derived/
    $effect) + the Standard typography engine. View Transitions for navigation.
  • Backend — Cloudflare Pages Functions (edge, zero cold starts). API at /api/*.
  • Database — Cloudflare D1 (SQLite, FTS5). Storage — R2 (markdown + attachments).
    Search — Vectorize (semantic / Mycelium graph).

Physical metaphors (naming)

Code reads like a place you visit, not abstract CS:

Directory Metaphor Responsibility
garden/ The Domain business logic, entities
shed/ The Tools shared utilities
press/ The Printer typography engine
atelier/ The Workshop editor tools
layouts/ The Terrain UI system
compass/ Navigation command palette
modules/ Growth feature modules

Domain models

Root (CF environment — D1/R2/Vectorize bindings) · User (tier, role, api_key_hash) · Author (public identity, username, custom domain) · Note (the atom — nano_id, slug, visibility, theme, style tokens, lang, expires_at) · Garden (a user’s collection) · Mycelium (backlinks + related).

The profile note (root-note model)

The user’s root note (permalink: "/", slug "") IS their garden’s home, with three roles:

  1. frontmatter = garden-wide defaults — its theme tokens cascade under every note
    (theme ← profile ← note), cached on user.settings.profileDefaults.
  2. body = the account page at /@user. ✅ live.
  3. ​```css blocks = garden-wide CSS (sanitized, origin-isolated). ⏳ role #3, see above.

One slug resolver (Note.resolveFrontmatterSlugpermalink > slug, allows "") is honored by publish, Note.create, and Note.update, so permalink: "/" lands idempotently from both Obsidian and the web writer. Schema: packages/utils/profile-schema.js.

Unpublish = hard delete. “Unpublish” in Obsidian permanently deletes server-side
(Note.destroy: D1 row, R2 content, attachments, backlinks, Vectorize embedding, profile
cache). The local note stays (publish: false). Republishing creates a new note.

The six temperaments

We apply the right one automatically (users don’t pick): Construct (Swiss) · Blueprint (Technical) · Letter (Humanist) · Chronicle (Editorial) · Treatise (Academic) · Exhibit (Gallery). All built on @stnd/styles CSS variables.

Francis

That… its written in the doc, but nothing in the todos for the code, and I’m actually not sure about this one, I think human might prefer to put it themself or it will feel that we play with their content.

In the obsidian plugin, there is however a button to ask the ai to generate a custom theme for the note and [ ] that might need some time to think about this one, first I’d like it to use the cloudflare ai instead of directly anthropic, does call can be cheap as not a lot of thinking need, but we do have to enrich the default prompt

Quick start

pnpm install
pnpm dev               # Astro dev server (port 8089)
pnpm dev:all           # with Cloudflare Wrangler (SSR, port 8088)
pnpm build             # production build
node scripts/manage-notes.mjs   # manage notes via CLI
pnpm db:reset:local            # reset local D1

Data layer notes

  • Secrets: .dev.vars (local) + wrangler secret put (prod). Never in wrangler.toml.
  • Rate limiting: D1 rate_limits (migration 0008) — ai/theme 10/min, publish 60/min,
    attachment 30/min (fail-open).
  • Compost: standalone cron worker workers/compost/ (daily 04:00 UTC).

Framework integration

Built on @stnd/core (the Astro orchestrator). Typography via @stnd/press remark/rehype (backlinks, tags, obsidian-links, typography). UI from @stnd/ui + layouts from @stnd/layout. 80+ utilities from @stnd/utils. See packages/README.md and the manual.