{
  "version": 2,
  "repo": "rahmanef63/resource-site",
  "branch": "main",
  "aliases": {
    "blog-section": "sections",
    "faq-section": "sections",
    "portfolio-section": "sections",
    "changelog-feed": "sections",
    "feature-grid": "sections",
    "testimonials-grid": "sections",
    "pricing-page": "sections",
    "files": "file-upload",
    "onboarding-wizard": "site-setup-wizard",
    "media-studio": "design-studio",
    "loading-states": "feedback-states",
    "empty-states": "feedback-states",
    "resume": "profile",
    "about-profile": "profile",
    "settings-page": "settings",
    "shell-settings": "settings",
    "doku-payment": "payment",
    "midtrans-payment": "payment",
    "landing-sections": "sections",
    "notion-shell": "notion-ui",
    "notion-database": "notion-ui",
    "notion-sidebar": "notion-ui",
    "notion": "notion-app",
    "admin-console": "admin",
    "ai-chat": "ai-workspace",
    "ai-studio": "ai-workspace",
    "ai-agents": "ai-workspace"
  },
  "layouts": [],
  "recipes": [],
  "features": [
    {
      "slug": "image-editor",
      "title": "Image Editor — layered raster editor",
      "category": "os",
      "description": "A Photoshop-style raster image editor built on Konva. Layers panel (reorder, opacity, visibility, lock, 16 blend modes), free transform (move/scale/rotate/flip via a Transformer), image + text + shape + paint layers, brush & eraser with size/opacity/hardness, non-destructive adjustments + filters, canvas resize/aspect presets, and LAYER STYLES: stroke, drop shadow, outer glow, clipping mask. One-click BACKGROUND REMOVAL runs fully in-browser via @imgly/background-removal (free, no API key — downloads a small ONNX model on first use). Undo/redo, zoom/pan, shortcuts, PNG/JPG/WebP export. v2 adds an AI FUNCTION-CALLING layer: every editor operation is a named, schema'd command (EDITOR_COMMANDS registry + useEditorCommands binding) driven by an in-editor chat; the streaming bridge is injectable via configureAgentStream(fn) and everything except the chat works without it. A headless server barrel (server.ts) runs commands against documents with no DOM. Image I/O via props (initialImage / onSave).",
      "source": "rahmanef63/os-vps",
      "install": "npx rahman-resources add image-editor",
      "npmPackages": [],
      "exampleCode": "\"use client\";\nimport { ImageEditor } from \"@/features/image-editor\";\n\nexport default function ImageEditorDemo() {\n  // No props → opens a blank 1080×1080 canvas with one paint layer. Brush/erase,\n  // add text/shapes, open an image + remove its background (free, in-browser),\n  // apply layer styles + filters, then export PNG/JPG/WebP. Konva stage is\n  // client-only (loaded via next/dynamic) so SSR never touches canvas/window.\n  return (\n    <div className=\"h-dvh w-full\">\n      <ImageEditor onSave={(dataUrl) => console.log(\"save\", dataUrl.slice(0, 32))} />\n    </div>\n  );\n}",
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui + Konva. A layered raster image editor. Image I/O is via props; background removal runs in-browser (no backend).\n\nSTEP 1 — Install. `npx rr add image-editor`. Ensure `@/features/image-editor` resolves in tsconfig paths and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `konva react-konva @imgly/background-removal lucide-react`. shadcn: `npx shadcn@latest add button input slider select tabs scroll-area separator tooltip label switch popover`.\n\nSTEP 3 — Mount. It is fully self-contained; the Konva stage is loaded client-only (next/dynamic ssr:false) inside the slice, so just render it in a height-bearing box:\n```tsx\n\"use client\";\nimport { ImageEditor } from \"@/features/image-editor\";\nexport default function Page() {\n  return (\n    <div className=\"h-dvh\">\n      <ImageEditor onSave={(dataUrl) => console.log(dataUrl)} />\n    </div>\n  );\n}\n```\nProps: `initialImage?` (data/object/remote URL opened on mount), `width?`/`height?` (blank canvas size, default 1080²), `onSave?(dataUrl)` (fires from the Save button with a PNG data URL; omit to hide Save), `className?`.\n\nSTEP 4 — Background removal. The \"Remove BG\" button calls removeImageBackground() from @imgly/background-removal — free, in-browser, no key. First run downloads a small model to the browser cache, then runs locally via WASM. You can also import `removeImageBackground(src) => Promise<pngDataUrl>` directly.\n\nSTEP 5 — Export. PNG/JPG/WebP at 1×/2×/3× via the Export tab, or call `exportStage(stage, {...})` / `stageToDataURL(stage, {...})`. The container owns the box — render inside h-dvh / h-full.",
      "tags": [
        "image-editor",
        "photoshop",
        "canvas",
        "konva",
        "layers",
        "filters",
        "background-removal",
        "paint",
        "ai",
        "ui"
      ]
    },
    {
      "slug": "reel-editor",
      "title": "Reel — video timeline editor",
      "category": "os",
      "description": "A complete in-browser video editor. Real media clips (image/video/audio) on a layered multi-track timeline — the top row renders frontmost, with ▲▼ reorder and per-track lock/hide/mute. ONE Canvas-2D draw path is shared by the live preview and the realtime MediaRecorder exporter, so what you see is exactly what renders (WebM with real mixed audio: per-clip volume/fades/auto-duck through a streaming audio graph). Per-clip trim/speed (0.25–4×)/reverse, dissolve/wipe/slide transitions via clip overlap, keyframes (opacity/scale/x/y/rotation) with easing + one-click In/Out animation presets, text styling with preset grid, color grading + vignette, filmstrip thumbnails + real waveforms, snapping, split/duplicate. The workspace is config-driven: 6 resizable layout presets (react-resizable-panels v4) incl. quick-import files-pane layouts, plus custom composition size. Drafts auto-save to localStorage. Self-contained: toasts via sonner, the files pane runs on an injectable fs adapter (configureReelFs; in-memory mock by default), and shell hooks (inspector/activity) are inert seams in lib/host.ts.",
      "source": "rahmanef63/os-vps",
      "install": "npx rahman-resources add reel-editor",
      "npmPackages": [],
      "exampleCode": "\"use client\";\nimport { ReelEditor } from \"@/features/reel-editor\";\n\nexport default function VideoEditorDemo() {\n  // Opens with a sample composition. Import media via File menu (local picker\n  // works with zero backend — object URLs), arrange clips on layered tracks,\n  // add text/transitions/keyframes, then Render → realtime WebM with audio.\n  return (\n    <div className=\"h-dvh w-full\">\n      <ReelEditor />\n    </div>\n  );\n}",
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. An in-browser video timeline editor with realtime WebM export. Fully client-side; no backend required.\n\nSTEP 1 — Install. `npx rr add reel-editor`. Ensure `@/features/reel-editor` resolves in tsconfig paths and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react react-resizable-panels sonner`. shadcn: `npx shadcn@latest add button input slider tooltip dialog dropdown-menu resizable sheet sonner`. Mount `<Toaster />` (sonner) once in your root layout.\n\nSTEP 3 — Mount. Render in a height-bearing box:\n```tsx\n\"use client\";\nimport { ReelEditor } from \"@/features/reel-editor\";\nexport default function Page() {\n  return <div className=\"h-dvh\"><ReelEditor /></div>;\n}\n```\nOr register the `reelEditorApp` descriptor in an appshell manifest for windowed hosts.\n\nSTEP 4 — Files pane backend (optional). The quick-import pane ships with an in-memory mock. Wire a real filesystem with `configureReelFs({ list, mkdir, rawUrl })` — list/mkdir mirror a simple fs API, rawUrl resolves a listed path to a fetchable media URL.\n\nSTEP 5 — Export. The Render button records the live canvas + mixed audio to WebM via MediaRecorder in realtime (duration = composition length). Users can also import local media via the file picker — object URLs, no upload needed.",
      "tags": [
        "video",
        "video-editor",
        "timeline",
        "nle",
        "keyframes",
        "transitions",
        "webm",
        "canvas",
        "ui"
      ]
    },
    {
      "slug": "media-viewer",
      "title": "Preview — media quick-look",
      "category": "os",
      "description": "A quick-look media viewer in the macOS Preview spirit. Images render on a zoomable (40–300%) checkerboard stage so transparency reads; audio gets a card player with a CSS-bar waveform + transport; video gets play/pause + scrubber + volume; PDFs embed full-bleed and text gets a simple surface. The toolbar carries a type-indicator chip, zoom, Download, Open-in-editor, and prev/next. Two integration seams in lib/host.ts make it portable: configureMediaSource maps fs paths to fetchable URLs (identity by default, so public URLs work with zero wiring) and configureMediaOpener routes the Open-in-editor handoff (image → image-editor, video/audio → reel-editor) to your shell — both inert until set. Launched bare it shows a fully offline sample gallery (inline SVG gradients, simulated A/V playback). Pairs with file-explorer (onOpenFile → MediaViewer payload) and the editors.",
      "source": "rahmanef63/os-vps",
      "install": "npx rahman-resources add media-viewer",
      "npmPackages": [],
      "exampleCode": "\"use client\";\nimport { MediaViewer } from \"@/features/media-viewer\";\n\nexport default function PreviewDemo() {\n  // No payload → offline sample gallery (gradient images, simulated A/V).\n  // Pass { path, name, kind } to view a real file; wire configureMediaSource\n  // when paths need resolving against your own fs API.\n  return (\n    <div className=\"h-dvh w-full\">\n      <MediaViewer />\n    </div>\n  );\n}",
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. A quick-look media viewer (image/video/audio/pdf/text). Fully client-side; no backend required.\n\nSTEP 1 — Install. `npx rr add media-viewer`. Ensure `@/features/media-viewer` resolves in tsconfig paths and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button badge separator tooltip slider`.\n\nSTEP 3 — Mount. `<MediaViewer />` with no payload shows the offline sample gallery. Pass a file to view it:\n```tsx\n\"use client\";\nimport { MediaViewer } from \"@/features/media-viewer\";\nexport default function Page() {\n  return <div className=\"h-dvh\"><MediaViewer payload={{ path: \"/media/clip.mp4\", name: \"clip.mp4\", kind: \"video\" }} /></div>;\n}\n```\nOr register the `mediaViewerApp` descriptor in an appshell manifest for windowed hosts.\n\nSTEP 4 — Remote files (optional). Paths resolve through `configureMediaSource({ rawUrl })` — identity by default, so public/absolute URLs already work. Point rawUrl at your fs endpoint for private files.\n\nSTEP 5 — Editor handoff (optional). `configureMediaOpener((appId, title, size, payload) => …)` routes the \"Open in Image/Video Editor\" actions to your shell (no-op until set). Wire it to openWindow when running inside appshell with image-editor / reel-editor installed.",
      "tags": [
        "media",
        "preview",
        "viewer",
        "quick-look",
        "image",
        "video",
        "audio",
        "pdf",
        "ui"
      ]
    },
    {
      "slug": "code-editor",
      "title": "Code — overlay syntax editor",
      "category": "os",
      "description": "A lightweight code editor in the VS-Code spirit without the weight: a transparent textarea layered over a highlighted pre (regex tokenizer for JS/TS/JSON/CSS) gives real editing with live syntax color and a line-number gutter; a tab strip tracks dirty buffers with Cmd/Ctrl+S save; a status bar shows path, Ln/Col, tab size, language and save state. The explorer is a lazy per-directory tree — each folder lists on expand, with inline new-file/new-folder affordances — rendered as a rail on desktop and a Sheet on mobile, and the new-file form is a responsive dialog ⇄ bottom drawer. The filesystem is INJECTED via a small CodeFsAdapter (list/read/write/mkdir): point configureCodeFs at a real API or use the bundled writable in-memory mock (seeded sample tree) so it works with zero backend. Writes are best-effort — a read-only host flags the save but keeps the local buffer. Pairs with file-explorer (onOpenFile → payload) and appshell.",
      "source": "rahmanef63/os-vps",
      "install": "npx rahman-resources add code-editor",
      "npmPackages": [],
      "exampleCode": "\"use client\";\nimport { CodeEditor } from \"@/features/code-editor\";\n\nexport default function CodeDemo() {\n  // No payload → seeded sample tree on the writable in-memory mock fs.\n  // Explorer lazy-lists each directory on expand; + buttons create\n  // files/folders; Cmd/Ctrl+S saves. Wire configureCodeFs for a real backend.\n  return (\n    <div className=\"h-dvh w-full\">\n      <CodeEditor />\n    </div>\n  );\n}",
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. A lightweight overlay-highlighting code editor with a lazy explorer tree. Fully client-side; no backend required.\n\nSTEP 1 — Install. `npx rr add code-editor`. Ensure `@/features/code-editor` resolves in tsconfig paths and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button badge input scroll-area sheet dialog`.\n\nSTEP 3 — Mount. `<CodeEditor />` opens the seeded sample tree (writable in-memory mock). Open a specific file with a payload:\n```tsx\n\"use client\";\nimport { CodeEditor } from \"@/features/code-editor\";\nexport default function Page() {\n  return <div className=\"h-dvh\"><CodeEditor payload={{ path: \"/Projects/hello.ts\" }} /></div>;\n}\n```\nOr register the `codeEditorApp` descriptor in an appshell manifest for windowed hosts.\n\nSTEP 4 — Real filesystem (optional). `configureCodeFs({ list, read, write, mkdir })` — list returns { path, entries: [{ name, kind }] } for ONE directory (the tree fetches per expand), read returns the file body, write/mkdir mutate. Writes are best-effort: on failure the editor keeps the local buffer and flags the status bar.\n\nSTEP 5 — Cross-app open. From a file manager (e.g. the file-explorer slice), wire onOpenFile to re-render CodeEditor with payload={{ path }} — the editor adds a tab and hydrates the buffer.",
      "tags": [
        "code",
        "editor",
        "syntax-highlight",
        "ide",
        "tabs",
        "file-tree",
        "ui"
      ]
    },
    {
      "slug": "system-monitor",
      "title": "System Monitor — host telemetry dashboard",
      "category": "os",
      "description": "An Activity-Monitor-style dashboard: circular CPU/RAM/disk/GPU gauges, rolling CPU + network sparklines on glass panels, and a live process table — polling every 1.5s with a ~40-point history. Telemetry is INJECTED via a small SysMonAdapter (stats/processes): point configureSysmon at a real host API (/proc, an agent, a cloud endpoint) or keep the bundled wavy in-browser mock so the dashboard renders alive with zero backend. Self-contained: shell inspector hooks are inert seams in lib/host.ts.",
      "source": "rahmanef63/os-vps",
      "install": "npx rahman-resources add system-monitor",
      "npmPackages": [],
      "exampleCode": "\"use client\";\nimport { SystemMonitor } from \"@/features/system-monitor\";\n\nexport default function MonitorDemo() {\n  // Unwired -> wavy mock telemetry; configureSysmon for a real host.\n  return <div className=\"h-dvh w-full\"><SystemMonitor /></div>;\n}",
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. Host telemetry dashboard. Fully client-side; no backend required.\n\nSTEP 1 — Install. `npx rr add system-monitor`. Ensure `@/features/system-monitor` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add scroll-area`.\n\nSTEP 3 — Mount. `<SystemMonitor />` in a height-bearing box — unwired it runs a wavy in-browser telemetry mock. Or register `systemMonitorApp` in an appshell manifest.\n\nSTEP 4 — Real telemetry. `configureSysmon({ mode:\"live\", stats, processes })` — stats returns { cpu:{pct,cores}, mem:{used,total}, disk:{used,total}, net?:{rx,tx}, uptime }; processes returns [{ pid, name, status, cpu, mem }].",
      "tags": [
        "monitoring",
        "telemetry",
        "dashboard",
        "gauges",
        "sparkline",
        "processes",
        "ui"
      ]
    },
    {
      "slug": "booking",
      "title": "Booking — session request form + owner inbox",
      "category": "os",
      "description": "One app that is BOTH a public 'book a session' request form AND the owner's triage inbox — it flips to show the inbox when the viewer can manage. Visitors submit name/email/topic (+ optional preferred time / note); the owner sees pending requests with Confirm / Decline. The backend is INJECTED via a small BookingAdapter (submit/list/setStatus/canManage): point configureBooking at your store, or keep the bundled in-memory mock so it renders fully interactive — form + inbox — with zero backend.",
      "source": "rahmanef63/os-vps",
      "install": "npx rahman-resources add booking",
      "npmPackages": [],
      "exampleCode": "\"use client\";\nimport { Booking } from \"@/features/booking\";\n\nexport default function BookingDemo() {\n  // Unwired -> in-memory mock; configureBooking for a real backend.\n  return <div className=\"h-dvh w-full\"><Booking /></div>;\n}",
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. A booking request form + owner inbox. Fully client-side; backend optional.\n\nSTEP 1 — Install. `npx rr add booking`. Ensure `@/features/booking` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button input textarea scroll-area`.\n\nSTEP 3 — Mount. `<Booking />` in a height-bearing box — unwired it runs on an in-memory mock store (form + inbox both live). Or register `bookingApp` in an appshell manifest.\n\nSTEP 4 — Real backend. `configureBooking({ mode:\"live\", submit, list, setStatus, canManage })` — submit takes { name, email, topic, preferredTime?, note? }; list returns rows with { id, status, createdAt }; omit list/canManage for a write-only public form.",
      "tags": [
        "booking",
        "contact",
        "form",
        "inbox",
        "lead",
        "scheduling",
        "ui"
      ]
    },
    {
      "slug": "html-studio",
      "title": "HTML Studio — sandboxed HTML/CSS/JS editor with live preview",
      "category": "os",
      "description": "A tiny web-page studio: write HTML / CSS / JS and see it render LIVE in a sandboxed iframe (srcdoc + sandbox=allow-scripts WITHOUT allow-same-origin, so user code runs in an opaque origin and cannot read the host) — then Save to a shareable /p/<slug>. Code / Split / Preview view toggle, a device-width preview (responsive / tablet / phone), a saved-pages rail, and public/private visibility. The backend is INJECTED via a small HtmlStudioAdapter (save/load/list/remove): point configureHtmlStudio at your store, or keep the bundled in-memory mock so the editor + live preview + saved list are fully interactive with zero backend.",
      "source": "rahmanef63/os-vps",
      "install": "npx rahman-resources add html-studio",
      "npmPackages": [],
      "exampleCode": "\"use client\";\nimport { HtmlStudio } from \"@/features/html-studio\";\n\nexport default function HtmlStudioDemo() {\n  // Unwired -> in-memory mock; configureHtmlStudio for a real backend.\n  return <div className=\"h-dvh w-full\"><HtmlStudio /></div>;\n}",
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. A sandboxed HTML/CSS/JS studio: editor + live iframe preview + saved pages. Fully client-side; backend optional.\n\nSTEP 1 — Install. `npx rr add html-studio`. Ensure `@/features/html-studio` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button input textarea scroll-area`.\n\nSTEP 3 — Mount. `<HtmlStudio />` in a height-bearing box — unwired it runs on an in-memory mock (editor + live sandboxed preview + saved list all live). Pass `payload={{ slug }}` to open a page, or register `htmlStudioApp` in an appshell manifest.\n\nSTEP 4 — Real backend. `configureHtmlStudio({ mode:\"live\", save, load, list, remove })` — save takes { slug?, title, html, visibility } and returns { slug }; load(slug) -> SavedPage | null; omit save for a read-only sandbox or list to hide the saved rail. KEEP the iframe sandbox without allow-same-origin — it is the security boundary.",
      "tags": [
        "html",
        "editor",
        "sandbox",
        "iframe",
        "preview",
        "playground",
        "code",
        "ui"
      ]
    },
    {
      "slug": "resources-launcher-admin",
      "title": "Resources Admin — curated icon-launcher CRUD",
      "category": "os",
      "description": "An owner-gated admin app for a curated icon-launcher: add / edit / remove / reorder links (label, lucide icon NAME, url, group, order) that open in a new tab. The backend is INJECTED via a small ResourcesAdapter (list/upsert/remove/canManage): point configureResources at your store, or keep the bundled in-memory mock so the whole CRUD — including reorder — is interactive with zero backend. Icons are stored as lucide NAME strings and resolved client-side, so the same data drives a public launcher surface.",
      "source": "rahmanef63/os-vps",
      "install": "npx rahman-resources add resources-launcher-admin",
      "npmPackages": [],
      "exampleCode": "\"use client\";\nimport { ResourcesAdmin } from \"@/features/resources-launcher-admin\";\n\nexport default function ResourcesAdminDemo() {\n  // Unwired -> in-memory mock; configureResources for a real backend.\n  return <div className=\"h-dvh w-full\"><ResourcesAdmin /></div>;\n}",
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. A curated icon-launcher admin (CRUD + reorder). Fully client-side; backend optional.\n\nSTEP 1 — Install. `npx rr add resources-launcher-admin`. Ensure `@/features/resources-launcher-admin` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button input label scroll-area native-select`.\n\nSTEP 3 — Mount. `<ResourcesAdmin />` in a height-bearing box — unwired it runs on an in-memory mock store (add / edit / remove / reorder all live). Or register `resourcesAdminApp` in an appshell manifest.\n\nSTEP 4 — Real backend. `configureResources({ mode:\"live\", list, upsert, remove, canManage })` — list returns rows { id, label, icon, url, group, order }; upsert takes the same minus id to insert (pass id to patch); canManage gates the editor + reorder. Icons are lucide NAME strings resolved via resolveIcon.",
      "tags": [
        "launcher",
        "links",
        "bookmarks",
        "admin",
        "crud",
        "icons",
        "ui"
      ]
    },
    {
      "slug": "profile",
      "title": "Profile — CV + identity card",
      "category": "os",
      "description": "One owner's identity in two co-located variants, behind one slug. resume: a clean one-column résumé / CV — name, roles, location, contacts, summary, skills, experience (role · org · period + bullets), projects — rendered by <Resume /> off a configureResume() seam, with a Print / PDF button. card: an \"About This Mac\"-style identity card — avatar / monogram, name, roles, outbound links, FAQ accordion — rendered by <AboutProfile /> off a configureAbout() seam. Both render a populated placeholder unwired (zero backend). Install one surface with `npx rr add profile resume|card`, or both with `npx rr add profile`.",
      "source": "rahmanef63/os-vps",
      "install": "npx rahman-resources add profile",
      "npmPackages": [],
      "exampleCode": "\"use client\";\nimport { Resume, AboutProfile } from \"@/features/profile\";\n\nexport default function ProfileDemo() {\n  // Unwired -> generic placeholders; configureResume(cv) / configureAbout(card) for real data.\n  return (\n    <div className=\"grid h-dvh grid-cols-2 gap-4\">\n      <Resume />\n      <AboutProfile />\n    </div>\n  );\n}",
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. Two identity renderers driven by injected data. Fully client-side; no backend required.\n\nSTEP 1 — Install. `npx rr add profile` for both, or `npx rr add profile resume` / `card` for one. Ensure `@/features/profile` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button scroll-area avatar`.\n\nSTEP 3 — Mount. `<Resume />` (CV) or `<AboutProfile />` (card) in a height-bearing box — unwired each renders a generic placeholder. Or register `resumeApp` / `aboutProfileApp` in an appshell manifest.\n\nSTEP 4 — Real data. `configureResume(profile)` with a ResumeProfile { name, roles[], location, summary, contacts[], skills[], experience[], projects[] }, and/or `configureAbout(card)` with { name, roles[], description, links[], faq[] }, once at boot from Convex / a CMS / a JSON file. Resume's \"Print / PDF\" button calls window.print() against a print-friendly layout.",
      "tags": [
        "resume",
        "cv",
        "profile",
        "portfolio",
        "about",
        "identity",
        "bio",
        "card",
        "links",
        "faq",
        "print",
        "ui"
      ]
    },
    {
      "slug": "start-here",
      "title": "Start Here — guided OS onboarding tour",
      "category": "os",
      "description": "A guided 'Start Here' tour that lays the OS out as a path of stages, each stage opening real apps from the LIVE registry — drift-proof, it reads the injected app catalog instead of a hardcoded list, so adding an app surfaces it automatically (in a stage if listed, else a final 'Everything else' bucket). The catalog, the open(id) callback, and the stage journey are INJECTED via a small StartHereAdapter (apps / open / stages): point configureStartHere at your live app registry + window opener, or keep the bundled in-memory mock (a few generic apps + 3 stages) so the welcome tour renders fully alive with zero host.",
      "source": "rahmanef63/os-vps",
      "install": "npx rahman-resources add start-here",
      "npmPackages": [],
      "exampleCode": "\"use client\";\nimport { StartHere } from \"@/features/start-here\";\n\nexport default function StartHereDemo() {\n  // Unwired -> in-memory mock catalog; configureStartHere for the live registry.\n  return <div className=\"h-dvh w-full\"><StartHere /></div>;\n}",
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. A guided onboarding tour that renders your live app catalog as a path of stages. Fully client-side; the catalog is injected.\n\nSTEP 1 — Install. `npx rr add start-here`. Ensure `@/features/start-here` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button scroll-area`.\n\nSTEP 3 — Mount. `<StartHere />` in a height-bearing box — unwired it reads an in-memory mock catalog (generic apps + 3 stages) so the tour is fully alive. Or register `startHereApp` in an appshell manifest.\n\nSTEP 4 — Real catalog. `configureStartHere({ mode:\"live\", apps, open, stages })` — apps is your live registry as [{ id, title, icon, description? }]; open(id) launches the real app/window; stages is [{ title, blurb, appIds }] (apps not placed fall into a final \"Everything else\" stage). Drift-proof: read the registry, never hardcode the list.",
      "tags": [
        "onboarding",
        "tour",
        "welcome",
        "launcher",
        "guide",
        "os",
        "ui"
      ]
    },
    {
      "slug": "os-terminal",
      "title": "Terminal — shell emulator with live passthrough + PTY seam",
      "category": "os",
      "description": "A React-DOM terminal: monospace glass aesthetic, colored prompt, arrow-key history, red stderr. Built-ins (ls·cd·pwd·cat·mkdir·touch·rm·mv·cp·echo·whoami·date·uname·df·ps·neofetch·help·clear) run against an in-memory FsModel, so it works with ZERO backend. Wire configureTerminal({ mode:\"live\", fs, exec }) and ls/cat read through your real filesystem, file mutations mirror to it, and any unknown command passes through exec.run as a one-shot shell call (stdout/stderr/exit rendered). Self-contained: shell inspector hooks are inert seams in lib/host.ts.",
      "source": "rahmanef63/os-vps",
      "install": "npx rahman-resources add os-terminal",
      "npmPackages": [],
      "exampleCode": "\"use client\";\nimport { Terminal } from \"@/features/os-terminal\";\n\nexport default function TerminalDemo() {\n  // Mock mode: 17 built-ins over an in-memory fs. configureTerminal to go live.\n  return <div className=\"h-96 w-full\"><Terminal /></div>;\n}",
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. Shell emulator with optional live passthrough. Fully client-side by default.\n\nSTEP 1 — Install. `npx rr add os-terminal`. Ensure `@/features/os-terminal` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. No shadcn components required.\n\nSTEP 3 — Mount. `<Terminal />` in a height-bearing box — mock mode runs entirely on the in-memory FsModel. Or register `osTerminalApp` in an appshell manifest.\n\nSTEP 4 — Go live. `configureTerminal({ mode:\"live\", fs:{list,read,write,mkdir,remove,move,copy}, exec:{run} })`. In live mode ls/cat read through your fs, mutations mirror, and unknown commands hit exec.run (one-shot; treat the endpoint like SSH).",
      "tags": [
        "terminal",
        "shell",
        "cli",
        "emulator",
        "exec",
        "ui"
      ]
    },
    {
      "slug": "assistant",
      "title": "Assistant — agent workspace with streaming chat",
      "category": "os",
      "description": "A full agent workspace: streaming chat with typing deltas and graceful error notes, plus a library where users CREATE and manage agents (persona, avatar gradient, system prompt), skills, and automations (trigger + schedule forms) — all persisted in localStorage, no backend. Preset agents/skills ship as starting points. The model is INJECTED: configureAssistantStream takes any (messages) => AsyncIterable<string> — your SSE endpoint, the AI SDK, an agent loop — and until wired a typing demo stream keeps the whole UI working offline. Self-contained: shell inspector hooks are inert seams in lib/host.ts.",
      "source": "rahmanef63/os-vps",
      "install": "npx rahman-resources add assistant",
      "npmPackages": [],
      "exampleCode": "\"use client\";\nimport { Assistant } from \"@/features/assistant\";\n\nexport default function AssistantDemo() {\n  // Unwired -> typing demo stream. configureAssistantStream for a real LLM.\n  return <div className=\"h-dvh w-full\"><Assistant /></div>;\n}",
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. Agent workspace with streaming chat. Fully client-side; model injected.\n\nSTEP 1 — Install. `npx rr add assistant`. Ensure `@/features/assistant` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button input textarea tabs badge scroll-area dropdown-menu dialog select switch`.\n\nSTEP 3 — Mount. `<Assistant />` in a height-bearing box. Unwired, a typing demo stream answers so the UI works offline; agents/skills/automations persist in localStorage.\n\nSTEP 4 — Wire a model. `configureAssistantStream(async function* (messages) { ...yield text deltas... })` — SSE endpoint, AI SDK, or an agent loop. Throw Error(\"no_api_key\") / Error(\"unauthorized\") for the chat's friendly error notes.",
      "tags": [
        "ai",
        "assistant",
        "chat",
        "agents",
        "streaming",
        "automations",
        "ui"
      ]
    },
    {
      "slug": "browser",
      "title": "Browser — remote headless-browser chrome",
      "category": "os",
      "description": "Full browser chrome for a REMOTE headless browser: omnibar with search-or-URL detection, bookmark bar, history view (localStorage-persisted), favicons with globe fallback, busy states, and a screenshot viewport that forwards clicks/typing/keys/scroll into the remote page. The backend is INJECTED via a small BrowserAdapter (state/screenshot/act): point configureBrowser at a real headless-Chromium service (e.g. Playwright behind an authed route — any site renders, no X-Frame-Options problem) or keep the bundled offline canvas demo renderer that fakes the viewport so the whole chrome works with zero backend. Self-contained: shell inspector hooks are inert seams in lib/host.ts.",
      "source": "rahmanef63/os-vps",
      "install": "npx rahman-resources add browser",
      "npmPackages": [],
      "exampleCode": "\"use client\";\nimport { Browser } from \"@/features/browser\";\n\nexport default function BrowserDemo() {\n  // Unwired -> offline canvas demo renderer. configureBrowser for Playwright.\n  return <div className=\"h-dvh w-full\"><Browser /></div>;\n}",
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. Remote headless-browser chrome. Demo renderer by default; real backend injected.\n\nSTEP 1 — Install. `npx rr add browser`. Ensure `@/features/browser` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button input badge dropdown-menu tooltip scroll-area`.\n\nSTEP 3 — Mount. `<Browser />` in a height-bearing box — unwired, an offline canvas demo renderer fakes the viewport (omnibar/bookmarks/history all work). Or register `browserApp` in an appshell manifest.\n\nSTEP 4 — Real headless browser. `configureBrowser({ state, screenshot, act })` against a Playwright service: state → { url, title }; screenshot → PNG Blob; act(path, body) handles navigate|click|type|key|scroll|back|forward|reload. AUTH those routes — a remote browser holds logged-in sessions.",
      "tags": [
        "browser",
        "headless",
        "playwright",
        "remote",
        "omnibar",
        "bookmarks",
        "ui"
      ]
    },
    {
      "slug": "app-store",
      "title": "App Store — install, create + toggle apps",
      "category": "os",
      "description": "The dynamic half of an app registry, in two surfaces. AppStore: a storefront with featured hero, category sidebar, install/uninstall cards for a curated catalog, and toggles that disable built-in apps/shell features (the DISABLED set is persisted so new apps always ship enabled). CreateApp: build a custom app — name, glyph, accent gradient, runtime (html/node/python/shell), entry — with live manifest preview. Both write one localStorage registry; useInstalledApps() turns it into appshell-style descriptors (html apps mount in a sandboxed iframe, command apps in a terminal-style console). The console's shell is INJECTED via configureAppStoreExec (demo echo by default). Self-contained: inspector hooks are inert seams in lib/host.ts; the Create-App flow is bundled in (no cross-slice imports).",
      "source": "rahmanef63/os-vps",
      "install": "npx rahman-resources add app-store",
      "npmPackages": [],
      "exampleCode": "\"use client\";\nimport { AppStore } from \"@/features/app-store\";\n\nexport default function StoreDemo() {\n  // Install/uninstall + Create-App write one localStorage registry.\n  return <div className=\"h-dvh w-full\"><AppStore /></div>;\n}",
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. Storefront + Create-App over a localStorage app registry. Fully client-side.\n\nSTEP 1 — Install. `npx rr add app-store`. Ensure `@/features/app-store` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button input badge separator scroll-area switch tooltip`.\n\nSTEP 3 — Mount. `<AppStore />` (storefront) and/or `<CreateApp />` (custom-app builder) — or register `appStoreApp` / `createAppApp` in an appshell manifest.\n\nSTEP 4 — Feed your launcher. `useInstalledApps()` returns AppDescriptor[] for everything installed/created (html → sandboxed iframe, command → console); `useDisabledIds()` filters your built-in manifest.\n\nSTEP 5 — Console exec (optional). `configureAppStoreExec({ mode:\"live\", exec:{run} })` so command/script apps run on a real one-shot shell (auth it like SSH).",
      "tags": [
        "app-store",
        "registry",
        "installer",
        "dynamic-apps",
        "launcher",
        "ui"
      ]
    },
    {
      "slug": "file-explorer",
      "title": "File Explorer — Tree + CRUD + Breadcrumb",
      "category": "os",
      "description": "A complete, portable file-directory explorer: a collapsible folder TREE sidebar (lazy-loaded per dir), a responsive BREADCRUMB that auto-collapses to a dropdown, grid + list views with sort, multi-select, a right-click context menu, drag-and-drop (internal move + external file/folder upload), inline rename, and full CRUD (new folder, rename, cut/copy/paste, move, delete/trash, empty trash). The filesystem backend is INJECTED via a small FileExplorerAdapter (list/mkdir/remove/move/copy/upload/usage/rawUrl) — point it at a real API or use the bundled createMockAdapter() (a writable in-memory tree) so it works with zero backend. Opening a file fires an onOpenFile(path, entry) callback you wire to your own viewer/editor. Self-contained: imports only @/components/ui/* + @/lib/utils. Ported from os-vps (Topside) files manager. Pairs with appshell as the file-dir counterpart to a notion-style sidebar.",
      "source": "rahmanef63/os-vps",
      "install": "npx rahman-resources add file-explorer",
      "npmPackages": [],
      "exampleCode": "\"use client\";\nimport { FileExplorer } from \"@/features/file-explorer\";\n\nexport default function FileExplorerDemo() {\n  // No adapter prop → uses the backend from lib/backend.ts (mock by default):\n  // a writable in-memory tree, so create/rename/delete/move/upload all work with\n  // no backend. Flip FILE_EXPLORER_BACKEND to \"live\"/\"convex\" in that one file to\n  // go real — nothing here changes. Pass adapter={…} to override per-instance.\n  return (\n    <div className=\"h-dvh w-full\">\n      <FileExplorer\n        rootLabel=\"Files\"\n        onOpenFile={(path, entry) => console.log(\"open file\", entry.name, path)}\n      />\n    </div>\n  );\n}",
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. The slice is self-contained — imports only @/components/ui/* + @/lib/utils (cn). The filesystem backend is injected; nothing is hardcoded.\n\nSTEP 1 — Install. `npx rr add file-explorer`. Ensure `@/features/file-explorer` resolves in tsconfig paths and Tailwind's content globs scan the slice folder.\n\nSTEP 2 — shadcn + npm. `npx shadcn@latest add button input scroll-area separator dropdown-menu sheet`. npm: lucide-react.\n\nSTEP 3 — Mount it. Drop it in with NO adapter prop — it falls back to the backend configured in lib/backend.ts (the writable in-memory mock by default), so it works out of the box with realistic seed data and full CRUD:\n```tsx\n\"use client\";\nimport { FileExplorer } from \"@/features/file-explorer\";\nexport default function Page() {\n  return (\n    <div className=\"h-dvh\">\n      <FileExplorer rootLabel=\"Files\" onOpenFile={(path) => console.log(\"open\", path)} />\n    </div>\n  );\n}\n```\n\nSTEP 4 — The backend switch (ONE file). Go to a real filesystem without touching any component: edit `slices/file-explorer/lib/backend.ts` and set `FILE_EXPLORER_BACKEND = \"mock\" | \"live\" | \"convex\"` (or set env `NEXT_PUBLIC_FILE_EXPLORER_BACKEND`). \"live\" = REST host fs (os-vps /api/v1/fs shape, base via NEXT_PUBLIC_FILES_API_URL — see adapter/live.ts). \"convex\" = self-hosted Convex fs functions, PREPARED but inert until you wire your generated client + api in the switch (see adapter/convex.ts; the slice imports nothing from @convex so the build stays green even without Convex). You can still pass `adapter={…}` to override per-instance.\n\nSTEP 5 — Custom adapter. Implement FileExplorerAdapter: { mode: \"live\"|\"mock\"|\"readonly\", list(path), mkdir(path), remove(path), move(from,to), copy(from,to), upload(dest,files), usage(), rawUrl(path), write?(path,content) }. `list` returns { path, entries:[{name,kind,size,ext?}], roots?, parent? }. Set mode:\"readonly\" to show an inline notice instead of mutating. `rawUrl(path)` returns a bytes URL for image thumbnails (return \"\" to fall back to icons).\n\nThe container owns the box — render <FileExplorer> inside something with a height (h-dvh / h-full). It self-provides its adapter context; no extra provider needed.",
      "tags": [
        "files",
        "file-manager",
        "explorer",
        "tree",
        "breadcrumb",
        "crud",
        "sidebar",
        "ui"
      ]
    },
    {
      "slug": "appshell",
      "title": "AppShell — Desktop + Mobile OS Shell",
      "category": "os",
      "description": "Generic, brand-free OS-style shell framework. One <AppShell manifest> wrapper provider gives a project a macOS-style window manager (drag/snap/maximize, dock, menu bar, Spotlight) AND an iOS-style mobile surface (home pager, app library, control center, widgets), driven entirely by a manifest: brand, apps, features, surface regions, capabilities, persistence, keymap. Five shell features (search, inspector, notifications, control-center, widgets) are bundled as defineFeature() contributions inside the slice and mount via named <Slot>s. Responsiveness is a single ResponsiveProvider + 4 DRY primitives (AppFrame, MasterDetail, ResponsiveToolbar, TouchList). Imports nothing project-specific — the consumer injects data/auth/AI through manifest.capabilities. Lifted from os-vps (Topside).",
      "source": "rahmanef63/os-vps",
      "install": "npx rahman-resources add appshell",
      "npmPackages": [],
      "exampleCode": "// ════════ VARIANT A — simplest: no URL sync (app/page.tsx) ════════\n// Mount AppShell full-bleed. Verified-working shape.\n\"use client\";\n\nimport { FileText } from \"lucide-react\";\nimport {\n  AppShell,\n  searchFeature,\n  inspectorFeature,\n  notificationsFeature,\n  controlCenterFeature,\n  widgetsFeature,\n  type ShellManifest,\n} from \"@/features/appshell\";\nimport \"@/features/appshell/appshell.css\"; // REQUIRED — the shell's theme tokens\n\n// Your app. It receives { payload } (whatever opened the window).\nfunction NotesApp({ payload }: { payload?: unknown }) {\n  return (\n    <div className=\"h-full bg-background p-4 text-sm\">\n      Your app UI here. payload: {String(payload ?? \"—\")}\n    </div>\n  );\n}\n\n// ⚠ Capability hooks MUST return STABLE references (module-level / useMemo),\n// or Spotlight's search effect loops forever. Define once, return the same ref.\nconst NOOP = () => {};\nconst APPEARANCE = {\n  theme: \"light\" as const,\n  setTheme: NOOP, // wire to your theme store; also toggle `.dark` on <html>\n  device: \"auto\" as const,\n  wallpaper: \"aurora\",\n};\n\nconst manifest: ShellManifest = {\n  brand: { name: \"My OS\", logo: \"▲\", idleAppName: \"Finder\" },\n  apps: [\n    {\n      id: \"notes\",\n      title: \"Notes\",\n      icon: FileText,\n      gradient: \"linear-gradient(160deg,#ffd34d,#ff9a3d)\",\n      defaultSize: { w: 560, h: 380 },\n      multi: true, // several Notes windows at once\n      load: async () => ({ default: NotesApp }),\n    },\n    // add more apps = add more entries (each lazy-loads its own bundle)\n  ],\n  features: [\n    searchFeature,\n    inspectorFeature,\n    notificationsFeature,\n    controlCenterFeature,\n    widgetsFeature,\n  ],\n  routing: false, // set true ONLY if you add app/[[...slug]]/page.tsx (notFound _next)\n  capabilities: {\n    useAppearance: () => APPEARANCE,\n    useCpuPercent: () => null,\n    // optional, all must be stable refs:\n    // useSearch: () => myStableSearchFn,   // (q) => Promise<SearchHit[]>\n    // useSystemStats: () => myStatsOrNull,\n    // useChat: () => myStableChatFn,\n    // useServerToggle: () => myToggleOrNull,\n  },\n};\n\nexport default function Page() {\n  return <AppShell manifest={manifest} />;\n}\n\n// ════════ VARIANT B — addressable URLs (deep-link /notes, back/forward) ════════\n// Same manifest as A, but: DROP `routing: false` (default is ON) and give each\n// app a `slug`. Mount from a CATCH-ALL route instead of app/page.tsx. The dock\n// uses History-API URL sync (window.history, NOT router.push) — handled inside\n// the slice; you only provide the catch-all route below.\n\n// 1) components/shell.tsx — the client mount (apps carry slugs, routing left ON)\n\"use client\";\nimport { FileText } from \"lucide-react\";\nimport {\n  AppShell, searchFeature, inspectorFeature, notificationsFeature,\n  controlCenterFeature, widgetsFeature, type ShellManifest,\n} from \"@/features/appshell\";\nimport \"@/features/appshell/appshell.css\";\n\nfunction NotesApp({ payload }: { payload?: unknown }) {\n  return <div className=\"h-full bg-background p-4 text-sm\">Notes · {String(payload ?? \"—\")}</div>;\n}\nconst NOOP = () => {};\nconst APPEARANCE = { theme: \"light\" as const, setTheme: NOOP, device: \"auto\" as const, wallpaper: \"aurora\" };\n\nconst manifest: ShellManifest = {\n  brand: { name: \"My OS\", logo: \"▲\", idleAppName: \"Finder\" },\n  apps: [\n    {\n      id: \"notes\",\n      slug: \"notes\", // deep-link: /notes focuses (or opens) this app\n      title: \"Notes\",\n      icon: FileText,\n      gradient: \"linear-gradient(160deg,#ffd34d,#ff9a3d)\",\n      defaultSize: { w: 560, h: 380 },\n      multi: true,\n      load: async () => ({ default: NotesApp }),\n    },\n  ],\n  features: [searchFeature, inspectorFeature, notificationsFeature, controlCenterFeature, widgetsFeature],\n  // routing omitted => defaults TRUE => focused app + launch path mirror to the URL\n  capabilities: { useAppearance: () => APPEARANCE, useCpuPercent: () => null },\n};\n\nexport function Shell() {\n  return <AppShell manifest={manifest} />;\n}\n\n// 2) app/[[...slug]]/page.tsx — ONE optional catch-all (server). No per-app pages;\n//    the window manager stays client-side, only the URL is mirrored.\nimport { notFound } from \"next/navigation\";\nimport { Shell } from \"@/components/shell\";\n\nexport async function generateMetadata({ params }: { params: Promise<{ slug?: string[] }> }) {\n  const { slug } = await params;\n  return { title: slug?.[0] ? `${slug[0]} — My OS` : \"My OS\" };\n}\n\nexport default async function Page({ params }: { params: Promise<{ slug?: string[] }> }) {\n  const { slug } = await params;\n  // ⚠ MUST notFound() reserved paths: a missing /_next/* chunk has to 404 — else\n  // this catch-all returns the app HTML with 200 (wrong MIME, no client recovery).\n  if (slug?.[0] === \"_next\") notFound();\n  return <Shell />;\n}",
      "agentRecipe": "Stack required: Next 16 (App Router) + React 19 + Tailwind 4 + shadcn/ui. The slice is self-contained — it imports only @/components/ui/* + @/lib/utils (cn); everything project-specific arrives via the manifest. Follow ALL steps; the ⚠ ones are where installs break.\n\nSTEP 1 — Install. `npx rr add appshell` (alias `npx rahman-resources add appshell`). It copies to your slices dir. Ensure `@/features/appshell` resolves in tsconfig paths (point it at that dir), and that Tailwind's content globs SCAN the slice folder (else the shell renders unstyled).\n\nSTEP 2 — shadcn + npm deps. Add any missing shadcn primitives: `npx shadcn@latest add button tooltip scroll-area sheet drawer dialog alert-dialog dropdown-menu`. npm: lucide-react class-variance-authority clsx tailwind-merge vaul.\n\nSTEP 3 — ⚠ Theme. Import the slice's tokens ONCE in the root layout: `import \"@/features/appshell/appshell.css\"`. These are the glass/dock/window/wallpaper CSS variables the shell needs — they are NOT shadcn defaults, so skipping this = an unstyled, broken-looking shell. It pairs with your shadcn tokens (--background etc.). Dark mode = toggle the `.dark` class on <html> (appshell.css ships light + dark).\n\nSTEP 4 — Mount full-bleed. Render <AppShell manifest={manifest} /> from a CLIENT component that owns one full viewport (the page is h-dvh w-screen / the root). AppShell auto-picks the macOS desktop on wide viewports and the iOS surface on narrow — you write nothing extra for mobile.\n\nSTEP 5 — Build the ShellManifest:\n• brand: { name, logo (string or ReactNode), idleAppName?, wallpaper?: \"aurora\"|\"dusk\"|\"mist\"|\"noir\" }.\n• apps: AppDescriptor[] — { id, title, icon (a lucide-react icon component), gradient (a CSS gradient string for the glossy icon), load: async () => ({ default: YourAppComponent }), slug?, defaultSize?: {w,h}, multi?: true (spawn a new window per open, e.g. a file manager), noDock?: true }. Your app component receives props { payload }.\n• features: the fastest path is `features: DEFAULT_FEATURES` — the bundled default system-feature set (all five, generic + brand-free) exported from \"@/features/appshell\". Or import individually and list only what you want: searchFeature (⌘K Spotlight), inspectorFeature (⌘I AI/context panel), notificationsFeature (toasts + iOS dynamic island), controlCenterFeature (iOS control center), widgetsFeature (iOS Today widgets). The surfaces are slot-driven, so spreading/trimming DEFAULT_FEATURES just mounts/omits a feature — `features: [...DEFAULT_FEATURES.filter(f => f.id !== \"widgets\")]`.\n• capabilities: ShellCapabilities — your data/auth/AI injection seam. useAppearance() and useCpuPercent() are REQUIRED; useSearch/useSystemStats/useChat/useServerToggle are optional (defaults degrade gracefully). ⚠ CRITICAL: every capability hook MUST return a REFERENTIALLY STABLE value — a module-level const, or useMemo/useCallback. Returning a fresh object/closure each render makes Spotlight's search effect re-fire forever (\"Maximum update depth exceeded\"). e.g. define APPEARANCE once at module scope and `useAppearance: () => APPEARANCE`.\n• persistKey?: localStorage namespace for the saved window layout (default \"appshell:layout\").\n• routing?: defaults TRUE — it mirrors the focused app to the URL via the History API (window.history, NOT router.push). ⚠ If true you MUST add a catch-all route `app/[[...slug]]/page.tsx` that renders the mount AND calls notFound() for reserved paths (slug[0] === \"_next\"), or missing chunks return wrong-MIME 200s. SIMPLEST first install: set `routing: false` to skip the catch-all entirely.\n\nExtending: add an app = one manifest entry; add a shell feature = a new defineFeature({id, slots}) listed in features[]. No surface edits ever (open/closed). exampleCode ships BOTH variants: Variant A = routing:false mount in app/page.tsx (simplest); Variant B = catch-all app/[[...slug]]/page.tsx with routing on + app slugs for addressable, deep-linkable URLs (the catch-all MUST notFound() \"_next\").",
      "tags": [
        "shell",
        "window-manager",
        "desktop",
        "mobile",
        "responsive",
        "framework",
        "ui"
      ]
    },
    {
      "slug": "convex-auth",
      "title": "Convex Auth — Multi-Provider Sign-in",
      "category": "auth",
      "description": "@convex-dev/auth with Password (PBKDF2-SHA256 100k, self-hosted-friendly), Anonymous (guest), Google OAuth, and Resend magic-link. Ships a production SignInPage plus a presentational, props-driven AuthCard (v0.3) — choose `methods` (google, github, magic-link, password signin/signup tabs, phone OTP, anonymous) and render the card anywhere with different props; handlers default to a mock so it's interactive with zero wiring. i18n via labels. No Clerk.",
      "source": "rahmanef63/resource-site",
      "docsUrl": "https://labs.convex.dev/auth",
      "install": "npm i @convex-dev/auth @auth/core resend",
      "npmPackages": [
        "@convex-dev/auth",
        "@auth/core",
        "resend"
      ],
      "exampleCode": "// convex/auth.ts\nimport { convexAuth } from \"@convex-dev/auth/server\";\nimport Resend from \"@convex-dev/auth/providers/Resend\";\n\nexport const { auth, signIn, signOut, store, isAuthenticated } = convexAuth({\n  providers: [Resend({ from: \"auth@yourdomain.com\" })],\n});\n\n// app/proxy.ts (Next 16 — NOT middleware.ts)\nimport { convexAuthNextjsMiddleware } from \"@convex-dev/auth/nextjs/server\";\nexport default convexAuthNextjsMiddleware();",
      "agentRecipe": "Run `rr add convex-auth`. Then create convex/auth.ts using the kitab pattern (Resend provider). Set env via `npx convex env set` for self-hosted.",
      "tags": [
        "auth",
        "convex",
        "password",
        "magic-link",
        "google",
        "anonymous",
        "no-clerk",
        "pbkdf2"
      ]
    },
    {
      "slug": "payment",
      "title": "Payment — Indonesia PSP (DOKU · Midtrans)",
      "category": "integrations",
      "description": "Indonesia payment providers behind one slug + ONE shared Convex backend (convex/features/payment discriminates on a provider column: paymentOrders + paymentWebhookEvents, unprefixed). Two frontend variants: doku — DOKU Hosted Checkout + Direct (VA / QRIS / e-Wallet / PayLater), HMAC-SHA256 signed REST, signature-verified webhook, idempotent retries, dependency-free, server-side env only. midtrans — Snap hosted-modal checkout + orders history (needs npm midtrans-client + a NEXT_PUBLIC_MIDTRANS_CLIENT_KEY). Install one with `npx rr add payment doku|midtrans`, or both. A future stripe variant is reserved in the schema's provider union.",
      "source": "rahmanef63/resource-site",
      "docsUrl": "https://sandbox.doku.com/integration",
      "install": "",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add payment` for both providers, or `npx rr add payment doku` / `midtrans`. Either variant copies the shared convex/features/payment backend. doku: Checkout (hosted) or Direct (single channel → VA/QRIS/deeplink); webhook /webhooks/doku verifies HMAC-SHA256; server-only, no NEXT_PUBLIC_*. midtrans: Snap.js + window.snap.pay(token); webhook verifies signature_key; needs NEXT_PUBLIC_MIDTRANS_CLIENT_KEY. Both patch paymentOrders by orderId; sandbox by default.",
      "tags": [
        "payment",
        "checkout",
        "indonesia",
        "doku",
        "midtrans",
        "snap",
        "qris",
        "virtual-account",
        "ewallet",
        "psp"
      ]
    },
    {
      "slug": "resend-newsletter",
      "title": "Resend — Transactional & Newsletter",
      "category": "integrations",
      "description": "Transactional email + newsletter blast via Resend. Double opt-in flow + audience segmentation. Magic-link delivery for Convex Auth. Bundles the subscribers list backend (subscribe / confirm / unsubscribe / count) — formerly the standalone `subscribers` slice, merged here in v0.1.3.",
      "source": "rahmanef63/resource-site",
      "docsUrl": "https://resend.com/docs",
      "install": "npm i resend react-email @react-email/components",
      "npmPackages": [
        "resend",
        "react-email",
        "@react-email/components"
      ],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add resend-newsletter`. Use Resend Audiences API for newsletter — store subscriber emails in Convex too for segmentation. Double opt-in: subscriber.create with status 'pending' → click link → status 'confirmed'.",
      "tags": [
        "email",
        "newsletter",
        "resend"
      ]
    },
    {
      "slug": "ai-workspace",
      "title": "AI Workspace — chat · studio · agents",
      "category": "ai",
      "description": "Three AI surfaces as shadcn-style variants — `npx rr add ai-workspace <variant>` for one, or `npx rr add ai-workspace` for all + a switcher. Only the chat variant pulls a Convex backend (per-variant convex gating).\n\n  • chat — floating <AiChatFab /> + createAgenticChatSend: real function-calling over any ToolHost (@/shared/agentic), key-guarded, over convex/features/aiChat.\n  • studio — <AiStudioPage /> single-prompt generation canvas (variation grid + version tree, Suno / Midjourney / Lovable pattern) + aiStudioTools so a shared agent can drive generations.\n  • agents — <AiAgentsPage /> autonomous-worker run dashboard + createAgentRunner(host) which drives the shared function-calling loop and records each tool_use as a RunStep trace.\n\nUse cases: support chatbot in a marketing site, AI generation product (image / code / text / audio), background workers (nightly audits, scheduled crawls, moderation). studio + agents are frontend-only — wire your own persistence.",
      "source": "rahmanef63/resource-site",
      "docsUrl": "https://sdk.vercel.ai/docs",
      "install": "npm i ai @ai-sdk/anthropic @ai-sdk/openai",
      "npmPackages": [
        "ai",
        "@ai-sdk/anthropic",
        "@ai-sdk/openai"
      ],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add ai-workspace <chat|studio|agents>` for one surface, or `npx rr add ai-workspace` for all. chat: mount <AiChatFab chat={useAction(api.features.aiChat.action.chat)} />. studio: mount <AiStudioPage /> + drive via aiStudioTools. agents: mount <AiAgentsPage /> + trigger via createAgentRunner(host).",
      "tags": [
        "ai",
        "ai:chatbot",
        "ai:studio",
        "ai:agent",
        "agent-mode",
        "tool-calls",
        "streaming",
        "generation",
        "async",
        "traces",
        "multimodal"
      ]
    },
    {
      "slug": "ai-admin",
      "title": "AI Admin — Console (Instructions · Skills · Tools · Agents · Providers)",
      "category": "ai",
      "description": "Central operator console for the whole AI stack. Every other ai-* feature reads its registries from here. Tabs ordered to match the build-flow:\n\n  1. Providers   — register Anthropic / OpenAI / Google / Mistral / Ollama (API keys AES-encrypted at rest)\n  2. Models      — per-provider catalog (capabilities, context window, pricing)\n  3. Instructions — custom system-prompt library (Claude Projects-style)\n  4. Skills      — named instruction + model default + tool defaults (consumed by chat + studio)\n  5. Tools       — JSON-schema function specs + impl (http / convex / shell) + sandbox flag\n  6. Agents      — skill × model × tools × max-iter (consumed by ai-agents)\n  7. Budgets     — per-workspace cost caps + alerts + hard kill\n  8. Audit       — every AI call: actor / agent / tokens / cost / latency / outcome\n\nIncludes Create-Agent / Create-Skill / Create-Tool / Create-Instruction wizards.",
      "source": "rahmanef63/resource-site",
      "install": "",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add ai-admin`. Adds an `AI` section to the admin-panel ADMIN_SECTIONS registry. Sub-tabs ordered to match build-flow: Providers → Models → Instructions → Skills → Tools → Agents → Budgets → Audit. Includes Create-* wizards for instructions / skills / tools / agents. API keys AES-encrypted via AI_ADMIN_ENCRYPTION_KEY env. The instruction / skill / tool / agent registries are SSOTs consumed by every ai-* consumer slice (chat + studio + agents).",
      "tags": [
        "ai",
        "ai:admin",
        "instructions",
        "skills",
        "tools",
        "agents",
        "providers",
        "models",
        "budgets",
        "audit"
      ]
    },
    {
      "slug": "ai-router",
      "title": "AI Router — Backend Provider Proxy",
      "category": "ai",
      "description": "Backend infrastructure (no UI). Single proxy that every other ai-* feature calls. Tier-routed — nano (Haiku) for classification, mid (Sonnet) for chat, flagship (Opus) for deep reasoning. Per-call usage log + cost guard. Works with direct provider keys or OpenRouter umbrella.\n\nNot something you mount — installed automatically as a peer when you add ai-workspace.",
      "source": "rahmanef63/resource-site",
      "docsUrl": "https://sdk.vercel.ai/docs",
      "install": "npm i ai @openrouter/ai-sdk-provider",
      "npmPackages": [
        "ai",
        "@openrouter/ai-sdk-provider"
      ],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add ai-router`. Wrap every AI call through ai-router. Tiers: nano = quick classification (spam-flag, headline-suggest), mid = chat / draft, flagship = methodology-review / deep-think. Token usage logs to ai_usage table for the cost dashboard.",
      "tags": [
        "ai",
        "ai:backend",
        "tier-routing",
        "cost-guard"
      ]
    },
    {
      "slug": "vector-search",
      "title": "Convex Vector Search",
      "category": "data",
      "description": "Embeddings-based search via Convex's built-in vector index. Embed via OpenAI text-embedding-3-small (1536-dim), query via vectorIndex().",
      "source": "rahmanef63/resource-site",
      "docsUrl": "https://docs.convex.dev/database/vector-search",
      "install": "npm i openai",
      "npmPackages": [
        "openai"
      ],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add vector-search`. Add embedding field + vectorIndex per searchable table. Re-embed on upsert via Convex action. Cache embeddings — don't re-call OpenAI on every read.",
      "tags": [
        "search",
        "vector",
        "embeddings",
        "convex",
        "rag"
      ]
    },
    {
      "slug": "cal-com-booking",
      "title": "Cal.com Booking",
      "category": "data",
      "description": "Embedded Cal.com booking widget + webhook receiver to mirror bookings into Convex.",
      "source": "rahmanef63/resource-site",
      "docsUrl": "https://cal.com/docs/integrations/web-app/embed",
      "install": "npm i @calcom/embed-react",
      "npmPackages": [
        "@calcom/embed-react"
      ],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add cal-com-booking`. Embed Cal.com via @calcom/embed-react di halaman services. Configure webhook di Cal.com dashboard → POST ke /api/cal-webhook → upsert booking di Convex.",
      "tags": [
        "data",
        "scheduling",
        "cal-com",
        "bookings"
      ]
    },
    {
      "slug": "command-menu",
      "title": "Command Menu",
      "category": "ui",
      "description": "Renderless ⌘K command palette + generic search modal. Consumer supplies CommandGroup[] + onSelect + label bag; slice owns dialog chrome, ⌘K hotkey, MRU history. Pulled UP from notion-page-clone's command-palette renderless surface (Wave N+3.7) — Nosion adapters dropped at the kitab boundary.",
      "source": "notion-page-clone (consumerVersion 0.3.0) + earlier superspace facade",
      "docsUrl": "https://cmdk.paco.me",
      "install": "npm i cmdk",
      "npmPackages": [
        "cmdk"
      ],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add command-menu`. Wire <CommandPalette groups={...} onHistorySelect={...} labels={...} /> at the dashboard shell. Build groups from your feature registry; each item.onSelect handles navigation. Use <SearchModal bindings={{ pages, databases, recents, isLoading, onQueryChange, onSelectPage, onSelectDatabase }} /> for the search dialog — see slice README.md for adapter shapes.",
      "tags": [
        "ui",
        "palette",
        "cmd-k",
        "navigation",
        "keyboard",
        "search",
        "notion-like"
      ]
    },
    {
      "slug": "motion-primitives",
      "title": "Motion Primitives (8)",
      "category": "ui",
      "description": "Eight ready-to-style motion components: marquee, kinetic-heading, magnetic, cursor-spotlight, stat-counter, reading-progress, grain, lightbox. Framer-Motion-powered, tree-shakeable. Facade slice — pulls from template-base/frontend/slices/motion-primitives.",
      "source": "rahmanef.com",
      "docsUrl": "",
      "install": "npm i framer-motion",
      "npmPackages": [
        "framer-motion"
      ],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add motion-primitives`. Each primitive is independently importable from @/features/motion-primitives. Use marquee for logo strips, kinetic-heading for hero text, magnetic for CTA buttons, cursor-spotlight for hover-reveal panels, stat-counter for animated numbers, reading-progress for blog top bar, grain for film texture, lightbox for image gallery.",
      "tags": [
        "ui",
        "motion",
        "animation",
        "marquee",
        "framer-motion"
      ]
    },
    {
      "slug": "responsive-dialog",
      "title": "Responsive Dialog (Sheet ↔ Modal)",
      "category": "ui",
      "description": "ResponsiveDialog — auto-switches between bottom Sheet (mobile) and centered Dialog (desktop) at the md breakpoint. Same API as shadcn Dialog. Kitab forbids raw <dialog>; use this everywhere. Facade slice — pulls from template-base/frontend/slices/responsive-dialog.",
      "source": "superspace",
      "docsUrl": "",
      "install": "",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add responsive-dialog`. Drop-in for shadcn Dialog. Use <ResponsiveDialog><ResponsiveDialogTrigger>…</ResponsiveDialogTrigger><ResponsiveDialogContent>…</ResponsiveDialogContent></ResponsiveDialog>. On mobile renders as Sheet sliding from bottom; on desktop as centered Dialog. Threshold via useMediaQuery('(min-width: 768px)').",
      "tags": [
        "ui",
        "dialog",
        "modal",
        "sheet",
        "responsive",
        "primitive"
      ]
    },
    {
      "slug": "dashboard-shell",
      "title": "Dashboard Shell — Responsive",
      "category": "ui",
      "description": "ResponsiveDashboardShell — desktop sidebar + topbar, mobile dock + sheet sidebar, breakpoint-aware. Ports superspace's layout/dashboard/{Desktop,Mobile,Responsive}DashboardShell + sidebar primary/secondary slots. Facade slice — pulls from template-base/frontend/slices/dashboard-shell.",
      "source": "superspace",
      "docsUrl": "",
      "install": "",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add dashboard-shell`. Wraps app/(admin) routes. <ResponsiveDashboardShell sidebar={<AppSidebar />} topbar={<TopBar />}>{children}</ResponsiveDashboardShell>. Mobile: sidebar collapses to <Sheet>. Desktop: persistent sidebar + topbar. Embed FullWidthToggle in topbar for instant container resize.",
      "tags": [
        "ui",
        "layout",
        "dashboard",
        "sidebar",
        "topbar",
        "responsive"
      ]
    },
    {
      "slug": "three-column",
      "title": "Three-Column Layout — Sidebar/Content/Inspector",
      "category": "ui",
      "description": "ThreeColumnLayoutAdvanced — collapsible left/right + resizable widths + responsive breakpoints + PanelSection compound (Header/Items/Footer) + per-panel footer slots. Models shadcn sidebar API for the panel interior. Pair with PanelGroup/PanelMenu/PanelSeparator primitives. Trigger ≠ header (V-wave separation rule).",
      "source": "superspace",
      "docsUrl": "",
      "install": "",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add three-column`. <ThreeColumnLayoutAdvanced preset=\"feature\" storageKey persistState left={…PanelSection…} center={…PanelSection unstyled…} right={…PanelSection…} leftFooter centerFooter rightFooter />. Center column SHOULD pass `unstyled` to drop sidebar tokens — body is content surface. `storageKey` MUST differ per slice or persisted widths collide.",
      "tags": [
        "ui",
        "layout",
        "three-column",
        "sidebar",
        "inspector",
        "panel-section",
        "responsive",
        "resizable"
      ]
    },
    {
      "slug": "broadcast-channel-sync",
      "title": "BroadcastChannel — Cross-tab Sync",
      "category": "data",
      "description": "Same-origin cross-tab + cross-iframe state sync via BroadcastChannel API. Tiny, no backend, no install.",
      "source": "Web Platform — BroadcastChannel API",
      "docsUrl": "https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API",
      "install": "// no install — Web Platform API",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add broadcast-channel-sync`. Use BroadcastChannel only for demo / cross-iframe state mirroring. Production data still goes through Convex realtime. Use the useBroadcastSync(channelName, initial) hook from @/features/broadcast-channel-sync.",
      "tags": [
        "realtime",
        "cross-tab",
        "broadcast-channel",
        "demo-pattern"
      ]
    },
    {
      "slug": "rbac-roles",
      "title": "RBAC — Roles & Permissions",
      "category": "auth",
      "description": "RBAC engine ported from superspace. 6 system role presets (owner/admin/manager/staff/client/guest with levels), dot-namespaced permissions with `*` / `feature.*` wildcard matching, and pure check helpers (resolvePermissions / hasPermission / roleHasPermission). Props-driven UI primitives: <PermissionGate>, usePermissions, <RoleBadge>, <PermissionMatrix>. Convex template ships a tenant-scoped rbac_roles table + checkPermission / requirePermission helpers + idempotent seedSystemRoles, with a PLATFORM_ADMIN_EMAILS superadmin bypass. Pair with `user-management` for the members / invites / roles-admin UI. @convex-dev/auth aware — no Clerk.",
      "source": "superspace",
      "install": "npx rahman-resources add rbac-roles",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add rbac-roles`. Frontend: import { PermissionGate, usePermissions, RoleBadge, PermissionMatrix, resolvePermissions, ROLE_PRESETS } from \"@/features/rbac-roles\". Feed usePermissions/PermissionGate the actor's resolved permission list (from your membership query or resolvePermissions(roleSlug)). Convex: spread rbacRolesTables into your schema, call seedSystemRoles({tenantId}) once, gate privileged fns with requirePermission(ctx, tenantId, \"members.manage\"). Set PLATFORM_ADMIN_EMAILS for superadmins. Add the user-management slice for the members/invites UI (provides um_members).",
      "tags": [
        "rbac",
        "auth",
        "permissions",
        "roles",
        "authorization",
        "no-clerk",
        "convex"
      ]
    },
    {
      "slug": "user-management",
      "title": "User Management",
      "category": "auth",
      "description": "Full superspace-parity user management, props-driven + RBAC-agnostic. <UserManagementPanel> tabs Members + Roles + Teams + Access: member table (search / filter / sort, inline role dropdown, soft-remove), InviteDialog (with an optional 'propagate to sub-workspaces' toggle — same / step-down role strategy) + PendingInvites, a RolesPanel (custom roles via permission matrix; system roles read-only), a TeamsPanel (named user groups), and an AccessMatrix (users × tenants grid with inline role assignment). All permission-gated. You pass `roles` + `currentPerms` + the permission catalog (resolved from rbac-roles) + callbacks; the slice imports no other slice's frontend. Convex ships um_members + um_invites + um_teams + um_team_members + um_tenant_links + member / invite / team / hierarchy endpoints + getAccessMatrix (gated via rbac-roles' requirePermission); roles CRUD reuses rbac-roles'. The hierarchy is a generic edge tree — rr never owns the tenant entities. P0–P4c: the complete user-management epic.",
      "source": "superspace",
      "install": "npx rahman-resources add user-management",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add user-management` (pulls rbac-roles + convex-auth). Frontend: <MembersPanel members={useQuery(api[\"features/user_management/query\"].listMembers,{tenantId})} roles={ROLE_PRESETS.map(r=>({slug:r.slug,name:r.name,color:r.color}))} currentPerms={actorPerms} onUpdateRole={useMutation(...updateMemberRole)} onRemove={useMutation(...removeMember)} onInvite={openInvite} />. Wire roles + currentPerms from rbac-roles at the app level — the slice itself imports no other slice. Convex: spread userManagementTables; listMembers/mutations gate via rbac-roles requirePermission.",
      "tags": [
        "user-management",
        "members",
        "rbac",
        "auth",
        "team",
        "admin",
        "convex",
        "no-clerk"
      ]
    },
    {
      "slug": "admin-panel",
      "title": "Admin Panel — Unified Product Admin",
      "category": "infra",
      "description": "17-section admin surface (events, funnels, attribution, users, A/B, flags, pricing, CMS, email, audit, ...) gated by RBAC. Auto-filters sidebar by tier (solo/influencer/organization) and user permissions. Single backend resolver (getMyAdminAccess) mirrors frontend gate so UI can never leak.",
      "source": "superspace + spec",
      "install": "npx rahman-resources add admin-panel",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add admin-panel`. Wrap pages with <AdminPage workspaceId tier>. AccessGate hides UI for non-admins, AdminShell renders 2-col layout with sidebar filtered by tier+perms. ADMIN_SECTIONS in config.ts is SSOT (17 entries). Personal-brand-os = tier 'solo' = owner sees everything.",
      "tags": [
        "admin",
        "owner",
        "platform",
        "rbac",
        "instrumentation",
        "panel"
      ]
    },
    {
      "slug": "event-tracking",
      "title": "Event Tracking — P0 Instrumentation",
      "category": "data",
      "description": "Client SDK + Convex ingestion endpoint for structured product events. Auto-captures page_view/signup/login + UTM/referrer/first-touch attribution. Batched flush via requestIdleCallback. Targets <100ms p99 ingestion.",
      "source": "spec + superspace analytics",
      "install": "npx rahman-resources add event-tracking",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add event-tracking`. Writes to analyticsEvents table (no new schema). Anonymous page_view allowed pre-signup; other events require workspaceId. Session id per tab (sessionStorage), first-touch UTM in localStorage. Flush every ~500ms via requestIdleCallback. Cap retry queue at 500.",
      "tags": [
        "events",
        "analytics",
        "instrumentation",
        "attribution",
        "utm",
        "p0"
      ]
    },
    {
      "slug": "icon-picker",
      "title": "Icon Picker",
      "category": "ui",
      "description": "Emoji + lucide (outline) + phosphor (fill) icon picker with search, 10-color palette, Twemoji/native toggle, recents tracking, and smart positioning. Two-tab layout (Emoji | Icon) with sub-variant pills (Native | Twemoji / Lucide | Phosphor fill). One string stores emoji OR lucide:Name OR phosphor:Name OR with ?c=hex tint — backwards-compat with raw-emoji fields. Popover auto-flips on collision (caps to Radix `--radix-popover-content-available-height`) and falls back to centered Dialog when neither side fits. Two variants: Popover (compact trigger) and Inline (full sheet/dialog use). Lifted 2026-05-25 from open-silong.",
      "source": "open-silong",
      "install": "npx rahman-resources add icon-picker",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add icon-picker` then `pnpm add @phosphor-icons/react`. parseIconValue() decodes; lucideValue() / phosphorValue() / withColor() build. Storage forms: `lucide:Name?c=hex` (outline) or `phosphor:Name?c=hex` (fill) or raw emoji. Add 'icon: v.string()' to Convex table — no migration needed for existing emoji + lucide fields. <IconPickerPopover> wraps any trigger (auto-flips, falls back to centered Dialog on tight viewports); <IconPickerInline> for sheets/dialogs. <DynamicIcon> renders from parsed value.",
      "tags": [
        "icon",
        "emoji",
        "lucide",
        "phosphor",
        "picker",
        "twemoji",
        "notion",
        "notion-like",
        "responsive"
      ]
    },
    {
      "slug": "activity",
      "title": "Activity — public productivity log",
      "category": "data",
      "description": "Public-facing weekly activity log. Lists user-facing activities grouped by ISO week with schema.org-friendly markup, designed to maximise SEO so the question 'what is <person> working on this week?' lands here. Convex-backed (schema + queries + unauthenticated mutations); MCP-friendly so AI workflows (Claude / GPT / custom agents) can append entries directly. All user-facing copy + per-category labels + date/time locale are prop-driven (English defaults). Lifted 2026-05-27 from rahmanef.com; 225-LOC view split into view + 2 sub-components + 4 lib helpers for the 200-LOC cap; Indonesian strings + custom primitives stripped; cross-slice auth import dropped (consumer wraps mutations).",
      "source": "rahmanef.com",
      "install": "npx rahman-resources add activity",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add activity`. Spread `activityTables` into your root Convex schema. Wrap the unauthenticated `create`/`update`/`remove` `internalMutation`s with your auth model (see README Install section). Render `<ActivityFeed rows={await fetchQuery(api.activity.listPublic)} stats={await fetchQuery(api.activity.statsThisWeek)} />`. Override `copy`, `categoryLabels`, `locale` per consumer. MCP integration: map `activity_create` tool → your wrapped `create` mutation.",
      "tags": [
        "activity",
        "productivity",
        "log",
        "now-page",
        "feed",
        "mcp",
        "seo",
        "personal-brand"
      ]
    },
    {
      "slug": "rate-limit",
      "title": "Rate Limit",
      "category": "infra",
      "description": "Convex-backed per-key request counter. Atomic check-and-increment via `consume` mutation; expired rows pruned by `_pruneExpired` internalMutation wired to a 5-min cron. Replaces single-replica in-memory Map so multi-replica Next deployments share buckets. Limits live in an in-code POLICY map keyed by namespace prefix (admin-login:<ip>, mcp:<ip>) — never caller-supplied; optional RATE_LIMIT_SERVER_KEY env gates anonymous calls. Lifted 2026-05-16 from rahmanef.com; hardened 2026-06-07.",
      "source": "rahmanef.com",
      "install": "npx rahman-resources add rate-limit",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add rate-limit`. Compose `rateLimitTables` into root convex/schema.ts. Wire `internal.features.rate_limit.mutations._pruneExpired` into convex/crons.ts every 5 min. Add your namespace to the in-code POLICY map, then call `api.features.rate_limit.mutations.consume({ key, serverKey })` from server-side handlers — keep a fail-open wrapper so a Convex outage doesn't 503 the route. Set RATE_LIMIT_SERVER_KEY on the deployment to block anonymous consume calls.",
      "tags": [
        "infra",
        "rate-limit",
        "convex",
        "backend",
        "throttle"
      ]
    },
    {
      "slug": "testimonials",
      "title": "Testimonials",
      "category": "content",
      "description": "Quote/name/role rotator backend. Public `listAll` + `get` (no auth — testimonials are public), admin CRUD via `requireAdmin`, internal `seed` for one-shot bootstrap. Indexed by `order` so carousel/grid keeps stable rotation. Lifted 2026-05-16 from rahmanef.com; token-based admin gate swapped for rr `_shared/auth`.",
      "source": "rahmanef.com",
      "install": "npx rahman-resources add testimonials",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add testimonials`. Compose `testimonialsTables` into root schema. Bootstrap via `npx convex run internal.features.testimonials.mutations.seed '{\"items\":[{\"quote\":\"...\",\"name\":\"...\",\"role\":\"...\",\"order\":1}]}'`. Render with `useQuery(api.features.testimonials.queries.listAll)`.",
      "tags": [
        "content",
        "testimonials",
        "convex",
        "backend",
        "marketing"
      ]
    },
    {
      "slug": "services",
      "title": "Services",
      "category": "content",
      "description": "Service offerings backend — title + summary + deliverables array + sort order. Public read, admin CRUD, internal seed. Pairs with a frontend services grid/list (consumer-side). Lifted 2026-05-16 from rahmanef.com; token-based admin gate swapped for rr `_shared/auth`.",
      "source": "rahmanef.com",
      "install": "npx rahman-resources add services",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add services`. Compose `servicesTables` into root schema. Use `useQuery(api.features.services.queries.listAll)` from a server component / route to render service cards. CRUD via admin UI calling `create` / `update` / `remove` after `requireAdmin` passes.",
      "tags": [
        "content",
        "services",
        "convex",
        "backend",
        "marketing",
        "agency"
      ]
    },
    {
      "slug": "create-your-mcp",
      "title": "Create Your MCP",
      "category": "ai",
      "description": "Turn any rr-based app into an MCP server that ChatGPT custom apps, Claude.ai connectors, Cursor MCP, and other AI clients authenticate to. OAuth 2.1 + PKCE flow with code → bearer exchange, env-configured vendor-host allowlist, single-use codes, 1-year bearer tokens, scope-tagged tools, opaque error collapsing, constant-time token compare. Static MCP_API_KEY fallback for service-account / CI scripts. Sanitized 2026-05-16 from rahmanef.com's production MCP integration — vendor literals (chatgpt.com / OpenAI paths) replaced with MCP_OAUTH_ALLOWED_HOSTS + MCP_OAUTH_ALLOWED_PATH_PREFIXES env vars so the slice ships portable.",
      "source": "rahmanef.com",
      "install": "npx rahman-resources add create-your-mcp",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add create-your-mcp`. Compose `createYourMcpTables` into root schema. Move `slices/create-your-mcp/routes/mcp.route.ts` → `app/api/mcp/route.ts` and `oauth-token.route.ts` → `app/api/oauth/token/route.ts`. Set MCP_OAUTH_ALLOWED_HOSTS (CSV vendor domains). Mount `<McpAdminView />` at /admin/mcp. Connect ChatGPT/Claude/Cursor via the setup form rendered by the admin view.",
      "tags": [
        "ai",
        "mcp",
        "oauth",
        "pkce",
        "chatgpt",
        "claude",
        "cursor",
        "convex",
        "integration"
      ]
    },
    {
      "slug": "contact-form-resend",
      "title": "Contact Form + Resend",
      "category": "integrations",
      "description": "Contact form posting to Resend email API. Server Action + Zod input validation. Convex mutation for storage + Resend send.",
      "source": "cescadesigns",
      "install": "npx rahman-resources add contact-form-resend",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add contact-form-resend`. Wire contactMessages.send mutation in convex/. Server emails via Resend from form@yourdomain.com. Always validate inputs with Zod or v.* server-side. Anonymous allowed.",
      "tags": [
        "form",
        "email",
        "resend",
        "convex"
      ]
    },
    {
      "slug": "admin",
      "title": "Admin — generic shell + composed console",
      "category": "infra",
      "description": "Access-gated admin surfaces behind one slug, in two variants — each pulls ONLY its own convex backend (per-variant convex gating). shell: a HEADLESS minimal generic admin shell — a titled landing region + a portable buildAdminStats(opts) nav-from-registry factory (consumer supplies a SliceRegistryAdapter + queryTable reader) over convex/features/admin; superadmin gate via SUPER_ADMIN_EMAIL. console: the composed admin panel distilled from ~15 project admin panels — a gated two-column shell (AdminConsole) over a 26-section registry (ADMIN_CONSOLE_SECTIONS: observability / identity / ai / content / commerce / config) that mounts OTHER rr slices via a consumer-supplied `components` map (users→user-management, roles→rbac-roles, ai→ai-admin, tenants→platform-admin) plus 5 owned gap sections (Analytics, Audit-log, Nav config, SEO health, Leads/CRM) over convex/features/admin_console (ac_leads + ac_nav_items); gate injected, PLATFORM_ADMIN_EMAILS allowlist. Install one with `npx rr add admin shell|console`, or both with `npx rr add admin`. NOT the multi-tenant control plane — that's the separate `platform-admin` slice (the console's `tenants` section provider).",
      "source": "rahmanef63/resource-site",
      "install": "npx rahman-resources add admin",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add admin` for both, or `npx rr add admin shell` / `console` for one — each variant pulls only its own convex backend. shell: mount <AdminPage labels={...} /> + call buildAdminStats({ sliceRegistry, queryTable }) in convex/features/admin/query.ts; lock down with SUPER_ADMIN_EMAIL. console: mount <AdminConsole access={useAdminAccess()} components={{ users: <UsersPanel/>, ... }} /> — owned sections (analytics/audit-log/nav-config/seo-health/leads) render as-is, map each reuse section id to the panel from the peer slice you installed; compose adminConsoleTables into convex/schema.ts and front ac_leads.create with rate-limit; gate via PLATFORM_ADMIN_EMAILS.",
      "tags": [
        "infra",
        "admin",
        "console",
        "shell",
        "dashboard",
        "composition",
        "rbac",
        "access-gate",
        "registry"
      ]
    },
    {
      "slug": "platform-admin",
      "title": "Platform Admin — Multi-Tenant Control Plane",
      "category": "infra",
      "description": "Multi-tenant SaaS control plane. Workspace lifecycle ops (list/delete/cascade), per-tenant tier presets (gates + quota), KPI dashboard grid. Consumer-domain bits injected via adapter props (tenantTablesAdapter / tierPresets / kpiSources). Contract-only scaffold; canonical implementation lands via /rr-send from superspace. See docs/contract-negotiations-2026-05-15.md §4.",
      "source": "rahmanef63/resource-site",
      "install": "npx rahman-resources add platform-admin",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add platform-admin`. Contract-only scaffold. Wait for superspace /rr-send platform-admin before adopting. Distinct from per-instance `admin` slug.",
      "tags": [
        "infra",
        "admin",
        "multi-tenant",
        "saas",
        "platform"
      ]
    },
    {
      "slug": "audit-log",
      "title": "Audit Log — Workspace Events",
      "category": "infra",
      "description": "Workspace-scoped audit event recorder. Canonical logAuditEvent helper for mutations + actions; supports entity tracking, before/after diff, IP/user-agent capture.",
      "source": "rahmanef63/resource-site",
      "install": "npx rahman-resources add audit-log",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `rr add audit-log`. Import logAuditEvent from convex/_shared/auditLogger.ts and call inside every workspace-scoped mutation with { action, workspaceId, entityType, entityId, before?, after? }.",
      "tags": [
        "infra",
        "audit",
        "compliance",
        "logging"
      ]
    },
    {
      "slug": "comments",
      "title": "Comments — Threaded",
      "category": "content",
      "description": "Polymorphic-target threaded comments. Consumer picks `TargetRef = { kind, id, subId? }` (e.g. page+block, blog+slug, task+id). Reply nesting is real: `parentId` end-to-end + `buildThread(flat) → CommentNode[]` tree (oldest-first, orphan-safe). Renderless <CommentsThread> + <CommentsAnchor> wrappers; useComments(bindings, opts) returns items + `tree` + openCount + CRUD + forbiddenWords guard. Adapter pattern — see contract-negotiations §1.",
      "source": "rahmanef63/resource-site",
      "install": "npx rahman-resources add comments",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `rr add comments`. Wire Convex bindings ({ list, create, update, resolve, remove }) then use <CommentsThread target={{ kind, id, subId? }} bindings={bindings} forbiddenWords={[...]}>{render-prop}</CommentsThread> OR <CommentsAnchor target=... bindings=... pathMap={(t)=>...}>. v0.2.0 polymorphic — pick `kind` literal per host domain.",
      "tags": [
        "content",
        "social",
        "comments",
        "threaded",
        "annotations"
      ]
    },
    {
      "slug": "seo",
      "title": "SEO — AI Metadata Generator",
      "category": "content",
      "description": "Service slice for SEO metadata generation — Anthropic-backed action with per-user 24h cost guard + portable persona prop. No public route. Backend exposes generate + generateAndApply mutations gated by requireAdmin; consumers inject brand voice via the personaContext arg (or buildSeoSystemPrompt factory).",
      "source": "rahmanef63/resource-site",
      "install": "npx rahman-resources add seo",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `rr add seo`. Call seo.generate from server actions or admin mutations with `personaContext` describing your brand voice (or rely on the generic default). Cost guard rate-limits per-user within 24h via callsInWindow query.",
      "tags": [
        "content",
        "seo",
        "ai",
        "anthropic",
        "metadata-generator"
      ]
    },
    {
      "slug": "publisher-clean-html",
      "title": "Publisher — clean HTML",
      "category": "content",
      "description": "A pure render-to-clean-HTML engine harvested from the Instatic CMS publisher, decoupled from its host caching / loops / visual-components / Layer-C islands. publishPage(tree, registry, options) walks a generic node tree bottom-up: render children, escape every prop by its schema-declared control type (url -> safe-URL, richtext -> DOMPurify, svg -> SVG profile, else HTML-escape), dedup CSS by moduleId (~60-80% shrink), splice author classes + inline styles onto each rendered root, then assemble <!DOCTYPE> + reset + framework + module CSS + a deterministic (sorted) CSP plan. Bring your own ModuleRegistry (each module is a pure render(props, children) -> { html, css? }). Security spine: HTML escape + safe-URL, CSS-value guard (expression()/{}/</), </style RAWTEXT neutraliser, and an injectable DOMPurify seam (configureRichtextSanitizer) that fails closed — without a runtime, richtext strips all tags and SVG returns empty. Stateless, env-free, ZERO npm deps, no Convex. Ships a PublishPreview iframe-srcdoc pane. A Wave-1 leaf of the feature-harvest ULTRAPLAN; a dependency of the planned visual-page-canvas.",
      "source": "rahman-resources",
      "install": "npx rahman-resources add publisher-clean-html",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add publisher-clean-html`. Build a registry: createModuleRegistry([{ id: 'base.body', render: (_p, kids) => ({ html: kids.join('') }) }, { id: 'demo.h', schema: { text: { type: 'text' } }, render: (p) => ({ html: `<h1>${p.text}</h1>`, css: 'h1{font-size:1.5rem}' }) }]). Tree = { rootNodeId, nodes: { [id]: { id, moduleId, props?, children?, classIds?, inlineStyles?, hidden? } } }. const { html } = publishPage(tree, registry, { title, cssEmission: 'inline' }). Preview: <PublishPreview html={html} />. Enable rich HTML/SVG by calling configureRichtextSanitizer(DOMPurify) once — without it, richtext/svg props fail closed (strip/empty). Props escape by schema control type, not key name.",
      "tags": [
        "content",
        "publisher",
        "html",
        "static-export",
        "sanitization",
        "csp",
        "css-dedup",
        "render"
      ]
    },
    {
      "slug": "content-loops",
      "title": "Content Loops",
      "category": "content",
      "description": "A data-source-driven repeater harvested from the Instatic CMS base.loop engine, decoupled from its publisher / page-tree / entryStack machinery into a plain React slice. Register pluggable LoopEntitySource backends (each declares display fields + an async fetch returning { items, totalItems }); drop <ContentLoop source|sourceId filters orderBy variants={[A, B]} /> to render one component per item, round-robining items across variants so alternating / featured layouts need no per-item branching. Ships a namespaced source registry (ids must be 'ns.name', so consumer sources can't shadow each other), createMockLoopSource for env-free previews + tests, and none/infinite pagination via useLoopPagination (a shadcn Load more button accumulates pageSize chunks). LoopItem.fields is a generic resolved-value bag — variants read item.fields.title directly, no second lookup. UI-only: no Convex tables shipped; point a source's fetch at Convex/REST when you have a backend. First slice of the feature-harvest ULTRAPLAN (docs/feature-harvest) and a dependency of the planned site-templates-engine + visual-page-canvas.",
      "source": "rahman-resources",
      "install": "npx rahman-resources add content-loops",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add content-loops`. Env-free demo: createMockLoopSource() then <ContentLoop source={s} pagination='infinite' pageSize={6} variants={[CardA, CardB]} /> — variants round-robin (item i -> variants[i % n]). Real source: implement LoopEntitySource { id: 'blog.posts' (namespaced 'ns.name'), fields, async fetch({ filters, orderBy, direction, limit, offset }) returns { items, totalItems } }, call loopSourceRegistry.registerOrReplace(source), then <ContentLoop sourceId='blog.posts' variants={[...]} />. item.fields holds RESOLVED values — resolve media/author inside fetch.",
      "tags": [
        "content",
        "loop",
        "repeater",
        "list",
        "data-source",
        "pagination",
        "variants"
      ]
    },
    {
      "slug": "markdown",
      "title": "Markdown — page container with CRUD tabs + diagrams",
      "category": "content",
      "description": "Markdown (.md) page container with optional CRUD surfaces. <MarkdownPage content={md} tabs={['read','write','review']}/> — Read renders rich text (headings, lists, todo, GitHub-style callouts, fenced code, KaTeX, tables, images, <details> toggles, inline marks); Write is a raw-source editor with snippet toolbar + live preview; Review overlays block-anchored comments (add/resolve, controlled via onAddComment/onResolveComment or internal fallback). Fenced ```mermaid blocks render as SVG diagrams (dynamic-imported mermaid) and ```chart blocks as recharts bar/line/area/pie from a JSON spec. Self-contained: ships its own parser (parseMarkdown → MdNode[]) + inline renderer, no notion runtime dependency. Sync is by shared grammar: the notion cluster's blocksToMarkdown / markdownToBlocks bridge (@notion/shared/lib/markdown) emits/consumes the exact same markdown this slice parses, so anything readable in the notion block page is readable here and vice-versa. No store, no Convex — comments CRUD is consumer-wired callbacks.",
      "source": "rahman-resources",
      "install": "npx rahman-resources add markdown",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add markdown`. Read-only: `<MarkdownReader content={md}/>`. Full surface: `<MarkdownPage content={md} tabs={['read','write','review']} onContentChange={save} comments={list} onAddComment={add} onResolveComment={resolve}/>` (omit callbacks for internal-state demo mode). Diagrams: fence ```mermaid; charts: fence ```chart with { type: bar|line|area|pie, data: [...] }. To bridge from the notion editor call `blocksToMarkdown(page.blocks)` from `@notion/shared/lib/markdown`; reverse with `markdownToBlocks(md)`.",
      "tags": [
        "content",
        "markdown",
        "reader",
        "editor",
        "review",
        "comments",
        "mermaid",
        "chart",
        "rich-text",
        "docs",
        "notion-sync"
      ]
    },
    {
      "slug": "notion-app",
      "title": "Notion App — Block Editor",
      "category": "content",
      "description": "Nested vertical slice (slice-of-slices) housing the full notion-page-clone block editor. Mount <PageEditor pageId/> inside <EditorAdapterProvider adapter/> — with `{}` it is a working plain-text/markdown block editor (slash menu, markdown triggers `# - > [] etc.`, dnd-kit drag with column layouts, per-block toolbar with turn-into/color/duplicate, per-block undo, paste-markdown import); host capabilities light up per optional adapter: data (block+page CRUD), selection (multi-select), comments (per-block popover), ai (Ask-AI panel), database (render + picker), mention (@-typeahead), page (nav/uploads/covers). Cluster-private shared layer under @notion/* — vendored block/page/database model, uid, inline markdown, page→md/html export. Pure convex block helpers (_blocks/_blockOps, unit-tested) ship in convex/features/notion. Same markdown grammar as the standalone `markdown` slice (blocksToMarkdown/markdownToBlocks bridge).",
      "source": "notion-page-clone",
      "install": "npx rahman-resources add notion-app",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add notion-app`. Wire the `@notion/*` path alias to `./slices/notion-app/*` in tsconfig. Minimal mount: `<EditorAdapterProvider adapter={{ data }}><PageEditor pageId={id}/></EditorAdapterProvider>` where `data` implements EditorDataAdapter (block+page CRUD over your store — see lib/dataAdapter.ts; a localStorage reference impl lives in the rr preview). Add capabilities incrementally: `selection` for multi-select, `comments` for per-block threads, `database.renderDatabase` to mount your database renderer inside database blocks, `mention.search` for @-typeahead, `page.navigateToPage`/`uploadFile` for nav + media. Convex hosts: copy convex/features/notion (_blocks/_blockOps are pure, unit-tested array ops) and keep handlers thin.",
      "tags": [
        "content",
        "notion",
        "editor",
        "block-editor",
        "rich-text",
        "slash-menu",
        "drag-drop",
        "adapter-seam"
      ]
    },
    {
      "slug": "sections",
      "title": "Sections — composable marketing/landing sections",
      "category": "content",
      "description": "Canonical landing-page composition slice — replaces the former standalone hero / cta / pricing-page / faq-section / feature-grid / testimonials-grid / blog-section / portfolio-section / changelog-feed slices (all merged here as `kind` variants in v0.2.0). Ships a pure reducer (v0.4.0: LANDING_UPSERT auto-shifts sibling `order` to keep positions unique; LANDING_DELETE closes the gap) + LandingProvider store adapter + admin LandingView/LandingEditorView built on the shared CRUD primitives, plus a per-section LandingSectionShell (background image + custom Tailwind className overlay + scroll-reveal). NEW in v0.4.0: a `sections/` library of config-driven public renderers (StatsSection, TestimonialsSection, FaqSection, PricingSection, NewsletterSection, CustomSection) that read `LandingSection.config` JSON merged over template defaults — content stays dashboard-controlled without per-template renderer code; plus `parse-config` helpers (parseConfigBadge/parseConfigField) and `sections/config` guards (parseConfigObject, cfg*). Sections carry { kind, order, title, subtitle, enabled, imageUrl, imageRatio, bgImageUrl, className, config (JSON) } with up/down reorder arrows. Lifted from the _templates fleet `_shared/landing` (2026-06-11) — the 8 standalone templates ship a byte-similar copy; this rr slice is the SSOT. Used by all 7 rr website templates.",
      "source": "rahman-resources (lifted from _templates fleet)",
      "install": "npx rahman-resources add sections",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add sections`. Fold `landingReducer` into your root reducer (cases LANDING_UPSERT + LANDING_DELETE), seed State.landingSections with `defaultLandingSections()`, wrap your StoreProvider with `<LandingProvider value={adapter}/>` where adapter maps {items, publicBase, adminBase, create, update, remove} from your dispatch. Mount `<LandingView/>` at `/admin/landing` and `<LandingEditorView id={params.id}/>` at `/admin/landing/[id]`. In HomePage iterate `state.landingSections.filter(s => s.enabled).sort((a,b) => a.order - b.order)` and render each inside `<LandingSectionShell section={s}>`; for stats/testimonials/pricing/faq/newsletter/custom kinds drop in the shipped `<StatsSection/>` etc. (they read `section.config` JSON over your template defaults), or map the remaining kinds (hero/features/blog/etc.) to your own renderer. Use `parseConfigBadge(section.config)` for a section badge. Requires the template-base shared surface that ships in every rr website template: `@/components/templates/_shared/motion` (Reveal/Stagger/CountUp/Marquee/useInView — the motion-kit primitives), `@/components/templates/_shared/ui/section-head`, and `@/components/templates/_shared/crud/*`. Sections also use shadcn accordion/card/carousel + embla-carousel-autoplay.",
      "tags": [
        "admin",
        "landing",
        "cms",
        "sections",
        "crud",
        "renderer"
      ]
    },
    {
      "slug": "motion-kit",
      "title": "Motion Kit — scroll reveals, carousel, accordion, micro-interactions",
      "category": "ui",
      "description": "Zero-dependency scroll-motion layer (IntersectionObserver + CSS) plus an embla carousel and a radix accordion, packaged so any page gets tasteful entrance animations without pulling in a motion library. Ships Reveal (fade-up/fade/fade-left/fade-right/zoom), Stagger (incremental per-child reveal for grids/lists), CountUp (rAF count-to-value with locale formatting; integers), Marquee (infinite logo/brand strip with hover-pause + edge fade), and the useInView hook behind them; plus Carousel (embla, optional Autoplay plugin) and Accordion (radix). All reveal + keyframe motion is gated behind prefers-reduced-motion. Consumers append globals-motion.css to their app/globals.css for the [data-reveal] transitions + accordion/marquee/blob keyframes. Lifted 2026-06-10 from the _templates fleet `_shared/motion` copy — the 8 standalone website templates already ship a byte-identical copy; this rr slice is the SSOT so future scaffolds get it via `npx rr add motion-kit`. Pairs with landing-sections (its renderers consume these primitives).",
      "source": "rahman-resources (lifted from _templates fleet)",
      "install": "npx rahman-resources add motion-kit",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add motion-kit`. Append the contents of `globals-motion.css` to your `app/globals.css` (after `@import \"tailwindcss\";`) — without it `data-reveal` elements stay static and the accordion snaps. Then import from `@/features/motion-kit`: `<Reveal variant=\"fade-up\">`, `<Stagger itemClassName=\"h-full\">{cards}</Stagger>` for grids, `<CountUp value={4800} />` (integers), `<Marquee speed={32}>{logos}</Marquee>`. Carousel: pair with `Autoplay` from embla-carousel-autoplay. Any component consuming a passed render/icon fn AND these hooks must be `\"use client\"`. Hover-lift convention: `transition-[translate,box-shadow] duration-300 hover:-translate-y-1 hover:shadow-lg`.",
      "tags": [
        "ui",
        "motion",
        "animation",
        "scroll",
        "reveal",
        "carousel",
        "accordion",
        "marquee",
        "countup",
        "embla"
      ]
    },
    {
      "slug": "storefront-checkout",
      "title": "Storefront Checkout — guest cart + checkout composition",
      "category": "content",
      "description": "Guest-friendly shopping cart for catalog storefronts. CartProvider holds items in React context with localStorage persistence (anonymous buyers keep their cart across reloads, zero backend). CartWidget is a header trigger with live count badge opening a slide-over Sheet: per-item qty steppers, remove, subtotal, checkout CTA to a host route. CheckoutSummary renders the order panel on the checkout page. Props-driven R3 — no convex/react anywhere; the host resolves a NUMERIC price per catalog item before add() and MUST re-price every line server-side when placing the order (client subtotal is display-only, never the charge). Proven end-to-end on wirausaha-os: catalog → cart → server-priced placeOrder action → DOKU Direct instructions → webhook flips paid (reactive). Pairs with doku-payment ≥0.2 (guest checkout: optional userId + buyer contact, key-guarded actions, guest-readable status query) or midtrans-payment.",
      "source": "wirausaha-os guest-checkout build-out 2026-06-10",
      "install": "npx rahman-resources add storefront-checkout",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add storefront-checkout`. Wrap your public layout once with `<CartProvider storageKey=\"my-shop-cart\">` and mount `<CartWidget checkoutHref=\"/checkout\" />` in the header extras. On product surfaces call `useCart().add({ slug, name, price, priceLabel, emoji })` with a host-resolved NUMERIC price. Build a /checkout route composing `<CheckoutSummary />` + a payment form (doku-payment's DokuDirectForm): its onSubmit calls YOUR Convex place-order action which re-prices each {slug, qty} from your catalog table server-side, generates an unguessable orderId, calls api.features.payment.actions.doku.createDirectPayment, records your domain order row, and returns { ok, orderId, instructions, expiresAt } ({ ok:false, notice } when DOKU creds are unset — surface it in the form and offer a contact fallback). After success render DokuPaymentInstructions + reactive status via api.features.payment.query.getOrderByOrderId. Reference: template-wirausaha-os convex/checkout.ts + slices/checkout/CheckoutPage.tsx.",
      "tags": [
        "ecommerce",
        "cart",
        "checkout",
        "guest",
        "storefront",
        "payment",
        "localStorage",
        "sheet"
      ]
    },
    {
      "slug": "theme-presets",
      "title": "Theme Presets — unified switcher with bundled tweakcn registry",
      "category": "ui",
      "description": "Single unified theme controller for next-themes apps. ThemePresetSwitcher ships a Palette-icon Popover trigger with three stacked sections: (1) sticky light/dark/system mode tabs, (2) sticky preset-count row with a Default reset button, (3) scrollable color-preset list grouped by mood (Profesional / Bold / Hangat / Artistik / Gelap + Lainnya). Hover-to-preview + click-to-commit + restore-on-close semantics. ThemePresetProvider context wraps state so deeply-nested consumers read via useThemePreset() instead of mounting the switcher directly. ThemeColorSync wrapper enables live tweakcn-CSS-variable preview on routes that need it. Tweakcn registry (~30 curated presets after HIDDEN_PRESETS filter drops Doom 64 / Cyberpunk / Neo Brutalism / Bubblegum / Candyland / Pastel Dreams) ships inside the slice as registry-data.json and loads lazily via dynamic import — code-splits into its own chunk, zero consumer public/ setup, no network roundtrip to a hosted URL. localStorage key `host:theme-preset` (rename via slice fork). CK-1F (2026-05-23) — collapsed prior TweakcnSwitcher + ThemePicker + phantom `theme-preset-switcher` catalog entry into this single component.",
      "source": "CareerPack + notion-page-clone",
      "install": "npx rahman-resources add theme-presets",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add theme-presets` (registry-data.json ships inside the slice — no separate public/ copy step). Wrap your tree once with `<ThemePresetProvider>` (inside next-themes' ThemeProvider). Mount `<ThemePresetSwitcher />` anywhere in your header / sidebar / settings — one component handles light/dark/system + preset palette. Wrap dashboard with `<ThemeColorSync>` if you need live tweakcn variable preview on inner routes. Deeply-nested consumers read state via `useThemePreset()` (returns `{ presetName, registry, setPreset, preview, restore, isReady }`). For lower-level access: `applyTweakcnPreset(name)`, `previewTweakcnPreset(name)`, `restoreTweakcnPreset()`, `groupTweakcnPresets(items)`, `tweakcnSwatches(preset)` all exported from `@/features/theme-presets`. To rename localStorage key, fork `STORAGE_KEY` in `lib/tweakcn/types.ts`.",
      "tags": [
        "ui",
        "theme",
        "tweakcn",
        "color",
        "preset",
        "switcher",
        "popover",
        "next-themes",
        "notion-like"
      ]
    },
    {
      "slug": "site-setup-wizard",
      "title": "Site Setup Wizard — first-run site setup",
      "category": "ui",
      "description": "Post-claim onboarding wizard for clone-to-own templates, graduated from the headless template surface (2026-06-06). Multi-step card flow (Identitas / Branding / Konten / Selesai) that stores ALL site config in the host backend via a props-driven save callback — a non-coder configures their site with zero code. Branding step ships a readable shadcn Select theme-preset picker (color swatches per preset + grouped headers + live preview callback — replaces the white-on-white native select), brand color quick-chips, light/dark/system default mode, logo/favicon upload via injected ImageField, and optional Analytics ID. Identity step hints invalid email format. 'Lewati setup' marks onboarded without fields and reverts any browsed-but-unsaved preset. Props-driven (R3): no convex/react import — host wires settings.upsert / seed.seedSample / setup.status into props; pairs naturally with the theme-presets slice (registry + tweakcnSwatches + previewTweakcnPreset) but works with any theme system or none.",
      "source": "personal-brand-os",
      "install": "npx rahman-resources add site-setup-wizard",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add site-setup-wizard`. Show from your admin gate when `setup.status().onboarded === false`: `<OnboardingWizard onDone={...} save={(f) => settingsUpsert(f)} seedSample={() => seedSample({})} seeded={status?.seeded} ImageField={ImageField} presetOptions={presets} onPresetPreview={(n) => preview(n)} />`. `save` receives Partial<OnboardingFields> + `markOnboarded: true` — back it with a `settings.upsert` mutation that patches only provided fields. Theme bridge (optional): with the theme-presets slice installed build `presetOptions` from `groupTweakcnPresets(registry.items)` + `tweakcnSwatches(p)` and pass `useThemePreset().preview` as `onPresetPreview` — the picker then live-previews while the user browses and `Lewati setup` reverts via `onPresetPreview(null)`. Omit `presetOptions` to hide the picker entirely; omit `ImageField` to hide logo/favicon upload. Full wiring recipe in the slice's HOST-SETUP.md.",
      "tags": [
        "ui",
        "onboarding",
        "wizard",
        "setup",
        "first-run",
        "branding",
        "theme",
        "clone-to-own",
        "templates"
      ]
    },
    {
      "slug": "file-upload",
      "title": "File Upload — pluggable upload + URL resolver with storage-adapter contract",
      "category": "data",
      "description": "Host-pluggable file upload + URL resolution. Ships <FileUploadButton>, <FileChip>, useFileUpload(), useFileUrl() — all reading from a FilesAdapter the host wires via <FilesAdapterProvider>. Bundled localStorage demo adapter stores blobs as data URLs (small files only). Drop in your own adapter for Convex / S3 / GCS / R2. The slice itself has zero backend coupling, proving the storage-adapter pattern for the rest of the open-silong blocked-pending-adapter wave (cover, workspace-io, templates, …).",
      "source": "notion-page-clone",
      "install": "npx rahman-resources add file-upload",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add file-upload`. Wrap your tree with `<FilesAdapterProvider adapter={...}>` — pass `useLocalStorageFilesAdapter()` for a quick demo or implement `FilesAdapter` (upload + remove + useUrl) against your backend. Then drop `<FileUploadButton onUploaded={...}>` anywhere; pair with `<FileChip fileRef={...}>` for rendered chips. Hooks: `useFileUpload()` returns `{upload, uploading, progress, removeFromStorage}`; `useFileUrl(storageId)` resolves to a fetchable URL (Convex adapter uses useQuery for live invalidation; demo reads localStorage synchronously). To wire S3: implement the FilesAdapter interface with presigned URLs + DELETE; the slice doesn't care which backend you pick.",
      "tags": [
        "data",
        "upload",
        "files",
        "storage",
        "adapter",
        "portable",
        "notion-like"
      ]
    },
    {
      "slug": "selection",
      "title": "Selection — marquee multi-select + bulk actions",
      "category": "ui",
      "description": "Framework-agnostic multi-selection for any vertical list (Notion-style blocks, table rows, cards). Hold-and-drag on empty space draws a rubber-band rectangle — AutoCAD-style: drag RIGHT selects only fully-enclosed items (solid ring), drag LEFT selects anything the rectangle touches (dashed green ring). Click an item's edge to select (Shift = range, Cmd/Ctrl = toggle). Selecting activates items with a ring + data-block-selected attribute. Backspace/Delete bulk-deletes, Escape and click-outside clear, and a floating count toolbar offers Delete/Clear. SelectionProvider owns only the id set — the host owns the data via onBulkDelete(ids). Pairs with notion-shell (the notion-clone template wires it onto the editor); lifted from notion-page-clone's block-selection slice.",
      "source": "notion-page-clone",
      "install": "npx rahman-resources add selection",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add selection`. Zero deps (react-dom only). Wrap your list area in `<SelectionProvider onBulkDelete={(ids) => removeMany(ids)}>`, give the surface a `position: relative` div with a ref, drop `<SelectionMarquee containerRef={ref} />` inside it, and wrap each item in `<SelectableBlock id={item.id} orderedIds={allIds}>…</SelectableBlock>`. Hold-drag on empty space to rubber-band: drag RIGHT = window (only fully-enclosed, solid ring), drag LEFT = crossing (anything touched, dashed green). Edge-click an item to pick it (Shift = range, Cmd/Ctrl = toggle). Backspace/Delete bulk-deletes (focus outside a contentEditable), Escape + click-outside clear, floating `N selected · Delete · Clear` toolbar. Read state anywhere via `useSelection()`. The slice owns ONLY the id set — you own the data + the delete. Works on table rows / cards too, not just notion blocks.",
      "tags": [
        "ui",
        "selection",
        "marquee",
        "rubber-band",
        "multi-select",
        "bulk",
        "notion",
        "blocks",
        "list"
      ]
    },
    {
      "slug": "notion-ui",
      "title": "Notion UI — page editor · database · sidebar primitives",
      "category": "ui",
      "description": "The pure, props-driven Notion-clone primitives suite behind one slug, over one shared domain-type model (Block / Page / Property / Database / DbView …). page: the page + block editor (NotionPage / NotionHeader / NotionBlock, SlashMenu, block renderers, inline-markdown decorator, built-in code (highlight.js) + equation (KaTeX)). database: a drop-in 11-view database (table/board/list/gallery/calendar/feed/chart/dashboard/form/map/timeline, 18 property/cell types, per-type column config, filter/sort/group/calculate, row peek + multi-select, cell drag-fill, formula engine, CSV/JSON import-export). sidebar: a standalone tree-nav sidebar (dnd reorder + reparent with depth projection, inline rename, per-row icon picker). All stateless + callback-CRUD — the host owns the data. Install one surface with `npx rr add notion-ui page|database|sidebar`, or all with `npx rr add notion-ui`; the shared/ domain type model is copied for every variant. NOT the full Notion app — that's the separate `notion` slice (adapter + Convex backed).",
      "source": "notion-page-clone",
      "install": "npx rahman-resources add notion-ui",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "**Controlled component.** `<NotionDatabase />` renders the whole surface — 11 views (table, board, list, gallery, calendar, feed, chart, dashboard, form, map, timeline), 18 cell types, filter / sort / group / calculate, row peek + multi-select, table cell drag-fill, CSV / JSON import-export. It is 100% props-driven: it owns NO data state — you hold `db` + `rows` and persist every change callback. The view tab strip scrolls horizontally and the card clips to its border, so it stays inside any container width.\n\n**1. Install** — `npx rr add notion-ui database`. Cascades the `notion-shell` peer (the domain types live there). Components import from `@/features/notion-ui`; types from `@/features/notion-ui`.\n\n**2. Minimal wire-up** — keep `db: Database` + `rows: Page[]` in your store (a Convex query result or `useState`) and pass change handlers:\n```tsx\nimport { NotionDatabase } from '@/features/notion-ui';\n\n<NotionDatabase\n  db={db}\n  rows={rows}\n  onRowAdd={addRow}\n  onRowUpdate={(rowId, propId, value) => setValue(rowId, propId, value)}\n  onRowRemove={removeRow}\n  onPropertyAdd={addProperty}\n  onViewActivate={setActiveView}\n  onViewAdd={addView}\n  onViewConfigChange={(viewId, patch) => patchView(viewId, patch)}\n/>\n```\nOmit any callback and that affordance goes read-only; pass `readOnly` to freeze everything at once.\n\n**3. Data shape** — `Database = { id, name, properties: Property[], views: DatabaseViewConfig[], activeViewId }`; each row `Page = { id, title, rowProps: Record<propId, PropertyValue> }`. For `relation` / `rollup` cells also pass `pages` + `databases`; for `person` / `created_by` cells pass `userLookup(id)`.\n\n**4. Import / export** — mount `<DatabaseIOActions db={db} rows={rows} onImport={handleImport} />` in your toolbar: CSV/JSON in (with schema-diff), CSV/JSON + live-schema templates out. New columns arrive with a `tempId` — map it to your real backend id before writing their `rowProps`.\n\n**5. Backend (optional)** — the UI is store-agnostic. For Convex persistence copy `template-base/database-silong/convex/` (handlers → `convex/`, schema fragment merges into `convex/schema.ts`). Pick `_shared/minimal/` (single-user, noop authz) or `_shared/full/` (`@convex-dev/auth` + workspaces). See CONVEX-BACKEND.md.\n\n**Just one view?** Import it directly — `import { TableView } from '@/features/notion-ui'` — and feed it `rows` + `renderCell` + `renderColumnHeader`.",
      "tags": [
        "ui",
        "notion",
        "notion-like",
        "database",
        "table",
        "board",
        "list",
        "gallery",
        "calendar",
        "feed",
        "chart",
        "dashboard",
        "form",
        "map",
        "timeline",
        "gantt",
        "kanban",
        "views",
        "filter",
        "sort",
        "property",
        "files",
        "person",
        "formula",
        "timestamp",
        "unique-id",
        "csv",
        "json",
        "import",
        "export",
        "template",
        "data",
        "backup",
        "primitive",
        "optional",
        "embeddable"
      ]
    },
    {
      "slug": "image-picker",
      "title": "Image Picker — one-button image/wallpaper chooser (gallery · upload · link · Unsplash · reposition)",
      "category": "ui",
      "description": "Generic image/wallpaper picker — not coupled to Notion. The headline API is ONE button (ImagePickerButton) that opens a dialog with 4 tabs: Gallery (12 colours + 8 gradients + Notion textures), Upload (drag/click, ≤8MB), Link (paste any https image URL), Unsplash (bundled curated landscapes + live search). On pick, onChange fires with an ImageValue ({ type, value, positionY?, metadata? }). ImageBanner is the optional reposition-able band — render an ImageValue as a full-width cover / profile header / card hero with hover controls: Change (opens the dialog), Reposition (drag the vertical focal point), Remove. The slice imports NO other slice and NO backend — the upload backend and Unsplash search are INJECTED as props (onUpload + searchUnsplash), so it drops into any app: wire onUpload to the `files` slice and searchUnsplash to a server route via unsplashSearchVia('/api/unsplash') that holds UNSPLASH_ACCESS_KEY server-side (never NEXT_PUBLIC). Ships a curated Unsplash fallback + gallery so it works with zero config. parseImage normalizes legacy raw-string values; imageStyle builds the focal-point CSS. Wired into the notion-page-clone template as the page cover via NotionPage's coverSlot.",
      "source": "notion-page-clone",
      "install": "npx rahman-resources add image-picker",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add image-picker`. The headline component is `<ImagePickerButton label=\"Change image\" onChange={(img)=>save(img)} onUpload={…} searchUnsplash={…} />` — ONE button that opens the 4-tab dialog (gallery / upload / link / Unsplash). For a reposition-able cover/hero band use `<ImageBanner image={value} onChange={save} resolvedUrl={…} onUpload={…} searchUnsplash={…} />` (also passable to notion-shell's `<NotionPage coverSlot={…} />`). Inject the backend: `onUpload` = the `files` slice's useFileUpload().upload (returns a FileRef); resolve upload images for display with `resolvedUrl` = files useFileUrl(parseFileRef(imageRef(parseImage(value))).storageId). `searchUnsplash` = `unsplashSearchVia('/api/unsplash')` — add a server route that proxies api.unsplash.com with UNSPLASH_ACCESS_KEY (never expose the key client-side). Ships a curated Unsplash + gallery fallback so it works with zero wiring. ImageValue = { type, value, positionY?, metadata? }; parseImage handles legacy string values.",
      "tags": [
        "ui",
        "image",
        "picker",
        "wallpaper",
        "cover",
        "upload",
        "unsplash",
        "gallery",
        "reposition",
        "files",
        "primitive",
        "portable",
        "dialog"
      ]
    },
    {
      "slug": "workspace-shell",
      "title": "Workspace Shell — atomic (workspace × menuSet) NavContext",
      "category": "ui",
      "description": "Unified workspace + menu navigation primitive. NavContext = (workspaceId, menuSetId) atomic pair. 2-tier dropdown switcher (workspace radio + menuSet picker), ContextBadge header chip, full editor with tabs (menus / workspace tree / settings), tiered RBAC (admin menus.manage, user menus.fork). Replaces silo'd menu-store + workspace-store slices in superspace. Resolver chain: user nav-context cache > user assignment > workspace default > system. Source: superspace.",
      "source": "superspace",
      "docsUrl": "",
      "install": "",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add workspace-shell`. Tables prefixed `workspaceShell_*` (menuSets, menuItems, itemComponents, wsAssignments, userAssignments, rolePerms, navContext). Mount `<NavContextProvider workspaceId={wsId}>` inside your auth provider; use `useNavContext(wsId)` to read `{workspace, menuSet, source, effectiveMenuItems, setMenuSet, forkMenuSet}`. Drop-in `<WorkspaceSwitcher canFork />` in sidebar header. Tiered RBAC: `menus.manage` for workspace-default editing, `menus.fork` for user-personal copy. Resolver chain: user cache → user assignment → workspace default → none. Pair with audit-log slice for context-switch / fork events (graceful try/catch if absent). Effective items query applies role filter via workspaceShell_rolePerms (no rolePerms → show all, pre-RBAC compat).",
      "tags": [
        "ui",
        "navigation",
        "workspace",
        "menu",
        "shell",
        "convex",
        "rbac"
      ]
    },
    {
      "slug": "library",
      "title": "Library — resource hub (prompts · visuals · snippets · links)",
      "category": "data",
      "description": "Grab-bag resource hub. One polymorphic `libraryItems` table holds six kinds — prompt, image, video, link, download, snippet — with per-kind payload fields switched on `kind` (no joins). Attribution-first: every item carries optional source/license/tools so re-shares stay correct. Collections group items. Convex-backed (schema + queries + unauthenticated mutations); SEO override fields reused from the `seo` peer slice so the surface matches blog/projects rows. Public view = filterable card grid + per-item detail with copy-to-clipboard for prompts/snippets and an opt-in upvote control. Lifted 2026-05-28 from rahmanef.com; 432-LOC mutations + 330-LOC detail split for the 200-LOC cap; Indonesian copy + custom primitives stripped (prop-driven English defaults); cross-slice auth + comments-votes coupling dropped (consumer wraps mutations + supplies the upvote handler).",
      "source": "rahmanef.com",
      "install": "npx rahman-resources add library",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add seo` (peer) then `npx rr add library`. Spread `seoTables` + `libraryTables` into your root Convex schema. Wrap the unauthenticated CRUD `internalMutation`s with your auth model (see README Install). Render `<LibraryIndex items={await fetchQuery(api.library.listPublic)} />` and `<LibraryDetail item={await fetchQuery(api.library.getBySlug, { slug })} />`. Pass `onUpvote` to enable voting (consumer-owned backend); override `copy` + `kindLabels` per consumer.",
      "tags": [
        "library",
        "resources",
        "prompts",
        "snippets",
        "moodboard",
        "downloads",
        "attribution",
        "seo",
        "personal-brand"
      ]
    },
    {
      "slug": "data-table",
      "title": "Data Table — TanStack + shadcn",
      "category": "data",
      "description": "Generic DataTable<TData> on TanStack Table v8 + shadcn Table. Sorting (3-state column headers), toolbar search bound to any column, pagination, checkbox row selection with count footer, column-visibility dropdown. density compact|comfortable + selectable on|off variant axes. Pure UI — consumer supplies columns + data.",
      "source": "rr original (shadcn data-table pattern)",
      "docsUrl": "https://tanstack.com/table/v8",
      "install": "npx rahman-resources add data-table",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add data-table`. Build ColumnDef<TData>[] (use sortable headers via DataTableColumnHeader), pass data + columns to <DataTable>. searchKey binds the toolbar input to one column; selectable prepends the checkbox column; density tightens row padding.",
      "tags": [
        "table",
        "data-table",
        "datagrid",
        "sorting",
        "filtering",
        "pagination",
        "selection",
        "basics"
      ]
    },
    {
      "slug": "pages-cms",
      "title": "Pages CMS — block-composed multi-page editor",
      "category": "content",
      "description": "A small multi-page CMS. PagesView (list + CRUD: create/edit/duplicate/delete/publish) + PageEditorView (metadata form + block editor) + a read-only public BlockRenderer. Pages are composed of 11 block kinds: hero, text, feature-list, cta, logo-cloud, testimonial, video, image-gallery, faq, stats, pricing-table. Ships a localStorage adapter (LocalPagesProvider) + a generic Home/About/Pricing seed so it runs env-free — or wire the bundled pagesReducer + PagesProvider to your own backend (optional Convex copy-source included). Pure UI; no Convex required.",
      "source": "rr original (generalized from saas-marketing pages engine)",
      "install": "npx rahman-resources add pages-cms",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add pages-cms`. Wrap your admin surface in <LocalPagesProvider seed={defaultPages()}> (localStorage, zero backend) or supply your own PagesStore via <PagesProvider>. Render <PagesView publicBase adminBase> for the list and <PageEditorView id publicBase adminBase> for the editor route. Public catch-all looks up the page by slug and renders <BlocksRenderer blocks={page.blocks} />. Add block kinds by extending the PageBlock union + emptyBlock + the renderer/editor switches.",
      "tags": [
        "content",
        "cms",
        "pages",
        "blocks",
        "editor",
        "builder",
        "basics"
      ]
    },
    {
      "slug": "feedback-states",
      "title": "Feedback States — loading skeletons + empty/error states",
      "category": "ui",
      "description": "Two co-located placeholder surfaces behind one slug. loading: a configurable LoadingSkeleton over the shadcn Skeleton (kind presets text / card / list / table / form / page / block, overridable count + columns) plus a spinner LoadingState (inline / block / overlay) for in-flight work. empty: a configurable EmptyState over the shadcn Empty (404 / 500 / 403 / no-results / empty-list / first-use, overridable icon/title/copy/actions) plus an ErrorPage full-page wrapper for app/not-found.tsx and app/error.tsx. Install one surface with `npx rr add feedback-states loading|empty`, or both with `npx rr add feedback-states`. Replaces ad-hoc animate-pulse divs, hand-rolled Loader2 spans, and one-off error pages.",
      "source": "rr original",
      "install": "npx rahman-resources add feedback-states",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add feedback-states` for both, or `npx rr add feedback-states loading` / `empty` for one surface. loading: <LoadingSkeleton kind=\"table\" count={8} /> mirrors streamed content, kind=\"page\" drops into route loading.tsx, <LoadingState variant=\"inline|block|overlay\" /> for in-flight work. empty: <EmptyState kind=\"no-results\" /> in zero-data spots, <ErrorPage kind=\"404\" /> in app/not-found.tsx and kind=\"500\" in app/error.tsx. Every preset overridable per use.",
      "tags": [
        "loading",
        "skeleton",
        "spinner",
        "empty-state",
        "404",
        "500",
        "403",
        "error-page",
        "fallback",
        "placeholder",
        "basics"
      ]
    },
    {
      "slug": "marketing-chrome",
      "title": "Marketing Chrome — Header + Footer",
      "category": "ui",
      "description": "MarketingHeader (split | centered | minimal layouts, sticky option, mobile sheet menu) + MarketingFooter (columns | slim layouts, link columns, social icons, legal bar). Brand / nav / CTA / columns all props — no hardcoded content. Lucide stand-ins for brand glyphs; swap a brand icon set post-copy (README).",
      "source": "rr original (extracted from template duplication)",
      "install": "npx rahman-resources add marketing-chrome",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add marketing-chrome`. Feed MarketingHeader { brand, nav[], cta, layout } and MarketingFooter { brand, columns[], social[], legal[], layout }. Header layout split is the default marketing pattern; footer columns for full sites, slim for single-pagers.",
      "tags": [
        "header",
        "footer",
        "navbar",
        "marketing",
        "navigation",
        "chrome",
        "basics"
      ]
    },
    {
      "slug": "settings",
      "title": "Settings — account + appearance shells",
      "category": "ui",
      "description": "Two settings surfaces behind one slug, each adapter-driven so the slice owns no data. account: SettingsShell two-column surface (nav collapses to a Select on mobile) — Profile (avatar/name/email/bio), Preferences (theme/language/density), Notifications (switch rows), Danger zone (AlertDialog-confirmed delete) over an ASYNC SettingsAdapter { load, save(patch) } with optimistic save + rollback; createMemoryAdapter ships for demos. appearance: AppearancePanel (style/mode/accent/wallpaper/reduce-transparency/display) over a SYNC per-setting AppearanceAdapter, plus the generic SettingsSection / SettingsRow / Segmented / AccentSwatches primitives you compose custom panels from. Install one surface with `npx rr add settings account|appearance`, or both with `npx rr add settings`.",
      "source": "rr original",
      "install": "npx rahman-resources add settings",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add settings` for both, or `npx rr add settings account` / `appearance` for one. account: implement SettingsAdapter { load, save } over your backend (Convex query + mutation), pass to <SettingsShell adapter>; save gets per-section partial patches (shallow-merge server-side); onDeleteAccount wires the danger zone. appearance: build an AppearanceAdapter (per-setting SegSetting values) from your appearance store, pass to <AppearancePanel appearance>; or compose custom panels from <SettingsSection>/<SettingsRow>/<Segmented>/<AccentSwatches>.",
      "tags": [
        "settings",
        "preferences",
        "account",
        "appearance",
        "theme",
        "adapter",
        "shell",
        "primitives",
        "ui",
        "basics"
      ]
    },
    {
      "slug": "notifications-center",
      "title": "Notifications Center — bell + inbox",
      "category": "ui",
      "description": "NotificationBell (ghost icon button, unread badge, popover or sheet surface) + NotificationList (All/Unread tabs, mark-all-read, clear, ScrollArea rows with kind icon, relative time, hover actions). NotificationsAdapter contract (list/markRead/markAllRead/dismiss/clear) with a useSyncExternalStore-friendly memory adapter included — swap in Convex for production (sketch in README).",
      "source": "rr original (appshell toast-log pattern, standalone)",
      "install": "npx rahman-resources add notifications-center",
      "npmPackages": [],
      "exampleCode": "",
      "agentRecipe": "Run `npx rr add notifications-center`. Mount <NotificationBell adapter> in your topbar. Implement NotificationsAdapter over your feed (Convex query + mutations) or start with createMemoryNotificationsAdapter(seed). surface=\"sheet\" for mobile-heavy apps.",
      "tags": [
        "notifications",
        "inbox",
        "bell",
        "unread",
        "toast",
        "basics"
      ]
    },
    {
      "slug": "design-studio",
      "title": "Design Studio — photo / social design canvas",
      "category": "os",
      "description": "A layered canvas studio: image/text/shape layers with filters, masks, transforms, safe-area guides and aspect presets (1:1/4:5/9:16/16:9), plus an export modal (download / copy / import JSON). Runs fully offline on bundled gradient-SVG samples. Host wiring is one call: configureMediaStudio({ saveDoc, imageSources }) lights up Save-to-host and feeds real image sources. Self-contained: inspector hooks are inert seams in lib/host.ts.",
      "source": "rahmanef63/os-vps",
      "install": "npx rahman-resources add design-studio",
      "npmPackages": [],
      "exampleCode": "\"use client\";\nimport { MediaStudio } from \"@/features/design-studio\";\n\nexport default function StudioDemo() {\n  return <div className=\"h-dvh w-full\"><MediaStudio /></div>;\n}",
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. Layered canvas editor. Fully client-side; no backend required.\n\nSTEP 1 — Install. `npx rr add design-studio`. Ensure `@/features/design-studio` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: button, dialog, badge, tooltip, scroll-area.\n\nSTEP 3 — Mount. `<MediaStudio />` in a height-bearing box — unwired it edits bundled sample layers. Or register `mediaStudioApp` in an appshell manifest.\n\nSTEP 4 — Host wiring. `configureMediaStudio({ saveDoc, imageSources })` — saveDoc persists the serialized document (enables Save-to-host in the export modal); imageSources supplies image URLs for new layers.",
      "tags": [
        "canvas",
        "editor",
        "layers",
        "filters",
        "export",
        "design",
        "ui"
      ]
    },
    {
      "slug": "quicklinks",
      "title": "Quicklinks — website shortcuts with favicons",
      "category": "os",
      "description": "A website-shortcut grid: add/remove links with auto favicons (Google s2) and new-tab open. State lives behind an injectable QuicklinksStore — createLocalStore persists to localStorage (SSR-safe hydrate), createMemoryStore suits previews/tests, configureQuicklinks swaps in a host store. Pairs with appshell: the useQuickLinks capability + QuicklinkIcon surface the same links in the dock/Launchpad/mobile grid.",
      "source": "rahmanef63/os-vps",
      "install": "npx rahman-resources add quicklinks",
      "npmPackages": [],
      "exampleCode": "\"use client\";\nimport { Quicklinks } from \"@/features/quicklinks\";\n\nexport default function LinksDemo() {\n  return <div className=\"h-dvh w-full\"><Quicklinks /></div>;\n}",
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. Website shortcut grid. Fully client-side; no backend required.\n\nSTEP 1 — Install. `npx rr add quicklinks`. Ensure `@/features/quicklinks` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: button.\n\nSTEP 3 — Mount. `<Quicklinks />` — unwired it persists to localStorage (\"rr:quicklinks\") with 4 demo seeds. Or register `quicklinksApp` in an appshell manifest.\n\nSTEP 4 — Host store. `configureQuicklinks(store)` with { get, subscribe, add, remove, hydrate? } — or feed appshell's useQuickLinks capability from the same store so dock shortcuts stay in sync.",
      "tags": [
        "shortcuts",
        "bookmarks",
        "favicons",
        "launcher",
        "ui"
      ]
    }
  ],
  "slices": [
    {
      "slug": "image-editor",
      "title": "Image Editor — layered raster editor",
      "category": "os",
      "kind": "ui",
      "version": "2.1.1",
      "description": "A Photoshop-style raster image editor built on Konva. Layers panel (reorder, opacity, visibility, lock, 16 blend modes), free transform (move/scale/rotate/flip via a Transformer), image + text + shape + paint layers, brush & eraser with size/opacity/hardness, non-destructive adjustments + filters, canvas resize/aspect presets, and LAYER STYLES: stroke, drop shadow, outer glow, clipping mask. One-click BACKGROUND REMOVAL runs fully in-browser via @imgly/background-removal (free, no API key — downloads a small ONNX model on first use). Undo/redo, zoom/pan, shortcuts, PNG/JPG/WebP export. v2 adds an AI FUNCTION-CALLING layer: every editor operation is a named, schema'd command (EDITOR_COMMANDS registry + useEditorCommands binding) driven by an in-editor chat; the streaming bridge is injectable via configureAgentStream(fn) and everything except the chat works without it. A headless server barrel (server.ts) runs commands against documents with no DOM. Image I/O via props (initialImage / onSave).",
      "source": "rahmanef63/os-vps",
      "slicePath": "frontend/slices/image-editor",
      "convexPaths": [],
      "npm": [
        "lucide-react",
        "konva",
        "react-konva",
        "@imgly/background-removal",
        "class-variance-authority",
        "radix-ui"
      ],
      "shadcn": [
        "button",
        "input",
        "label",
        "separator",
        "select",
        "scroll-area",
        "switch",
        "dropdown-menu",
        "tooltip",
        "resizable",
        "popover"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "image-editor",
        "photoshop",
        "canvas",
        "konva",
        "layers",
        "filters",
        "background-removal",
        "paint",
        "ai",
        "ui"
      ],
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui + Konva. A layered raster image editor. Image I/O is via props; background removal runs in-browser (no backend).\n\nSTEP 1 — Install. `npx rr add image-editor`. Ensure `@/features/image-editor` resolves in tsconfig paths and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `konva react-konva @imgly/background-removal lucide-react`. shadcn: `npx shadcn@latest add button input slider select tabs scroll-area separator tooltip label switch popover`.\n\nSTEP 3 — Mount. It is fully self-contained; the Konva stage is loaded client-only (next/dynamic ssr:false) inside the slice, so just render it in a height-bearing box:\n```tsx\n\"use client\";\nimport { ImageEditor } from \"@/features/image-editor\";\nexport default function Page() {\n  return (\n    <div className=\"h-dvh\">\n      <ImageEditor onSave={(dataUrl) => console.log(dataUrl)} />\n    </div>\n  );\n}\n```\nProps: `initialImage?` (data/object/remote URL opened on mount), `width?`/`height?` (blank canvas size, default 1080²), `onSave?(dataUrl)` (fires from the Save button with a PNG data URL; omit to hide Save), `className?`.\n\nSTEP 4 — Background removal. The \"Remove BG\" button calls removeImageBackground() from @imgly/background-removal — free, in-browser, no key. First run downloads a small model to the browser cache, then runs locally via WASM. You can also import `removeImageBackground(src) => Promise<pngDataUrl>` directly.\n\nSTEP 5 — Export. PNG/JPG/WebP at 1×/2×/3× via the Export tab, or call `exportStage(stage, {...})` / `stageToDataURL(stage, {...})`. The container owns the box — render inside h-dvh / h-full."
    },
    {
      "slug": "reel-editor",
      "title": "Reel — video timeline editor",
      "category": "os",
      "kind": "ui",
      "version": "1.2.1",
      "description": "A complete in-browser video editor. Real media clips (image/video/audio) on a layered multi-track timeline — the top row renders frontmost, with ▲▼ reorder and per-track lock/hide/mute. ONE Canvas-2D draw path is shared by the live preview and the realtime MediaRecorder exporter, so what you see is exactly what renders (WebM with real mixed audio: per-clip volume/fades/auto-duck through a streaming audio graph). Per-clip trim/speed (0.25–4×)/reverse, dissolve/wipe/slide transitions via clip overlap, keyframes (opacity/scale/x/y/rotation) with easing + one-click In/Out animation presets, text styling with preset grid, color grading + vignette, filmstrip thumbnails + real waveforms, snapping, split/duplicate. The workspace is config-driven: 6 resizable layout presets (react-resizable-panels v4) incl. quick-import files-pane layouts, plus custom composition size. Drafts auto-save to localStorage. Self-contained: toasts via sonner, the files pane runs on an injectable fs adapter (configureReelFs; in-memory mock by default), and shell hooks (inspector/activity) are inert seams in lib/host.ts.",
      "source": "rahmanef63/os-vps",
      "slicePath": "frontend/slices/reel-editor",
      "convexPaths": [],
      "npm": [
        "lucide-react",
        "react-resizable-panels",
        "sonner"
      ],
      "shadcn": [
        "button",
        "input",
        "slider",
        "tooltip",
        "dialog",
        "dropdown-menu",
        "resizable",
        "sheet",
        "sonner"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "video",
        "video-editor",
        "timeline",
        "nle",
        "keyframes",
        "transitions",
        "webm",
        "canvas",
        "ui"
      ],
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. An in-browser video timeline editor with realtime WebM export. Fully client-side; no backend required.\n\nSTEP 1 — Install. `npx rr add reel-editor`. Ensure `@/features/reel-editor` resolves in tsconfig paths and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react react-resizable-panels sonner`. shadcn: `npx shadcn@latest add button input slider tooltip dialog dropdown-menu resizable sheet sonner`. Mount `<Toaster />` (sonner) once in your root layout.\n\nSTEP 3 — Mount. Render in a height-bearing box:\n```tsx\n\"use client\";\nimport { ReelEditor } from \"@/features/reel-editor\";\nexport default function Page() {\n  return <div className=\"h-dvh\"><ReelEditor /></div>;\n}\n```\nOr register the `reelEditorApp` descriptor in an appshell manifest for windowed hosts.\n\nSTEP 4 — Files pane backend (optional). The quick-import pane ships with an in-memory mock. Wire a real filesystem with `configureReelFs({ list, mkdir, rawUrl })` — list/mkdir mirror a simple fs API, rawUrl resolves a listed path to a fetchable media URL.\n\nSTEP 5 — Export. The Render button records the live canvas + mixed audio to WebM via MediaRecorder in realtime (duration = composition length). Users can also import local media via the file picker — object URLs, no upload needed."
    },
    {
      "slug": "media-viewer",
      "title": "Preview — media quick-look",
      "category": "os",
      "kind": "ui",
      "version": "1.2.1",
      "description": "A quick-look media viewer in the macOS Preview spirit. Images render on a zoomable (40–300%) checkerboard stage so transparency reads; audio gets a card player with a CSS-bar waveform + transport; video gets play/pause + scrubber + volume; PDFs embed full-bleed and text gets a simple surface. The toolbar carries a type-indicator chip, zoom, Download, Open-in-editor, and prev/next. Two integration seams in lib/host.ts make it portable: configureMediaSource maps fs paths to fetchable URLs (identity by default, so public URLs work with zero wiring) and configureMediaOpener routes the Open-in-editor handoff (image → image-editor, video/audio → reel-editor) to your shell — both inert until set. Launched bare it shows a fully offline sample gallery (inline SVG gradients, simulated A/V playback). Pairs with file-explorer (onOpenFile → MediaViewer payload) and the editors.",
      "source": "rahmanef63/os-vps",
      "slicePath": "frontend/slices/media-viewer",
      "convexPaths": [],
      "npm": [
        "lucide-react"
      ],
      "shadcn": [
        "button",
        "badge",
        "separator",
        "tooltip",
        "slider"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "media",
        "preview",
        "viewer",
        "quick-look",
        "image",
        "video",
        "audio",
        "pdf",
        "ui"
      ],
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. A quick-look media viewer (image/video/audio/pdf/text). Fully client-side; no backend required.\n\nSTEP 1 — Install. `npx rr add media-viewer`. Ensure `@/features/media-viewer` resolves in tsconfig paths and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button badge separator tooltip slider`.\n\nSTEP 3 — Mount. `<MediaViewer />` with no payload shows the offline sample gallery. Pass a file to view it:\n```tsx\n\"use client\";\nimport { MediaViewer } from \"@/features/media-viewer\";\nexport default function Page() {\n  return <div className=\"h-dvh\"><MediaViewer payload={{ path: \"/media/clip.mp4\", name: \"clip.mp4\", kind: \"video\" }} /></div>;\n}\n```\nOr register the `mediaViewerApp` descriptor in an appshell manifest for windowed hosts.\n\nSTEP 4 — Remote files (optional). Paths resolve through `configureMediaSource({ rawUrl })` — identity by default, so public/absolute URLs already work. Point rawUrl at your fs endpoint for private files.\n\nSTEP 5 — Editor handoff (optional). `configureMediaOpener((appId, title, size, payload) => …)` routes the \"Open in Image/Video Editor\" actions to your shell (no-op until set). Wire it to openWindow when running inside appshell with image-editor / reel-editor installed."
    },
    {
      "slug": "code-editor",
      "title": "Code — overlay syntax editor",
      "category": "os",
      "kind": "ui",
      "version": "1.2.1",
      "description": "A lightweight code editor in the VS-Code spirit without the weight: a transparent textarea layered over a highlighted pre (regex tokenizer for JS/TS/JSON/CSS) gives real editing with live syntax color and a line-number gutter; a tab strip tracks dirty buffers with Cmd/Ctrl+S save; a status bar shows path, Ln/Col, tab size, language and save state. The explorer is a lazy per-directory tree — each folder lists on expand, with inline new-file/new-folder affordances — rendered as a rail on desktop and a Sheet on mobile, and the new-file form is a responsive dialog ⇄ bottom drawer. The filesystem is INJECTED via a small CodeFsAdapter (list/read/write/mkdir): point configureCodeFs at a real API or use the bundled writable in-memory mock (seeded sample tree) so it works with zero backend. Writes are best-effort — a read-only host flags the save but keeps the local buffer. Pairs with file-explorer (onOpenFile → payload) and appshell.",
      "source": "rahmanef63/os-vps",
      "slicePath": "frontend/slices/code-editor",
      "convexPaths": [],
      "npm": [
        "lucide-react"
      ],
      "shadcn": [
        "button",
        "badge",
        "input",
        "scroll-area",
        "sheet",
        "dialog"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "code",
        "editor",
        "syntax-highlight",
        "ide",
        "tabs",
        "file-tree",
        "ui"
      ],
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. A lightweight overlay-highlighting code editor with a lazy explorer tree. Fully client-side; no backend required.\n\nSTEP 1 — Install. `npx rr add code-editor`. Ensure `@/features/code-editor` resolves in tsconfig paths and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button badge input scroll-area sheet dialog`.\n\nSTEP 3 — Mount. `<CodeEditor />` opens the seeded sample tree (writable in-memory mock). Open a specific file with a payload:\n```tsx\n\"use client\";\nimport { CodeEditor } from \"@/features/code-editor\";\nexport default function Page() {\n  return <div className=\"h-dvh\"><CodeEditor payload={{ path: \"/Projects/hello.ts\" }} /></div>;\n}\n```\nOr register the `codeEditorApp` descriptor in an appshell manifest for windowed hosts.\n\nSTEP 4 — Real filesystem (optional). `configureCodeFs({ list, read, write, mkdir })` — list returns { path, entries: [{ name, kind }] } for ONE directory (the tree fetches per expand), read returns the file body, write/mkdir mutate. Writes are best-effort: on failure the editor keeps the local buffer and flags the status bar.\n\nSTEP 5 — Cross-app open. From a file manager (e.g. the file-explorer slice), wire onOpenFile to re-render CodeEditor with payload={{ path }} — the editor adds a tab and hydrates the buffer."
    },
    {
      "slug": "system-monitor",
      "title": "System Monitor — host telemetry dashboard",
      "category": "os",
      "kind": "ui",
      "version": "1.2.1",
      "description": "An Activity-Monitor-style dashboard: circular CPU/RAM/disk/GPU gauges, rolling CPU + network sparklines on glass panels, and a live process table — polling every 1.5s with a ~40-point history. Telemetry is INJECTED via a small SysMonAdapter (stats/processes): point configureSysmon at a real host API (/proc, an agent, a cloud endpoint) or keep the bundled wavy in-browser mock so the dashboard renders alive with zero backend. Self-contained: shell inspector hooks are inert seams in lib/host.ts.",
      "source": "rahmanef63/os-vps",
      "slicePath": "frontend/slices/system-monitor",
      "convexPaths": [],
      "npm": [
        "lucide-react"
      ],
      "shadcn": [
        "scroll-area"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "monitoring",
        "telemetry",
        "dashboard",
        "gauges",
        "sparkline",
        "processes",
        "ui"
      ],
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. Host telemetry dashboard. Fully client-side; no backend required.\n\nSTEP 1 — Install. `npx rr add system-monitor`. Ensure `@/features/system-monitor` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add scroll-area`.\n\nSTEP 3 — Mount. `<SystemMonitor />` in a height-bearing box — unwired it runs a wavy in-browser telemetry mock. Or register `systemMonitorApp` in an appshell manifest.\n\nSTEP 4 — Real telemetry. `configureSysmon({ mode:\"live\", stats, processes })` — stats returns { cpu:{pct,cores}, mem:{used,total}, disk:{used,total}, net?:{rx,tx}, uptime }; processes returns [{ pid, name, status, cpu, mem }]."
    },
    {
      "slug": "booking",
      "title": "Booking — session request form + owner inbox",
      "category": "os",
      "kind": "ui",
      "version": "1.0.0",
      "description": "One app that is BOTH a public 'book a session' request form AND the owner's triage inbox — it flips to show the inbox when the viewer can manage. Visitors submit name/email/topic (+ optional preferred time / note); the owner sees pending requests with Confirm / Decline. The backend is INJECTED via a small BookingAdapter (submit/list/setStatus/canManage): point configureBooking at your store, or keep the bundled in-memory mock so it renders fully interactive — form + inbox — with zero backend.",
      "source": "rahmanef63/os-vps",
      "slicePath": "frontend/slices/booking",
      "convexPaths": [],
      "npm": [
        "lucide-react"
      ],
      "shadcn": [
        "button",
        "input",
        "textarea",
        "scroll-area"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "booking",
        "contact",
        "form",
        "inbox",
        "lead",
        "scheduling",
        "ui"
      ],
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. A booking request form + owner inbox. Fully client-side; backend optional.\n\nSTEP 1 — Install. `npx rr add booking`. Ensure `@/features/booking` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button input textarea scroll-area`.\n\nSTEP 3 — Mount. `<Booking />` in a height-bearing box — unwired it runs on an in-memory mock store (form + inbox both live). Or register `bookingApp` in an appshell manifest.\n\nSTEP 4 — Real backend. `configureBooking({ mode:\"live\", submit, list, setStatus, canManage })` — submit takes { name, email, topic, preferredTime?, note? }; list returns rows with { id, status, createdAt }; omit list/canManage for a write-only public form."
    },
    {
      "slug": "html-studio",
      "title": "HTML Studio — sandboxed HTML/CSS/JS editor with live preview",
      "category": "os",
      "kind": "ui",
      "version": "1.0.0",
      "description": "A tiny web-page studio: write HTML / CSS / JS and see it render LIVE in a sandboxed iframe (srcdoc + sandbox=allow-scripts WITHOUT allow-same-origin, so user code runs in an opaque origin and cannot read the host) — then Save to a shareable /p/<slug>. Code / Split / Preview view toggle, a device-width preview (responsive / tablet / phone), a saved-pages rail, and public/private visibility. The backend is INJECTED via a small HtmlStudioAdapter (save/load/list/remove): point configureHtmlStudio at your store, or keep the bundled in-memory mock so the editor + live preview + saved list are fully interactive with zero backend.",
      "source": "rahmanef63/os-vps",
      "slicePath": "frontend/slices/html-studio",
      "convexPaths": [],
      "npm": [
        "lucide-react"
      ],
      "shadcn": [
        "button",
        "input",
        "textarea",
        "scroll-area"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "html",
        "editor",
        "sandbox",
        "iframe",
        "preview",
        "playground",
        "code",
        "ui"
      ],
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. A sandboxed HTML/CSS/JS studio: editor + live iframe preview + saved pages. Fully client-side; backend optional.\n\nSTEP 1 — Install. `npx rr add html-studio`. Ensure `@/features/html-studio` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button input textarea scroll-area`.\n\nSTEP 3 — Mount. `<HtmlStudio />` in a height-bearing box — unwired it runs on an in-memory mock (editor + live sandboxed preview + saved list all live). Pass `payload={{ slug }}` to open a page, or register `htmlStudioApp` in an appshell manifest.\n\nSTEP 4 — Real backend. `configureHtmlStudio({ mode:\"live\", save, load, list, remove })` — save takes { slug?, title, html, visibility } and returns { slug }; load(slug) -> SavedPage | null; omit save for a read-only sandbox or list to hide the saved rail. KEEP the iframe sandbox without allow-same-origin — it is the security boundary."
    },
    {
      "slug": "resources-launcher-admin",
      "title": "Resources Admin — curated icon-launcher CRUD",
      "category": "os",
      "kind": "ui",
      "version": "1.0.0",
      "description": "An owner-gated admin app for a curated icon-launcher: add / edit / remove / reorder links (label, lucide icon NAME, url, group, order) that open in a new tab. The backend is INJECTED via a small ResourcesAdapter (list/upsert/remove/canManage): point configureResources at your store, or keep the bundled in-memory mock so the whole CRUD — including reorder — is interactive with zero backend. Icons are stored as lucide NAME strings and resolved client-side, so the same data drives a public launcher surface.",
      "source": "rahmanef63/os-vps",
      "slicePath": "frontend/slices/resources-launcher-admin",
      "convexPaths": [],
      "npm": [
        "lucide-react"
      ],
      "shadcn": [
        "button",
        "input",
        "label",
        "scroll-area",
        "native-select"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "launcher",
        "links",
        "bookmarks",
        "admin",
        "crud",
        "icons",
        "ui"
      ],
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. A curated icon-launcher admin (CRUD + reorder). Fully client-side; backend optional.\n\nSTEP 1 — Install. `npx rr add resources-launcher-admin`. Ensure `@/features/resources-launcher-admin` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button input label scroll-area native-select`.\n\nSTEP 3 — Mount. `<ResourcesAdmin />` in a height-bearing box — unwired it runs on an in-memory mock store (add / edit / remove / reorder all live). Or register `resourcesAdminApp` in an appshell manifest.\n\nSTEP 4 — Real backend. `configureResources({ mode:\"live\", list, upsert, remove, canManage })` — list returns rows { id, label, icon, url, group, order }; upsert takes the same minus id to insert (pass id to patch); canManage gates the editor + reorder. Icons are lucide NAME strings resolved via resolveIcon."
    },
    {
      "slug": "profile",
      "title": "Profile — CV + identity card",
      "category": "os",
      "kind": "ui",
      "version": "1.0.0",
      "description": "One owner's identity in two co-located variants, behind one slug. resume: a clean one-column résumé / CV — name, roles, location, contacts, summary, skills, experience (role · org · period + bullets), projects — rendered by <Resume /> off a configureResume() seam, with a Print / PDF button. card: an \"About This Mac\"-style identity card — avatar / monogram, name, roles, outbound links, FAQ accordion — rendered by <AboutProfile /> off a configureAbout() seam. Both render a populated placeholder unwired (zero backend). Install one surface with `npx rr add profile resume|card`, or both with `npx rr add profile`.",
      "source": "rahmanef63/os-vps",
      "slicePath": "frontend/slices/profile",
      "convexPaths": [],
      "npm": [
        "lucide-react"
      ],
      "shadcn": [
        "button",
        "scroll-area",
        "avatar"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "resume",
        "cv",
        "profile",
        "portfolio",
        "about",
        "identity",
        "bio",
        "card",
        "links",
        "faq",
        "print",
        "ui"
      ],
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. Two identity renderers driven by injected data. Fully client-side; no backend required.\n\nSTEP 1 — Install. `npx rr add profile` for both, or `npx rr add profile resume` / `card` for one. Ensure `@/features/profile` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button scroll-area avatar`.\n\nSTEP 3 — Mount. `<Resume />` (CV) or `<AboutProfile />` (card) in a height-bearing box — unwired each renders a generic placeholder. Or register `resumeApp` / `aboutProfileApp` in an appshell manifest.\n\nSTEP 4 — Real data. `configureResume(profile)` with a ResumeProfile { name, roles[], location, summary, contacts[], skills[], experience[], projects[] }, and/or `configureAbout(card)` with { name, roles[], description, links[], faq[] }, once at boot from Convex / a CMS / a JSON file. Resume's \"Print / PDF\" button calls window.print() against a print-friendly layout.",
      "variants": {
        "default": "resume",
        "items": [
          {
            "id": "resume",
            "title": "Resume",
            "description": "Formal one-column printable CV (Resume + configureResume)."
          },
          {
            "id": "card",
            "title": "Card",
            "description": "Compact avatar + links + FAQ identity card (AboutProfile + configureAbout)."
          }
        ]
      }
    },
    {
      "slug": "start-here",
      "title": "Start Here — guided OS onboarding tour",
      "category": "os",
      "kind": "ui",
      "version": "1.0.0",
      "description": "A guided 'Start Here' tour that lays the OS out as a path of stages, each stage opening real apps from the LIVE registry — drift-proof, it reads the injected app catalog instead of a hardcoded list, so adding an app surfaces it automatically (in a stage if listed, else a final 'Everything else' bucket). The catalog, the open(id) callback, and the stage journey are INJECTED via a small StartHereAdapter (apps / open / stages): point configureStartHere at your live app registry + window opener, or keep the bundled in-memory mock (a few generic apps + 3 stages) so the welcome tour renders fully alive with zero host.",
      "source": "rahmanef63/os-vps",
      "slicePath": "frontend/slices/start-here",
      "convexPaths": [],
      "npm": [
        "lucide-react"
      ],
      "shadcn": [
        "button",
        "scroll-area"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "onboarding",
        "tour",
        "welcome",
        "launcher",
        "guide",
        "os",
        "ui"
      ],
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. A guided onboarding tour that renders your live app catalog as a path of stages. Fully client-side; the catalog is injected.\n\nSTEP 1 — Install. `npx rr add start-here`. Ensure `@/features/start-here` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button scroll-area`.\n\nSTEP 3 — Mount. `<StartHere />` in a height-bearing box — unwired it reads an in-memory mock catalog (generic apps + 3 stages) so the tour is fully alive. Or register `startHereApp` in an appshell manifest.\n\nSTEP 4 — Real catalog. `configureStartHere({ mode:\"live\", apps, open, stages })` — apps is your live registry as [{ id, title, icon, description? }]; open(id) launches the real app/window; stages is [{ title, blurb, appIds }] (apps not placed fall into a final \"Everything else\" stage). Drift-proof: read the registry, never hardcode the list."
    },
    {
      "slug": "os-terminal",
      "title": "Terminal — shell emulator with live passthrough + PTY seam",
      "category": "os",
      "kind": "ui",
      "version": "1.2.1",
      "description": "A React-DOM terminal: monospace glass aesthetic, colored prompt, arrow-key history, red stderr. Built-ins (ls·cd·pwd·cat·mkdir·touch·rm·mv·cp·echo·whoami·date·uname·df·ps·neofetch·help·clear) run against an in-memory FsModel, so it works with ZERO backend. Wire configureTerminal({ mode:\"live\", fs, exec }) and ls/cat read through your real filesystem, file mutations mirror to it, and any unknown command passes through exec.run as a one-shot shell call (stdout/stderr/exit rendered). Self-contained: shell inspector hooks are inert seams in lib/host.ts.",
      "source": "rahmanef63/os-vps",
      "slicePath": "frontend/slices/os-terminal",
      "convexPaths": [],
      "npm": [
        "lucide-react"
      ],
      "shadcn": [],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "terminal",
        "shell",
        "cli",
        "emulator",
        "exec",
        "ui"
      ],
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. Shell emulator with optional live passthrough. Fully client-side by default.\n\nSTEP 1 — Install. `npx rr add os-terminal`. Ensure `@/features/os-terminal` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. No shadcn components required.\n\nSTEP 3 — Mount. `<Terminal />` in a height-bearing box — mock mode runs entirely on the in-memory FsModel. Or register `osTerminalApp` in an appshell manifest.\n\nSTEP 4 — Go live. `configureTerminal({ mode:\"live\", fs:{list,read,write,mkdir,remove,move,copy}, exec:{run} })`. In live mode ls/cat read through your fs, mutations mirror, and unknown commands hit exec.run (one-shot; treat the endpoint like SSH)."
    },
    {
      "slug": "assistant",
      "title": "Assistant — agent workspace with streaming chat",
      "category": "os",
      "kind": "ui",
      "version": "1.1.1",
      "description": "A full agent workspace: streaming chat with typing deltas and graceful error notes, plus a library where users CREATE and manage agents (persona, avatar gradient, system prompt), skills, and automations (trigger + schedule forms) — all persisted in localStorage, no backend. Preset agents/skills ship as starting points. The model is INJECTED: configureAssistantStream takes any (messages) => AsyncIterable<string> — your SSE endpoint, the AI SDK, an agent loop — and until wired a typing demo stream keeps the whole UI working offline. Self-contained: shell inspector hooks are inert seams in lib/host.ts.",
      "source": "rahmanef63/os-vps",
      "slicePath": "frontend/slices/assistant",
      "convexPaths": [],
      "npm": [
        "lucide-react"
      ],
      "shadcn": [
        "button",
        "input",
        "textarea",
        "tabs",
        "badge",
        "scroll-area",
        "dropdown-menu",
        "dialog",
        "select",
        "switch"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "ai",
        "assistant",
        "chat",
        "agents",
        "streaming",
        "automations",
        "ui"
      ],
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. Agent workspace with streaming chat. Fully client-side; model injected.\n\nSTEP 1 — Install. `npx rr add assistant`. Ensure `@/features/assistant` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button input textarea tabs badge scroll-area dropdown-menu dialog select switch`.\n\nSTEP 3 — Mount. `<Assistant />` in a height-bearing box. Unwired, a typing demo stream answers so the UI works offline; agents/skills/automations persist in localStorage.\n\nSTEP 4 — Wire a model. `configureAssistantStream(async function* (messages) { ...yield text deltas... })` — SSE endpoint, AI SDK, or an agent loop. Throw Error(\"no_api_key\") / Error(\"unauthorized\") for the chat's friendly error notes."
    },
    {
      "slug": "browser",
      "title": "Browser — remote headless-browser chrome",
      "category": "os",
      "kind": "ui",
      "version": "1.2.1",
      "description": "Full browser chrome for a REMOTE headless browser: omnibar with search-or-URL detection, bookmark bar, history view (localStorage-persisted), favicons with globe fallback, busy states, and a screenshot viewport that forwards clicks/typing/keys/scroll into the remote page. The backend is INJECTED via a small BrowserAdapter (state/screenshot/act): point configureBrowser at a real headless-Chromium service (e.g. Playwright behind an authed route — any site renders, no X-Frame-Options problem) or keep the bundled offline canvas demo renderer that fakes the viewport so the whole chrome works with zero backend. Self-contained: shell inspector hooks are inert seams in lib/host.ts.",
      "source": "rahmanef63/os-vps",
      "slicePath": "frontend/slices/browser",
      "convexPaths": [],
      "npm": [
        "lucide-react"
      ],
      "shadcn": [
        "button",
        "input",
        "badge",
        "dropdown-menu",
        "tooltip",
        "scroll-area"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "browser",
        "headless",
        "playwright",
        "remote",
        "omnibar",
        "bookmarks",
        "ui"
      ],
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. Remote headless-browser chrome. Demo renderer by default; real backend injected.\n\nSTEP 1 — Install. `npx rr add browser`. Ensure `@/features/browser` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button input badge dropdown-menu tooltip scroll-area`.\n\nSTEP 3 — Mount. `<Browser />` in a height-bearing box — unwired, an offline canvas demo renderer fakes the viewport (omnibar/bookmarks/history all work). Or register `browserApp` in an appshell manifest.\n\nSTEP 4 — Real headless browser. `configureBrowser({ state, screenshot, act })` against a Playwright service: state → { url, title }; screenshot → PNG Blob; act(path, body) handles navigate|click|type|key|scroll|back|forward|reload. AUTH those routes — a remote browser holds logged-in sessions."
    },
    {
      "slug": "app-store",
      "title": "App Store — install, create + toggle apps",
      "category": "os",
      "kind": "ui",
      "version": "1.2.1",
      "description": "The dynamic half of an app registry, in two surfaces. AppStore: a storefront with featured hero, category sidebar, install/uninstall cards for a curated catalog, and toggles that disable built-in apps/shell features (the DISABLED set is persisted so new apps always ship enabled). CreateApp: build a custom app — name, glyph, accent gradient, runtime (html/node/python/shell), entry — with live manifest preview. Both write one localStorage registry; useInstalledApps() turns it into appshell-style descriptors (html apps mount in a sandboxed iframe, command apps in a terminal-style console). The console's shell is INJECTED via configureAppStoreExec (demo echo by default). Self-contained: inspector hooks are inert seams in lib/host.ts; the Create-App flow is bundled in (no cross-slice imports).",
      "source": "rahmanef63/os-vps",
      "slicePath": "frontend/slices/app-store",
      "convexPaths": [],
      "npm": [
        "lucide-react"
      ],
      "shadcn": [
        "button",
        "input",
        "badge",
        "separator",
        "scroll-area",
        "switch",
        "tooltip"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "app-store",
        "registry",
        "installer",
        "dynamic-apps",
        "launcher",
        "ui"
      ],
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. Storefront + Create-App over a localStorage app registry. Fully client-side.\n\nSTEP 1 — Install. `npx rr add app-store`. Ensure `@/features/app-store` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: `npx shadcn@latest add button input badge separator scroll-area switch tooltip`.\n\nSTEP 3 — Mount. `<AppStore />` (storefront) and/or `<CreateApp />` (custom-app builder) — or register `appStoreApp` / `createAppApp` in an appshell manifest.\n\nSTEP 4 — Feed your launcher. `useInstalledApps()` returns AppDescriptor[] for everything installed/created (html → sandboxed iframe, command → console); `useDisabledIds()` filters your built-in manifest.\n\nSTEP 5 — Console exec (optional). `configureAppStoreExec({ mode:\"live\", exec:{run} })` so command/script apps run on a real one-shot shell (auth it like SSH)."
    },
    {
      "slug": "file-explorer",
      "title": "File Explorer — Tree + CRUD + Breadcrumb",
      "category": "os",
      "kind": "full",
      "version": "1.4.1",
      "description": "A complete, portable file-directory explorer: a collapsible folder TREE sidebar (lazy-loaded per dir), a responsive BREADCRUMB that auto-collapses to a dropdown, grid + list views with sort, multi-select, a right-click context menu, drag-and-drop (internal move + external file/folder upload), inline rename, and full CRUD (new folder, rename, cut/copy/paste, move, delete/trash, empty trash). The filesystem backend is INJECTED via a small FileExplorerAdapter (list/mkdir/remove/move/copy/upload/usage/rawUrl) — point it at a real API or use the bundled createMockAdapter() (a writable in-memory tree) so it works with zero backend. Opening a file fires an onOpenFile(path, entry) callback you wire to your own viewer/editor. Self-contained: imports only @/components/ui/* + @/lib/utils. Ported from os-vps (Topside) files manager. Pairs with appshell as the file-dir counterpart to a notion-style sidebar.",
      "source": "rahmanef63/os-vps",
      "slicePath": "frontend/slices/file-explorer",
      "convexPaths": [],
      "npm": [
        "lucide-react"
      ],
      "shadcn": [
        "button",
        "input",
        "scroll-area",
        "separator",
        "dropdown-menu",
        "sheet"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "files",
        "file-manager",
        "explorer",
        "tree",
        "breadcrumb",
        "crud",
        "sidebar",
        "ui"
      ],
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. The slice is self-contained — imports only @/components/ui/* + @/lib/utils (cn). The filesystem backend is injected; nothing is hardcoded.\n\nSTEP 1 — Install. `npx rr add file-explorer`. Ensure `@/features/file-explorer` resolves in tsconfig paths and Tailwind's content globs scan the slice folder.\n\nSTEP 2 — shadcn + npm. `npx shadcn@latest add button input scroll-area separator dropdown-menu sheet`. npm: lucide-react.\n\nSTEP 3 — Mount it. Drop it in with NO adapter prop — it falls back to the backend configured in lib/backend.ts (the writable in-memory mock by default), so it works out of the box with realistic seed data and full CRUD:\n```tsx\n\"use client\";\nimport { FileExplorer } from \"@/features/file-explorer\";\nexport default function Page() {\n  return (\n    <div className=\"h-dvh\">\n      <FileExplorer rootLabel=\"Files\" onOpenFile={(path) => console.log(\"open\", path)} />\n    </div>\n  );\n}\n```\n\nSTEP 4 — The backend switch (ONE file). Go to a real filesystem without touching any component: edit `slices/file-explorer/lib/backend.ts` and set `FILE_EXPLORER_BACKEND = \"mock\" | \"live\" | \"convex\"` (or set env `NEXT_PUBLIC_FILE_EXPLORER_BACKEND`). \"live\" = REST host fs (os-vps /api/v1/fs shape, base via NEXT_PUBLIC_FILES_API_URL — see adapter/live.ts). \"convex\" = self-hosted Convex fs functions, PREPARED but inert until you wire your generated client + api in the switch (see adapter/convex.ts; the slice imports nothing from @convex so the build stays green even without Convex). You can still pass `adapter={…}` to override per-instance.\n\nSTEP 5 — Custom adapter. Implement FileExplorerAdapter: { mode: \"live\"|\"mock\"|\"readonly\", list(path), mkdir(path), remove(path), move(from,to), copy(from,to), upload(dest,files), usage(), rawUrl(path), write?(path,content) }. `list` returns { path, entries:[{name,kind,size,ext?}], roots?, parent? }. Set mode:\"readonly\" to show an inline notice instead of mutating. `rawUrl(path)` returns a bytes URL for image thumbnails (return \"\" to fall back to icons).\n\nThe container owns the box — render <FileExplorer> inside something with a height (h-dvh / h-full). It self-provides its adapter context; no extra provider needed."
    },
    {
      "slug": "appshell",
      "title": "AppShell — Desktop + Mobile OS Shell",
      "category": "os",
      "kind": "full",
      "version": "1.5.1",
      "description": "Generic, brand-free OS-style shell framework. One <AppShell manifest> wrapper provider gives a project a macOS-style window manager (drag/snap/maximize, dock, menu bar, Spotlight) AND an iOS-style mobile surface (home pager, app library, control center, widgets), driven entirely by a manifest: brand, apps, features, surface regions, capabilities, persistence, keymap. Five shell features (search, inspector, notifications, control-center, widgets) are bundled as defineFeature() contributions inside the slice and mount via named <Slot>s. Responsiveness is a single ResponsiveProvider + 4 DRY primitives (AppFrame, MasterDetail, ResponsiveToolbar, TouchList). Imports nothing project-specific — the consumer injects data/auth/AI through manifest.capabilities. Lifted from os-vps (Topside).",
      "source": "rahmanef63/os-vps",
      "slicePath": "frontend/slices/appshell",
      "convexPaths": [],
      "npm": [
        "lucide-react",
        "class-variance-authority",
        "clsx",
        "tailwind-merge",
        "vaul"
      ],
      "shadcn": [
        "button",
        "tooltip",
        "scroll-area",
        "sheet",
        "drawer",
        "dialog",
        "alert-dialog",
        "dropdown-menu"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "shell",
        "window-manager",
        "desktop",
        "mobile",
        "responsive",
        "framework",
        "ui"
      ],
      "agentRecipe": "Stack required: Next 16 (App Router) + React 19 + Tailwind 4 + shadcn/ui. The slice is self-contained — it imports only @/components/ui/* + @/lib/utils (cn); everything project-specific arrives via the manifest. Follow ALL steps; the ⚠ ones are where installs break.\n\nSTEP 1 — Install. `npx rr add appshell` (alias `npx rahman-resources add appshell`). It copies to your slices dir. Ensure `@/features/appshell` resolves in tsconfig paths (point it at that dir), and that Tailwind's content globs SCAN the slice folder (else the shell renders unstyled).\n\nSTEP 2 — shadcn + npm deps. Add any missing shadcn primitives: `npx shadcn@latest add button tooltip scroll-area sheet drawer dialog alert-dialog dropdown-menu`. npm: lucide-react class-variance-authority clsx tailwind-merge vaul.\n\nSTEP 3 — ⚠ Theme. Import the slice's tokens ONCE in the root layout: `import \"@/features/appshell/appshell.css\"`. These are the glass/dock/window/wallpaper CSS variables the shell needs — they are NOT shadcn defaults, so skipping this = an unstyled, broken-looking shell. It pairs with your shadcn tokens (--background etc.). Dark mode = toggle the `.dark` class on <html> (appshell.css ships light + dark).\n\nSTEP 4 — Mount full-bleed. Render <AppShell manifest={manifest} /> from a CLIENT component that owns one full viewport (the page is h-dvh w-screen / the root). AppShell auto-picks the macOS desktop on wide viewports and the iOS surface on narrow — you write nothing extra for mobile.\n\nSTEP 5 — Build the ShellManifest:\n• brand: { name, logo (string or ReactNode), idleAppName?, wallpaper?: \"aurora\"|\"dusk\"|\"mist\"|\"noir\" }.\n• apps: AppDescriptor[] — { id, title, icon (a lucide-react icon component), gradient (a CSS gradient string for the glossy icon), load: async () => ({ default: YourAppComponent }), slug?, defaultSize?: {w,h}, multi?: true (spawn a new window per open, e.g. a file manager), noDock?: true }. Your app component receives props { payload }.\n• features: the fastest path is `features: DEFAULT_FEATURES` — the bundled default system-feature set (all five, generic + brand-free) exported from \"@/features/appshell\". Or import individually and list only what you want: searchFeature (⌘K Spotlight), inspectorFeature (⌘I AI/context panel), notificationsFeature (toasts + iOS dynamic island), controlCenterFeature (iOS control center), widgetsFeature (iOS Today widgets). The surfaces are slot-driven, so spreading/trimming DEFAULT_FEATURES just mounts/omits a feature — `features: [...DEFAULT_FEATURES.filter(f => f.id !== \"widgets\")]`.\n• capabilities: ShellCapabilities — your data/auth/AI injection seam. useAppearance() and useCpuPercent() are REQUIRED; useSearch/useSystemStats/useChat/useServerToggle are optional (defaults degrade gracefully). ⚠ CRITICAL: every capability hook MUST return a REFERENTIALLY STABLE value — a module-level const, or useMemo/useCallback. Returning a fresh object/closure each render makes Spotlight's search effect re-fire forever (\"Maximum update depth exceeded\"). e.g. define APPEARANCE once at module scope and `useAppearance: () => APPEARANCE`.\n• persistKey?: localStorage namespace for the saved window layout (default \"appshell:layout\").\n• routing?: defaults TRUE — it mirrors the focused app to the URL via the History API (window.history, NOT router.push). ⚠ If true you MUST add a catch-all route `app/[[...slug]]/page.tsx` that renders the mount AND calls notFound() for reserved paths (slug[0] === \"_next\"), or missing chunks return wrong-MIME 200s. SIMPLEST first install: set `routing: false` to skip the catch-all entirely.\n\nExtending: add an app = one manifest entry; add a shell feature = a new defineFeature({id, slots}) listed in features[]. No surface edits ever (open/closed). exampleCode ships BOTH variants: Variant A = routing:false mount in app/page.tsx (simplest); Variant B = catch-all app/[[...slug]]/page.tsx with routing on + app slugs for addressable, deep-linkable URLs (the catch-all MUST notFound() \"_next\")."
    },
    {
      "slug": "convex-auth",
      "title": "Convex Auth — Multi-Provider Sign-in",
      "category": "auth",
      "kind": "backend",
      "version": "0.4.0",
      "description": "@convex-dev/auth with Password (PBKDF2-SHA256 100k, self-hosted-friendly), Anonymous (guest), Google OAuth, and Resend magic-link. Ships a production SignInPage plus a presentational, props-driven AuthCard (v0.3) — choose `methods` (google, github, magic-link, password signin/signup tabs, phone OTP, anonymous) and render the card anywhere with different props; handlers default to a mock so it's interactive with zero wiring. i18n via labels. No Clerk.",
      "source": "rahmanef63/resource-site",
      "slicePath": "frontend/slices/convex-auth",
      "convexPaths": [
        "convex/features/auth"
      ],
      "npm": [
        "@convex-dev/auth@^0.0.92",
        "@auth/core@^0.37.4",
        "resend@^4.0.0"
      ],
      "shadcn": [
        "button",
        "card",
        "input",
        "label",
        "tabs",
        "alert",
        "input-otp"
      ],
      "env": [
        {
          "name": "AUTH_RESEND_KEY",
          "scope": "convex"
        },
        {
          "name": "JWT_PRIVATE_KEY",
          "scope": "convex"
        },
        {
          "name": "JWKS",
          "scope": "convex"
        },
        {
          "name": "SITE_URL",
          "scope": "convex"
        },
        {
          "name": "AUTH_GOOGLE_ID",
          "scope": "convex"
        },
        {
          "name": "AUTH_GOOGLE_SECRET",
          "scope": "convex"
        }
      ],
      "peers": [],
      "providers": [],
      "tags": [
        "auth",
        "convex",
        "password",
        "magic-link",
        "google",
        "anonymous",
        "no-clerk",
        "pbkdf2"
      ],
      "agentRecipe": "Run `rr add convex-auth`. Then create convex/auth.ts using the kitab pattern (Resend provider). Set env via `npx convex env set` for self-hosted."
    },
    {
      "slug": "payment",
      "title": "Payment — Indonesia PSP (DOKU · Midtrans)",
      "category": "integrations",
      "kind": "full",
      "version": "0.4.0",
      "description": "Indonesia payment providers behind one slug + ONE shared Convex backend (convex/features/payment discriminates on a provider column: paymentOrders + paymentWebhookEvents, unprefixed). Two frontend variants: doku — DOKU Hosted Checkout + Direct (VA / QRIS / e-Wallet / PayLater), HMAC-SHA256 signed REST, signature-verified webhook, idempotent retries, dependency-free, server-side env only. midtrans — Snap hosted-modal checkout + orders history (needs npm midtrans-client + a NEXT_PUBLIC_MIDTRANS_CLIENT_KEY). Install one with `npx rr add payment doku|midtrans`, or both. A future stripe variant is reserved in the schema's provider union.",
      "source": "rahmanef63/resource-site",
      "slicePath": "frontend/slices/payment",
      "convexPaths": [
        "convex/features/payment"
      ],
      "npm": [
        "midtrans-client@^1.4.2"
      ],
      "shadcn": [
        "badge",
        "button",
        "card",
        "dialog",
        "input",
        "label",
        "select",
        "skeleton"
      ],
      "env": [
        {
          "name": "DOKU_CLIENT_ID",
          "scope": "convex"
        },
        {
          "name": "DOKU_SECRET_KEY",
          "scope": "convex"
        },
        {
          "name": "DOKU_IS_PRODUCTION",
          "scope": "convex"
        },
        {
          "name": "MIDTRANS_SERVER_KEY",
          "scope": "convex"
        },
        {
          "name": "MIDTRANS_CLIENT_KEY",
          "scope": "next-public"
        },
        {
          "name": "MIDTRANS_IS_PRODUCTION",
          "scope": "convex"
        }
      ],
      "peers": [
        {
          "slug": "convex-auth",
          "range": "^0.1",
          "reason": "Order ownership requires authenticated user (guest checkout works without)."
        }
      ],
      "providers": [
        "doku",
        "midtrans"
      ],
      "tags": [
        "payment",
        "checkout",
        "indonesia",
        "doku",
        "midtrans",
        "snap",
        "qris",
        "virtual-account",
        "ewallet",
        "psp"
      ],
      "agentRecipe": "Run `npx rr add payment` for both providers, or `npx rr add payment doku` / `midtrans`. Either variant copies the shared convex/features/payment backend. doku: Checkout (hosted) or Direct (single channel → VA/QRIS/deeplink); webhook /webhooks/doku verifies HMAC-SHA256; server-only, no NEXT_PUBLIC_*. midtrans: Snap.js + window.snap.pay(token); webhook verifies signature_key; needs NEXT_PUBLIC_MIDTRANS_CLIENT_KEY. Both patch paymentOrders by orderId; sandbox by default.",
      "variants": {
        "default": "doku",
        "items": [
          {
            "id": "doku",
            "title": "DOKU",
            "description": "Hosted Checkout + Direct channel picker, HMAC REST, dependency-free."
          },
          {
            "id": "midtrans",
            "title": "Midtrans",
            "description": "Snap hosted-checkout button + orders history (needs midtrans-client + next-public key)."
          }
        ]
      }
    },
    {
      "slug": "resend-newsletter",
      "title": "Resend — Transactional & Newsletter",
      "category": "integrations",
      "kind": "backend",
      "version": "0.2.0",
      "description": "Transactional email + newsletter blast via Resend. Double opt-in flow + audience segmentation. Magic-link delivery for Convex Auth. Bundles the subscribers list backend (subscribe / confirm / unsubscribe / count) — formerly the standalone `subscribers` slice, merged here in v0.1.3.",
      "source": "rahmanef63/resource-site",
      "slicePath": "frontend/slices/resend-newsletter",
      "convexPaths": [
        "convex/features/newsletter",
        "convex/features/subscribers"
      ],
      "npm": [
        "resend@^4.0.0"
      ],
      "shadcn": [
        "button",
        "card",
        "input",
        "label",
        "textarea"
      ],
      "env": [
        {
          "name": "RESEND_API_KEY",
          "scope": "convex",
          "required": true
        },
        {
          "name": "RESEND_FROM",
          "scope": "convex",
          "required": true
        }
      ],
      "peers": [],
      "providers": [],
      "tags": [
        "email",
        "newsletter",
        "resend"
      ],
      "agentRecipe": "Run `npx rr add resend-newsletter`. Use Resend Audiences API for newsletter — store subscriber emails in Convex too for segmentation. Double opt-in: subscriber.create with status 'pending' → click link → status 'confirmed'."
    },
    {
      "slug": "ai-workspace",
      "title": "AI Workspace — chat · studio · agents",
      "category": "ai",
      "kind": "full",
      "version": "0.3.0",
      "description": "Three AI surfaces as shadcn-style variants — `npx rr add ai-workspace <variant>` for one, or `npx rr add ai-workspace` for all + a switcher. Only the chat variant pulls a Convex backend (per-variant convex gating).\n\n  • chat — floating <AiChatFab /> + createAgenticChatSend: real function-calling over any ToolHost (@/shared/agentic), key-guarded, over convex/features/aiChat.\n  • studio — <AiStudioPage /> single-prompt generation canvas (variation grid + version tree, Suno / Midjourney / Lovable pattern) + aiStudioTools so a shared agent can drive generations.\n  • agents — <AiAgentsPage /> autonomous-worker run dashboard + createAgentRunner(host) which drives the shared function-calling loop and records each tool_use as a RunStep trace.\n\nUse cases: support chatbot in a marketing site, AI generation product (image / code / text / audio), background workers (nightly audits, scheduled crawls, moderation). studio + agents are frontend-only — wire your own persistence.",
      "source": "rahmanef63/resource-site",
      "slicePath": "frontend/slices/ai-workspace",
      "convexPaths": [
        "convex/features/aiChat"
      ],
      "npm": [
        "ai@^4.0.0",
        "@ai-sdk/anthropic@^0.0.50",
        "@ai-sdk/openai@^0.0.60"
      ],
      "shadcn": [
        "avatar",
        "badge",
        "button",
        "card",
        "progress",
        "scroll-area",
        "select",
        "separator",
        "slider",
        "switch",
        "table",
        "tabs",
        "textarea",
        "tooltip"
      ],
      "env": [
        {
          "name": "ANTHROPIC_API_KEY",
          "scope": "convex",
          "required": false
        },
        {
          "name": "OPENAI_API_KEY",
          "scope": "convex",
          "required": false
        },
        {
          "name": "GOOGLE_GENERATIVE_AI_API_KEY",
          "scope": "convex",
          "required": false
        }
      ],
      "peers": [
        {
          "slug": "convex-auth",
          "range": "^0.1",
          "reason": "chat/studio/agents ownership requires an authenticated user."
        },
        {
          "slug": "ai-router",
          "range": "^0.1",
          "reason": "Routes provider calls through the tiered proxy."
        },
        {
          "slug": "ai-admin",
          "range": "^0.1",
          "reason": "Reads instructions / skills / tools / models / agent defs from the ai-admin registry."
        },
        {
          "slug": "vector-search",
          "range": "^0.1",
          "reason": "Optional — chat RAG mode pulls workspace embeddings."
        }
      ],
      "providers": [],
      "tags": [
        "ai",
        "ai:chatbot",
        "ai:studio",
        "ai:agent",
        "agent-mode",
        "tool-calls",
        "streaming",
        "generation",
        "async",
        "traces",
        "multimodal"
      ],
      "agentRecipe": "Run `npx rr add ai-workspace <chat|studio|agents>` for one surface, or `npx rr add ai-workspace` for all. chat: mount <AiChatFab chat={useAction(api.features.aiChat.action.chat)} />. studio: mount <AiStudioPage /> + drive via aiStudioTools. agents: mount <AiAgentsPage /> + trigger via createAgentRunner(host).",
      "variants": {
        "default": "chat",
        "items": [
          {
            "id": "chat",
            "title": "Chat",
            "description": "Floating assistant FAB with real function-calling over any ToolHost.",
            "convex": [
              "convex/features/aiChat"
            ]
          },
          {
            "id": "studio",
            "title": "Studio",
            "description": "Single-prompt generation canvas + agentic generate tool.",
            "convex": []
          },
          {
            "id": "agents",
            "title": "Agents",
            "description": "Autonomous-worker run dashboard + createAgentRunner loop.",
            "convex": []
          }
        ]
      }
    },
    {
      "slug": "ai-admin",
      "title": "AI Admin — Console (Instructions · Skills · Tools · Agents · Providers)",
      "category": "ai",
      "kind": "full",
      "version": "0.3.0",
      "description": "Central operator console for the whole AI stack. Every other ai-* feature reads its registries from here. Tabs ordered to match the build-flow:\n\n  1. Providers   — register Anthropic / OpenAI / Google / Mistral / Ollama (API keys AES-encrypted at rest)\n  2. Models      — per-provider catalog (capabilities, context window, pricing)\n  3. Instructions — custom system-prompt library (Claude Projects-style)\n  4. Skills      — named instruction + model default + tool defaults (consumed by chat + studio)\n  5. Tools       — JSON-schema function specs + impl (http / convex / shell) + sandbox flag\n  6. Agents      — skill × model × tools × max-iter (consumed by ai-agents)\n  7. Budgets     — per-workspace cost caps + alerts + hard kill\n  8. Audit       — every AI call: actor / agent / tokens / cost / latency / outcome\n\nIncludes Create-Agent / Create-Skill / Create-Tool / Create-Instruction wizards.",
      "source": "rahmanef63/resource-site",
      "slicePath": "frontend/slices/ai-admin",
      "convexPaths": [
        "convex/features/ai"
      ],
      "npm": [],
      "shadcn": [
        "card",
        "button",
        "badge",
        "tabs",
        "table",
        "dialog",
        "input",
        "label",
        "select",
        "textarea",
        "switch",
        "command"
      ],
      "env": [
        {
          "name": "AI_ADMIN_ENCRYPTION_KEY",
          "scope": "convex",
          "required": true,
          "description": "Encrypts stored provider API keys at rest."
        }
      ],
      "peers": [
        {
          "slug": "convex-auth",
          "range": "^0.1",
          "reason": "requireAdmin gate."
        },
        {
          "slug": "rbac-roles",
          "range": "^0.1",
          "reason": "Section gated by ai.* permissions (manage_providers, manage_skills, etc)."
        },
        {
          "slug": "admin-panel",
          "range": "^0.1",
          "reason": "Lives as a registered admin section."
        },
        {
          "slug": "audit-log",
          "range": "^0.1",
          "reason": "Every config change + AI call routes through audit-log."
        }
      ],
      "providers": [],
      "tags": [
        "ai",
        "ai:admin",
        "instructions",
        "skills",
        "tools",
        "agents",
        "providers",
        "models",
        "budgets",
        "audit"
      ],
      "agentRecipe": "Run `npx rr add ai-admin`. Adds an `AI` section to the admin-panel ADMIN_SECTIONS registry. Sub-tabs ordered to match build-flow: Providers → Models → Instructions → Skills → Tools → Agents → Budgets → Audit. Includes Create-* wizards for instructions / skills / tools / agents. API keys AES-encrypted via AI_ADMIN_ENCRYPTION_KEY env. The instruction / skill / tool / agent registries are SSOTs consumed by every ai-* consumer slice (chat + studio + agents)."
    },
    {
      "slug": "ai-router",
      "title": "AI Router — Backend Provider Proxy",
      "category": "ai",
      "kind": "backend",
      "version": "0.5.0",
      "description": "Backend infrastructure (no UI). Single proxy that every other ai-* feature calls. Tier-routed — nano (Haiku) for classification, mid (Sonnet) for chat, flagship (Opus) for deep reasoning. Per-call usage log + cost guard. Works with direct provider keys or OpenRouter umbrella.\n\nNot something you mount — installed automatically as a peer when you add ai-workspace.",
      "source": "rahmanef63/resource-site",
      "slicePath": "frontend/slices/ai-router",
      "convexPaths": [
        "convex/features/ai"
      ],
      "npm": [
        "ai@^4.0.0",
        "@openrouter/ai-sdk-provider@^0.0.5"
      ],
      "shadcn": [
        "button"
      ],
      "env": [
        {
          "name": "OPENROUTER_API_KEY",
          "scope": "convex",
          "required": true
        }
      ],
      "peers": [],
      "providers": [],
      "tags": [
        "ai",
        "ai:backend",
        "tier-routing",
        "cost-guard"
      ],
      "agentRecipe": "Run `npx rr add ai-router`. Wrap every AI call through ai-router. Tiers: nano = quick classification (spam-flag, headline-suggest), mid = chat / draft, flagship = methodology-review / deep-think. Token usage logs to ai_usage table for the cost dashboard."
    },
    {
      "slug": "vector-search",
      "title": "Convex Vector Search",
      "category": "data",
      "kind": "full",
      "version": "0.2.0",
      "description": "Embeddings-based search via Convex's built-in vector index. Embed via OpenAI text-embedding-3-small (1536-dim), query via vectorIndex().",
      "source": "rahmanef63/resource-site",
      "slicePath": "frontend/slices/vector-search",
      "convexPaths": [
        "convex/features/search"
      ],
      "npm": [
        "@convex-dev/vector-search@^0.0.5"
      ],
      "shadcn": [
        "card",
        "input"
      ],
      "env": [
        {
          "name": "OPENAI_API_KEY",
          "scope": "convex",
          "required": true
        }
      ],
      "peers": [],
      "providers": [],
      "tags": [
        "search",
        "vector",
        "embeddings",
        "convex",
        "rag"
      ],
      "agentRecipe": "Run `npx rr add vector-search`. Add embedding field + vectorIndex per searchable table. Re-embed on upsert via Convex action. Cache embeddings — don't re-call OpenAI on every read."
    },
    {
      "slug": "cal-com-booking",
      "title": "Cal.com Booking",
      "category": "data",
      "kind": "full",
      "version": "0.2.0",
      "description": "Embedded Cal.com booking widget + webhook receiver to mirror bookings into Convex.",
      "source": "rahmanef63/resource-site",
      "slicePath": "frontend/slices/cal-com-booking",
      "convexPaths": [
        "convex/features/bookings"
      ],
      "npm": [
        "@calcom/embed-react@^1.5.0"
      ],
      "shadcn": [
        "card"
      ],
      "env": [
        {
          "name": "NEXT_PUBLIC_CALCOM_USERNAME",
          "scope": "next-public",
          "required": true
        },
        {
          "name": "CALCOM_WEBHOOK_SECRET",
          "scope": "convex",
          "required": true
        }
      ],
      "peers": [],
      "providers": [],
      "tags": [
        "data",
        "scheduling",
        "cal-com",
        "bookings"
      ],
      "agentRecipe": "Run `npx rr add cal-com-booking`. Embed Cal.com via @calcom/embed-react di halaman services. Configure webhook di Cal.com dashboard → POST ke /api/cal-webhook → upsert booking di Convex."
    },
    {
      "slug": "command-menu",
      "title": "Command Menu",
      "category": "ui",
      "kind": "ui",
      "version": "0.3.0",
      "description": "Renderless ⌘K command palette + generic search modal. Consumer supplies CommandGroup[] + onSelect + label bag; slice owns dialog chrome, ⌘K hotkey, MRU history. Pulled UP from notion-page-clone's command-palette renderless surface (Wave N+3.7) — Nosion adapters dropped at the kitab boundary.",
      "source": "notion-page-clone (consumerVersion 0.3.0) + earlier superspace facade",
      "slicePath": "frontend/slices/command-menu",
      "convexPaths": [],
      "npm": [
        "cmdk@^1.0.0"
      ],
      "shadcn": [
        "command",
        "dialog"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "ui",
        "palette",
        "cmd-k",
        "navigation",
        "keyboard",
        "search",
        "notion-like"
      ],
      "agentRecipe": "Run `npx rr add command-menu`. Wire <CommandPalette groups={...} onHistorySelect={...} labels={...} /> at the dashboard shell. Build groups from your feature registry; each item.onSelect handles navigation. Use <SearchModal bindings={{ pages, databases, recents, isLoading, onQueryChange, onSelectPage, onSelectDatabase }} /> for the search dialog — see slice README.md for adapter shapes."
    },
    {
      "slug": "motion-primitives",
      "title": "Motion Primitives (8)",
      "category": "ui",
      "kind": "ui",
      "version": "0.1.0",
      "description": "Eight ready-to-style motion components: marquee, kinetic-heading, magnetic, cursor-spotlight, stat-counter, reading-progress, grain, lightbox. Framer-Motion-powered, tree-shakeable. Facade slice — pulls from template-base/frontend/slices/motion-primitives.",
      "source": "rahmanef.com",
      "slicePath": "template-base/frontend/slices/motion-primitives",
      "convexPaths": [],
      "npm": [
        "framer-motion@^11.0.0"
      ],
      "shadcn": [],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "ui",
        "motion",
        "animation",
        "marquee",
        "framer-motion"
      ],
      "agentRecipe": "Run `npx rr add motion-primitives`. Each primitive is independently importable from @/features/motion-primitives. Use marquee for logo strips, kinetic-heading for hero text, magnetic for CTA buttons, cursor-spotlight for hover-reveal panels, stat-counter for animated numbers, reading-progress for blog top bar, grain for film texture, lightbox for image gallery."
    },
    {
      "slug": "responsive-dialog",
      "title": "Responsive Dialog (Sheet ↔ Modal)",
      "category": "ui",
      "kind": "ui",
      "version": "0.1.0",
      "description": "ResponsiveDialog — auto-switches between bottom Sheet (mobile) and centered Dialog (desktop) at the md breakpoint. Same API as shadcn Dialog. Kitab forbids raw <dialog>; use this everywhere. Facade slice — pulls from template-base/frontend/slices/responsive-dialog.",
      "source": "superspace",
      "slicePath": "template-base/frontend/slices/responsive-dialog",
      "convexPaths": [],
      "npm": [],
      "shadcn": [
        "dialog",
        "sheet"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "ui",
        "dialog",
        "modal",
        "sheet",
        "responsive",
        "primitive"
      ],
      "agentRecipe": "Run `npx rr add responsive-dialog`. Drop-in for shadcn Dialog. Use <ResponsiveDialog><ResponsiveDialogTrigger>…</ResponsiveDialogTrigger><ResponsiveDialogContent>…</ResponsiveDialogContent></ResponsiveDialog>. On mobile renders as Sheet sliding from bottom; on desktop as centered Dialog. Threshold via useMediaQuery('(min-width: 768px)')."
    },
    {
      "slug": "dashboard-shell",
      "title": "Dashboard Shell — Responsive",
      "category": "ui",
      "kind": "ui",
      "version": "0.1.0",
      "description": "ResponsiveDashboardShell — desktop sidebar + topbar, mobile dock + sheet sidebar, breakpoint-aware. Ports superspace's layout/dashboard/{Desktop,Mobile,Responsive}DashboardShell + sidebar primary/secondary slots. Facade slice — pulls from template-base/frontend/slices/dashboard-shell.",
      "source": "superspace",
      "slicePath": "template-base/frontend/slices/dashboard-shell",
      "convexPaths": [],
      "npm": [],
      "shadcn": [
        "sheet",
        "scroll-area",
        "separator",
        "tooltip"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "ui",
        "layout",
        "dashboard",
        "sidebar",
        "topbar",
        "responsive"
      ],
      "agentRecipe": "Run `npx rr add dashboard-shell`. Wraps app/(admin) routes. <ResponsiveDashboardShell sidebar={<AppSidebar />} topbar={<TopBar />}>{children}</ResponsiveDashboardShell>. Mobile: sidebar collapses to <Sheet>. Desktop: persistent sidebar + topbar. Embed FullWidthToggle in topbar for instant container resize."
    },
    {
      "slug": "three-column",
      "title": "Three-Column Layout — Sidebar/Content/Inspector",
      "category": "ui",
      "kind": "ui",
      "version": "0.1.0",
      "description": "ThreeColumnLayoutAdvanced — collapsible left/right + resizable widths + responsive breakpoints + PanelSection compound (Header/Items/Footer) + per-panel footer slots. Models shadcn sidebar API for the panel interior. Pair with PanelGroup/PanelMenu/PanelSeparator primitives. Trigger ≠ header (V-wave separation rule).",
      "source": "superspace",
      "slicePath": "template-base/frontend/slices/three-column",
      "convexPaths": [],
      "npm": [],
      "shadcn": [
        "sheet",
        "scroll-area",
        "separator",
        "tooltip"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "ui",
        "layout",
        "three-column",
        "sidebar",
        "inspector",
        "panel-section",
        "responsive",
        "resizable"
      ],
      "agentRecipe": "Run `npx rr add three-column`. <ThreeColumnLayoutAdvanced preset=\"feature\" storageKey persistState left={…PanelSection…} center={…PanelSection unstyled…} right={…PanelSection…} leftFooter centerFooter rightFooter />. Center column SHOULD pass `unstyled` to drop sidebar tokens — body is content surface. `storageKey` MUST differ per slice or persisted widths collide."
    },
    {
      "slug": "broadcast-channel-sync",
      "title": "BroadcastChannel — Cross-tab Sync",
      "category": "data",
      "kind": "ui",
      "version": "0.2.0",
      "description": "Same-origin cross-tab + cross-iframe state sync via BroadcastChannel API. Tiny, no backend, no install.",
      "source": "Web Platform — BroadcastChannel API",
      "slicePath": "frontend/slices/broadcast-channel-sync",
      "convexPaths": [],
      "npm": [],
      "shadcn": [],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "realtime",
        "cross-tab",
        "broadcast-channel",
        "demo-pattern"
      ],
      "agentRecipe": "Run `npx rr add broadcast-channel-sync`. Use BroadcastChannel only for demo / cross-iframe state mirroring. Production data still goes through Convex realtime. Use the useBroadcastSync(channelName, initial) hook from @/features/broadcast-channel-sync."
    },
    {
      "slug": "rbac-roles",
      "title": "RBAC — Roles & Permissions",
      "category": "auth",
      "kind": "full",
      "version": "0.3.0",
      "description": "RBAC engine ported from superspace. 6 system role presets (owner/admin/manager/staff/client/guest with levels), dot-namespaced permissions with `*` / `feature.*` wildcard matching, and pure check helpers (resolvePermissions / hasPermission / roleHasPermission). Props-driven UI primitives: <PermissionGate>, usePermissions, <RoleBadge>, <PermissionMatrix>. Convex template ships a tenant-scoped rbac_roles table + checkPermission / requirePermission helpers + idempotent seedSystemRoles, with a PLATFORM_ADMIN_EMAILS superadmin bypass. Pair with `user-management` for the members / invites / roles-admin UI. @convex-dev/auth aware — no Clerk.",
      "source": "superspace",
      "slicePath": "frontend/slices/rbac-roles",
      "convexPaths": [
        "convex/features/rbac_roles"
      ],
      "npm": [],
      "shadcn": [
        "badge",
        "checkbox",
        "label"
      ],
      "env": [
        {
          "name": "PLATFORM_ADMIN_EMAILS",
          "scope": "convex",
          "description": "Comma-separated emails granted cross-tenant superadmin (`*`)."
        }
      ],
      "peers": [
        {
          "slug": "convex-auth",
          "range": "^0.1",
          "reason": "RBAC checks resolve the authed user via getAuthUserId."
        }
      ],
      "providers": [],
      "tags": [
        "rbac",
        "auth",
        "permissions",
        "roles",
        "authorization",
        "no-clerk",
        "convex"
      ],
      "agentRecipe": "Run `npx rr add rbac-roles`. Frontend: import { PermissionGate, usePermissions, RoleBadge, PermissionMatrix, resolvePermissions, ROLE_PRESETS } from \"@/features/rbac-roles\". Feed usePermissions/PermissionGate the actor's resolved permission list (from your membership query or resolvePermissions(roleSlug)). Convex: spread rbacRolesTables into your schema, call seedSystemRoles({tenantId}) once, gate privileged fns with requirePermission(ctx, tenantId, \"members.manage\"). Set PLATFORM_ADMIN_EMAILS for superadmins. Add the user-management slice for the members/invites UI (provides um_members)."
    },
    {
      "slug": "user-management",
      "title": "User Management",
      "category": "auth",
      "kind": "full",
      "version": "0.7.0",
      "description": "Full superspace-parity user management, props-driven + RBAC-agnostic. <UserManagementPanel> tabs Members + Roles + Teams + Access: member table (search / filter / sort, inline role dropdown, soft-remove), InviteDialog (with an optional 'propagate to sub-workspaces' toggle — same / step-down role strategy) + PendingInvites, a RolesPanel (custom roles via permission matrix; system roles read-only), a TeamsPanel (named user groups), and an AccessMatrix (users × tenants grid with inline role assignment). All permission-gated. You pass `roles` + `currentPerms` + the permission catalog (resolved from rbac-roles) + callbacks; the slice imports no other slice's frontend. Convex ships um_members + um_invites + um_teams + um_team_members + um_tenant_links + member / invite / team / hierarchy endpoints + getAccessMatrix (gated via rbac-roles' requirePermission); roles CRUD reuses rbac-roles'. The hierarchy is a generic edge tree — rr never owns the tenant entities. P0–P4c: the complete user-management epic.",
      "source": "superspace",
      "slicePath": "frontend/slices/user-management",
      "convexPaths": [
        "convex/features/user_management"
      ],
      "npm": [],
      "shadcn": [
        "avatar",
        "badge",
        "button",
        "checkbox",
        "dialog",
        "dropdown-menu",
        "input",
        "label",
        "select",
        "switch",
        "table",
        "tabs",
        "textarea"
      ],
      "env": [],
      "peers": [
        {
          "slug": "rbac-roles",
          "range": "^0.2",
          "reason": "Roles + resolved permissions + convex permission helpers (requirePermission, getActorPermissions)."
        },
        {
          "slug": "convex-auth",
          "range": "^0.1",
          "reason": "Member identity (name/email/avatar) joined from the users table."
        }
      ],
      "providers": [],
      "tags": [
        "user-management",
        "members",
        "rbac",
        "auth",
        "team",
        "admin",
        "convex",
        "no-clerk"
      ],
      "agentRecipe": "Run `npx rr add user-management` (pulls rbac-roles + convex-auth). Frontend: <MembersPanel members={useQuery(api[\"features/user_management/query\"].listMembers,{tenantId})} roles={ROLE_PRESETS.map(r=>({slug:r.slug,name:r.name,color:r.color}))} currentPerms={actorPerms} onUpdateRole={useMutation(...updateMemberRole)} onRemove={useMutation(...removeMember)} onInvite={openInvite} />. Wire roles + currentPerms from rbac-roles at the app level — the slice itself imports no other slice. Convex: spread userManagementTables; listMembers/mutations gate via rbac-roles requirePermission."
    },
    {
      "slug": "admin-panel",
      "title": "Admin Panel — Unified Product Admin",
      "category": "infra",
      "kind": "full",
      "version": "0.1.0",
      "description": "17-section admin surface (events, funnels, attribution, users, A/B, flags, pricing, CMS, email, audit, ...) gated by RBAC. Auto-filters sidebar by tier (solo/influencer/organization) and user permissions. Single backend resolver (getMyAdminAccess) mirrors frontend gate so UI can never leak.",
      "source": "superspace + spec",
      "slicePath": "template-base/frontend/slices/admin-panel",
      "convexPaths": [
        "template-base/convex/features/admin-panel"
      ],
      "npm": [],
      "shadcn": [
        "card",
        "badge",
        "button"
      ],
      "env": [],
      "peers": [
        {
          "slug": "rbac-roles",
          "range": "^0.1",
          "reason": "Admin sections require RBAC perms — must seed roles first."
        },
        {
          "slug": "dashboard-shell",
          "range": "^0.1",
          "reason": "AdminShell is the INNER section nav — mount AdminPage inside the dashboard-shell app chrome."
        }
      ],
      "providers": [],
      "tags": [
        "admin",
        "owner",
        "platform",
        "rbac",
        "instrumentation",
        "panel"
      ],
      "agentRecipe": "Run `npx rr add admin-panel`. Wrap pages with <AdminPage workspaceId tier>. AccessGate hides UI for non-admins, AdminShell renders 2-col layout with sidebar filtered by tier+perms. ADMIN_SECTIONS in config.ts is SSOT (17 entries). Personal-brand-os = tier 'solo' = owner sees everything."
    },
    {
      "slug": "event-tracking",
      "title": "Event Tracking — P0 Instrumentation",
      "category": "data",
      "kind": "full",
      "version": "0.1.0",
      "description": "Client SDK + Convex ingestion endpoint for structured product events. Auto-captures page_view/signup/login + UTM/referrer/first-touch attribution. Batched flush via requestIdleCallback. Targets <100ms p99 ingestion.",
      "source": "spec + superspace analytics",
      "slicePath": "template-base/frontend/slices/admin-panel/slices/events",
      "convexPaths": [
        "template-base/convex/features/admin-panel",
        "template-base/convex/features/analytics"
      ],
      "npm": [],
      "shadcn": [],
      "env": [],
      "peers": [
        {
          "slug": "admin-panel",
          "range": "^0.1",
          "reason": "Lives under admin slice events subfolder."
        }
      ],
      "providers": [],
      "tags": [
        "events",
        "analytics",
        "instrumentation",
        "attribution",
        "utm",
        "p0"
      ],
      "agentRecipe": "Run `npx rr add event-tracking`. Writes to analyticsEvents table (no new schema). Anonymous page_view allowed pre-signup; other events require workspaceId. Session id per tab (sessionStorage), first-touch UTM in localStorage. Flush every ~500ms via requestIdleCallback. Cap retry queue at 500."
    },
    {
      "slug": "icon-picker",
      "title": "Icon Picker",
      "category": "ui",
      "kind": "ui",
      "version": "0.5.0",
      "description": "Emoji + lucide (outline) + phosphor (fill) icon picker with search, 10-color palette, Twemoji/native toggle, recents tracking, and smart positioning. Two-tab layout (Emoji | Icon) with sub-variant pills (Native | Twemoji / Lucide | Phosphor fill). One string stores emoji OR lucide:Name OR phosphor:Name OR with ?c=hex tint — backwards-compat with raw-emoji fields. Popover auto-flips on collision (caps to Radix `--radix-popover-content-available-height`) and falls back to centered Dialog when neither side fits. Two variants: Popover (compact trigger) and Inline (full sheet/dialog use). Lifted 2026-05-25 from open-silong.",
      "source": "open-silong",
      "slicePath": "frontend/slices/icon-picker",
      "convexPaths": [],
      "npm": [
        "@phosphor-icons/react@^2.1.10"
      ],
      "shadcn": [
        "popover",
        "dialog",
        "button",
        "input",
        "scroll-area",
        "tabs"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "icon",
        "emoji",
        "lucide",
        "phosphor",
        "picker",
        "twemoji",
        "notion",
        "notion-like",
        "responsive"
      ],
      "agentRecipe": "Run `npx rr add icon-picker` then `pnpm add @phosphor-icons/react`. parseIconValue() decodes; lucideValue() / phosphorValue() / withColor() build. Storage forms: `lucide:Name?c=hex` (outline) or `phosphor:Name?c=hex` (fill) or raw emoji. Add 'icon: v.string()' to Convex table — no migration needed for existing emoji + lucide fields. <IconPickerPopover> wraps any trigger (auto-flips, falls back to centered Dialog on tight viewports); <IconPickerInline> for sheets/dialogs. <DynamicIcon> renders from parsed value."
    },
    {
      "slug": "activity",
      "title": "Activity — public productivity log",
      "category": "data",
      "kind": "full",
      "version": "0.3.0",
      "description": "Public-facing weekly activity log. Lists user-facing activities grouped by ISO week with schema.org-friendly markup, designed to maximise SEO so the question 'what is <person> working on this week?' lands here. Convex-backed (schema + queries + unauthenticated mutations); MCP-friendly so AI workflows (Claude / GPT / custom agents) can append entries directly. All user-facing copy + per-category labels + date/time locale are prop-driven (English defaults). Lifted 2026-05-27 from rahmanef.com; 225-LOC view split into view + 2 sub-components + 4 lib helpers for the 200-LOC cap; Indonesian strings + custom primitives stripped; cross-slice auth import dropped (consumer wraps mutations).",
      "source": "rahmanef.com",
      "slicePath": "frontend/slices/activity",
      "convexPaths": [
        "convex/features/activity"
      ],
      "npm": [
        "convex@^1.17",
        "lucide-react@^0.400.0",
        "next@^15",
        "react@^18"
      ],
      "shadcn": [],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "activity",
        "productivity",
        "log",
        "now-page",
        "feed",
        "mcp",
        "seo",
        "personal-brand"
      ],
      "agentRecipe": "Run `npx rr add activity`. Spread `activityTables` into your root Convex schema. Wrap the unauthenticated `create`/`update`/`remove` `internalMutation`s with your auth model (see README Install section). Render `<ActivityFeed rows={await fetchQuery(api.activity.listPublic)} stats={await fetchQuery(api.activity.statsThisWeek)} />`. Override `copy`, `categoryLabels`, `locale` per consumer. MCP integration: map `activity_create` tool → your wrapped `create` mutation."
    },
    {
      "slug": "rate-limit",
      "title": "Rate Limit",
      "category": "infra",
      "kind": "backend",
      "version": "0.3.0",
      "description": "Convex-backed per-key request counter. Atomic check-and-increment via `consume` mutation; expired rows pruned by `_pruneExpired` internalMutation wired to a 5-min cron. Replaces single-replica in-memory Map so multi-replica Next deployments share buckets. Limits live in an in-code POLICY map keyed by namespace prefix (admin-login:<ip>, mcp:<ip>) — never caller-supplied; optional RATE_LIMIT_SERVER_KEY env gates anonymous calls. Lifted 2026-05-16 from rahmanef.com; hardened 2026-06-07.",
      "source": "rahmanef.com",
      "slicePath": "frontend/slices/rate-limit",
      "convexPaths": [
        "convex/features/rate_limit"
      ],
      "npm": [],
      "shadcn": [],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "infra",
        "rate-limit",
        "convex",
        "backend",
        "throttle"
      ],
      "agentRecipe": "Run `npx rr add rate-limit`. Compose `rateLimitTables` into root convex/schema.ts. Wire `internal.features.rate_limit.mutations._pruneExpired` into convex/crons.ts every 5 min. Add your namespace to the in-code POLICY map, then call `api.features.rate_limit.mutations.consume({ key, serverKey })` from server-side handlers — keep a fail-open wrapper so a Convex outage doesn't 503 the route. Set RATE_LIMIT_SERVER_KEY on the deployment to block anonymous consume calls."
    },
    {
      "slug": "testimonials",
      "title": "Testimonials",
      "category": "content",
      "kind": "backend",
      "version": "0.1.1",
      "description": "Quote/name/role rotator backend. Public `listAll` + `get` (no auth — testimonials are public), admin CRUD via `requireAdmin`, internal `seed` for one-shot bootstrap. Indexed by `order` so carousel/grid keeps stable rotation. Lifted 2026-05-16 from rahmanef.com; token-based admin gate swapped for rr `_shared/auth`.",
      "source": "rahmanef.com",
      "slicePath": "frontend/slices/testimonials",
      "convexPaths": [
        "convex/features/testimonials"
      ],
      "npm": [],
      "shadcn": [],
      "env": [
        {
          "name": "SUPER_ADMIN_EMAIL",
          "scope": "convex",
          "required": false
        }
      ],
      "peers": [
        {
          "slug": "convex-auth",
          "range": "^0.1",
          "reason": "requireAdmin uses getAuthUserId from @convex-dev/auth."
        }
      ],
      "providers": [],
      "tags": [
        "content",
        "testimonials",
        "convex",
        "backend",
        "marketing"
      ],
      "agentRecipe": "Run `npx rr add testimonials`. Compose `testimonialsTables` into root schema. Bootstrap via `npx convex run internal.features.testimonials.mutations.seed '{\"items\":[{\"quote\":\"...\",\"name\":\"...\",\"role\":\"...\",\"order\":1}]}'`. Render with `useQuery(api.features.testimonials.queries.listAll)`."
    },
    {
      "slug": "services",
      "title": "Services",
      "category": "content",
      "kind": "backend",
      "version": "0.1.1",
      "description": "Service offerings backend — title + summary + deliverables array + sort order. Public read, admin CRUD, internal seed. Pairs with a frontend services grid/list (consumer-side). Lifted 2026-05-16 from rahmanef.com; token-based admin gate swapped for rr `_shared/auth`.",
      "source": "rahmanef.com",
      "slicePath": "frontend/slices/services",
      "convexPaths": [
        "convex/features/services"
      ],
      "npm": [],
      "shadcn": [],
      "env": [
        {
          "name": "SUPER_ADMIN_EMAIL",
          "scope": "convex",
          "required": false
        }
      ],
      "peers": [
        {
          "slug": "convex-auth",
          "range": "^0.1",
          "reason": "requireAdmin uses getAuthUserId from @convex-dev/auth."
        }
      ],
      "providers": [],
      "tags": [
        "content",
        "services",
        "convex",
        "backend",
        "marketing",
        "agency"
      ],
      "agentRecipe": "Run `npx rr add services`. Compose `servicesTables` into root schema. Use `useQuery(api.features.services.queries.listAll)` from a server component / route to render service cards. CRUD via admin UI calling `create` / `update` / `remove` after `requireAdmin` passes."
    },
    {
      "slug": "create-your-mcp",
      "title": "Create Your MCP",
      "category": "ai",
      "kind": "full",
      "version": "0.2.0",
      "description": "Turn any rr-based app into an MCP server that ChatGPT custom apps, Claude.ai connectors, Cursor MCP, and other AI clients authenticate to. OAuth 2.1 + PKCE flow with code → bearer exchange, env-configured vendor-host allowlist, single-use codes, 1-year bearer tokens, scope-tagged tools, opaque error collapsing, constant-time token compare. Static MCP_API_KEY fallback for service-account / CI scripts. Sanitized 2026-05-16 from rahmanef.com's production MCP integration — vendor literals (chatgpt.com / OpenAI paths) replaced with MCP_OAUTH_ALLOWED_HOSTS + MCP_OAUTH_ALLOWED_PATH_PREFIXES env vars so the slice ships portable.",
      "source": "rahmanef.com",
      "slicePath": "frontend/slices/create-your-mcp",
      "convexPaths": [
        "convex/features/create_your_mcp"
      ],
      "npm": [],
      "shadcn": [],
      "env": [
        {
          "name": "MCP_API_KEY",
          "scope": "server",
          "required": false,
          "description": "Static bearer for service-account / CI access. Min 32 chars. Must match Convex env."
        },
        {
          "name": "MCP_OAUTH_ALLOWED_HOSTS",
          "scope": "convex",
          "required": false,
          "description": "CSV vendor domains for redirect_uri (chatgpt.com,claude.ai,cursor.sh)."
        },
        {
          "name": "MCP_OAUTH_ALLOWED_PATH_PREFIXES",
          "scope": "convex",
          "required": false,
          "description": "CSV path prefixes under allowed hosts (/aip/,/connector/,/oauth/)."
        },
        {
          "name": "NEXT_PUBLIC_SITE_URL",
          "scope": "next-public",
          "required": true,
          "description": "Public site origin for WWW-Authenticate challenge."
        }
      ],
      "peers": [
        {
          "slug": "convex-auth",
          "range": "^0.1",
          "reason": "requireAdmin uses getAuthUserId from @convex-dev/auth."
        }
      ],
      "providers": [],
      "tags": [
        "ai",
        "mcp",
        "oauth",
        "pkce",
        "chatgpt",
        "claude",
        "cursor",
        "convex",
        "integration"
      ],
      "agentRecipe": "Run `npx rr add create-your-mcp`. Compose `createYourMcpTables` into root schema. Move `slices/create-your-mcp/routes/mcp.route.ts` → `app/api/mcp/route.ts` and `oauth-token.route.ts` → `app/api/oauth/token/route.ts`. Set MCP_OAUTH_ALLOWED_HOSTS (CSV vendor domains). Mount `<McpAdminView />` at /admin/mcp. Connect ChatGPT/Claude/Cursor via the setup form rendered by the admin view."
    },
    {
      "slug": "contact-form-resend",
      "title": "Contact Form + Resend",
      "category": "integrations",
      "kind": "full",
      "version": "0.1.0",
      "description": "Contact form posting to Resend email API. Server Action + Zod input validation. Convex mutation for storage + Resend send.",
      "source": "cescadesigns",
      "slicePath": "template-base/frontend/slices/contact-form-resend",
      "convexPaths": [],
      "npm": [
        "resend@^4.0.0",
        "framer-motion@^11.0.0"
      ],
      "shadcn": [
        "card",
        "button",
        "input",
        "label",
        "textarea"
      ],
      "env": [
        {
          "name": "RESEND_API_KEY",
          "scope": "convex",
          "required": true
        }
      ],
      "peers": [
        {
          "slug": "convex-auth",
          "range": "^0.1",
          "reason": "Optional — anonymous submission works without auth."
        }
      ],
      "providers": [],
      "tags": [
        "form",
        "email",
        "resend",
        "convex"
      ],
      "agentRecipe": "Run `npx rr add contact-form-resend`. Wire contactMessages.send mutation in convex/. Server emails via Resend from form@yourdomain.com. Always validate inputs with Zod or v.* server-side. Anonymous allowed."
    },
    {
      "slug": "admin",
      "title": "Admin — generic shell + composed console",
      "category": "infra",
      "kind": "full",
      "version": "0.2.1",
      "description": "Access-gated admin surfaces behind one slug, in two variants — each pulls ONLY its own convex backend (per-variant convex gating). shell: a HEADLESS minimal generic admin shell — a titled landing region + a portable buildAdminStats(opts) nav-from-registry factory (consumer supplies a SliceRegistryAdapter + queryTable reader) over convex/features/admin; superadmin gate via SUPER_ADMIN_EMAIL. console: the composed admin panel distilled from ~15 project admin panels — a gated two-column shell (AdminConsole) over a 26-section registry (ADMIN_CONSOLE_SECTIONS: observability / identity / ai / content / commerce / config) that mounts OTHER rr slices via a consumer-supplied `components` map (users→user-management, roles→rbac-roles, ai→ai-admin, tenants→platform-admin) plus 5 owned gap sections (Analytics, Audit-log, Nav config, SEO health, Leads/CRM) over convex/features/admin_console (ac_leads + ac_nav_items); gate injected, PLATFORM_ADMIN_EMAILS allowlist. Install one with `npx rr add admin shell|console`, or both with `npx rr add admin`. NOT the multi-tenant control plane — that's the separate `platform-admin` slice (the console's `tenants` section provider).",
      "source": "rahmanef63/resource-site",
      "slicePath": "frontend/slices/admin",
      "convexPaths": [
        "convex/features/admin",
        "convex/features/admin_console"
      ],
      "npm": [],
      "shadcn": [
        "badge",
        "button",
        "card",
        "input",
        "progress",
        "scroll-area",
        "select",
        "sheet",
        "table",
        "textarea"
      ],
      "env": [
        {
          "name": "SUPER_ADMIN_EMAIL",
          "scope": "convex",
          "required": false,
          "description": "shell variant — single super-admin gate."
        },
        {
          "name": "PLATFORM_ADMIN_EMAILS",
          "scope": "convex",
          "required": false,
          "description": "console variant — comma-separated platform-admin allowlist."
        }
      ],
      "peers": [
        {
          "slug": "convex-auth",
          "range": "^0.1",
          "reason": "requireAdmin gate uses convex-auth identity."
        },
        {
          "slug": "rbac-roles",
          "range": "^0.1",
          "reason": "console section gates are permission tokens resolved by rbac-roles."
        }
      ],
      "providers": [],
      "tags": [
        "infra",
        "admin",
        "console",
        "shell",
        "dashboard",
        "composition",
        "rbac",
        "access-gate",
        "registry"
      ],
      "agentRecipe": "Run `npx rr add admin` for both, or `npx rr add admin shell` / `console` for one — each variant pulls only its own convex backend. shell: mount <AdminPage labels={...} /> + call buildAdminStats({ sliceRegistry, queryTable }) in convex/features/admin/query.ts; lock down with SUPER_ADMIN_EMAIL. console: mount <AdminConsole access={useAdminAccess()} components={{ users: <UsersPanel/>, ... }} /> — owned sections (analytics/audit-log/nav-config/seo-health/leads) render as-is, map each reuse section id to the panel from the peer slice you installed; compose adminConsoleTables into convex/schema.ts and front ac_leads.create with rate-limit; gate via PLATFORM_ADMIN_EMAILS.",
      "variants": {
        "default": "console",
        "items": [
          {
            "id": "shell",
            "title": "Shell",
            "description": "Minimal generic admin shell (titled card + buildAdminStats).",
            "convex": [
              "convex/features/admin"
            ]
          },
          {
            "id": "console",
            "title": "Console",
            "description": "Composed access-gated 26-section console mounting other rr slices.",
            "convex": [
              "convex/features/admin_console"
            ]
          }
        ]
      }
    },
    {
      "slug": "platform-admin",
      "title": "Platform Admin — Multi-Tenant Control Plane",
      "category": "infra",
      "kind": "full",
      "version": "0.2.0",
      "description": "Multi-tenant SaaS control plane. Workspace lifecycle ops (list/delete/cascade), per-tenant tier presets (gates + quota), KPI dashboard grid. Consumer-domain bits injected via adapter props (tenantTablesAdapter / tierPresets / kpiSources). Contract-only scaffold; canonical implementation lands via /rr-send from superspace. See docs/contract-negotiations-2026-05-15.md §4.",
      "source": "rahmanef63/resource-site",
      "slicePath": "frontend/slices/platform-admin",
      "convexPaths": [],
      "npm": [],
      "shadcn": [],
      "env": [
        {
          "name": "PLATFORM_ADMIN_EMAILS",
          "scope": "convex",
          "required": true,
          "description": "Comma-separated list of platform admin email addresses."
        }
      ],
      "peers": [
        {
          "slug": "convex-auth",
          "range": "^0.1",
          "reason": "Actor identity for audit + tier-set ops."
        },
        {
          "slug": "audit-log",
          "range": "^0.2",
          "reason": "padmin_audit table feeds through audit-log TenantAdapter."
        },
        {
          "slug": "dashboard-shell",
          "range": "^0.1",
          "reason": "Control-plane panels mount inside the dashboard-shell app chrome — no chrome of its own."
        }
      ],
      "providers": [],
      "tags": [
        "infra",
        "admin",
        "multi-tenant",
        "saas",
        "platform"
      ],
      "agentRecipe": "Run `npx rr add platform-admin`. Contract-only scaffold. Wait for superspace /rr-send platform-admin before adopting. Distinct from per-instance `admin` slug."
    },
    {
      "slug": "audit-log",
      "title": "Audit Log — Workspace Events",
      "category": "infra",
      "kind": "backend",
      "version": "0.3.0",
      "description": "Workspace-scoped audit event recorder. Canonical logAuditEvent helper for mutations + actions; supports entity tracking, before/after diff, IP/user-agent capture.",
      "source": "rahmanef63/resource-site",
      "slicePath": "frontend/slices/audit-log",
      "convexPaths": [
        "convex/features/audit-log"
      ],
      "npm": [],
      "shadcn": [],
      "env": [],
      "peers": [
        {
          "slug": "convex-auth",
          "range": "^0.1",
          "reason": "Event actor resolved via authenticated user."
        }
      ],
      "providers": [],
      "tags": [
        "infra",
        "audit",
        "compliance",
        "logging"
      ],
      "agentRecipe": "Run `rr add audit-log`. Import logAuditEvent from convex/_shared/auditLogger.ts and call inside every workspace-scoped mutation with { action, workspaceId, entityType, entityId, before?, after? }."
    },
    {
      "slug": "comments",
      "title": "Comments — Threaded",
      "category": "content",
      "kind": "full",
      "version": "0.3.0",
      "description": "Polymorphic-target threaded comments. Consumer picks `TargetRef = { kind, id, subId? }` (e.g. page+block, blog+slug, task+id). Reply nesting is real: `parentId` end-to-end + `buildThread(flat) → CommentNode[]` tree (oldest-first, orphan-safe). Renderless <CommentsThread> + <CommentsAnchor> wrappers; useComments(bindings, opts) returns items + `tree` + openCount + CRUD + forbiddenWords guard. Adapter pattern — see contract-negotiations §1.",
      "source": "rahmanef63/resource-site",
      "slicePath": "frontend/slices/comments",
      "convexPaths": [
        "convex/features/comments"
      ],
      "npm": [],
      "shadcn": [
        "button",
        "textarea",
        "avatar"
      ],
      "env": [],
      "peers": [
        {
          "slug": "convex-auth",
          "range": "^0.1",
          "reason": "Comment author identity from convex-auth."
        }
      ],
      "providers": [],
      "tags": [
        "content",
        "social",
        "comments",
        "threaded",
        "annotations"
      ],
      "agentRecipe": "Run `rr add comments`. Wire Convex bindings ({ list, create, update, resolve, remove }) then use <CommentsThread target={{ kind, id, subId? }} bindings={bindings} forbiddenWords={[...]}>{render-prop}</CommentsThread> OR <CommentsAnchor target=... bindings=... pathMap={(t)=>...}>. v0.2.0 polymorphic — pick `kind` literal per host domain."
    },
    {
      "slug": "seo",
      "title": "SEO — AI Metadata Generator",
      "category": "content",
      "kind": "full",
      "version": "0.3.0",
      "description": "Service slice for SEO metadata generation — Anthropic-backed action with per-user 24h cost guard + portable persona prop. No public route. Backend exposes generate + generateAndApply mutations gated by requireAdmin; consumers inject brand voice via the personaContext arg (or buildSeoSystemPrompt factory).",
      "source": "rahmanef63/resource-site",
      "slicePath": "frontend/slices/seo",
      "convexPaths": [
        "convex/features/seo"
      ],
      "npm": [],
      "shadcn": [],
      "env": [
        {
          "name": "ANTHROPIC_API_KEY",
          "scope": "server",
          "required": true
        }
      ],
      "peers": [
        {
          "slug": "convex-auth",
          "range": "^0.1",
          "reason": "Cost guard + requireAdmin gates use convex-auth user identity."
        }
      ],
      "providers": [],
      "tags": [
        "content",
        "seo",
        "ai",
        "anthropic",
        "metadata-generator"
      ],
      "agentRecipe": "Run `rr add seo`. Call seo.generate from server actions or admin mutations with `personaContext` describing your brand voice (or rely on the generic default). Cost guard rate-limits per-user within 24h via callsInWindow query."
    },
    {
      "slug": "publisher-clean-html",
      "title": "Publisher — clean HTML",
      "category": "content",
      "kind": "ui",
      "version": "0.1.0",
      "description": "A pure render-to-clean-HTML engine harvested from the Instatic CMS publisher, decoupled from its host caching / loops / visual-components / Layer-C islands. publishPage(tree, registry, options) walks a generic node tree bottom-up: render children, escape every prop by its schema-declared control type (url -> safe-URL, richtext -> DOMPurify, svg -> SVG profile, else HTML-escape), dedup CSS by moduleId (~60-80% shrink), splice author classes + inline styles onto each rendered root, then assemble <!DOCTYPE> + reset + framework + module CSS + a deterministic (sorted) CSP plan. Bring your own ModuleRegistry (each module is a pure render(props, children) -> { html, css? }). Security spine: HTML escape + safe-URL, CSS-value guard (expression()/{}/</), </style RAWTEXT neutraliser, and an injectable DOMPurify seam (configureRichtextSanitizer) that fails closed — without a runtime, richtext strips all tags and SVG returns empty. Stateless, env-free, ZERO npm deps, no Convex. Ships a PublishPreview iframe-srcdoc pane. A Wave-1 leaf of the feature-harvest ULTRAPLAN; a dependency of the planned visual-page-canvas.",
      "source": "rahman-resources",
      "slicePath": "frontend/slices/publisher-clean-html",
      "convexPaths": [],
      "npm": [],
      "shadcn": [],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "content",
        "publisher",
        "html",
        "static-export",
        "sanitization",
        "csp",
        "css-dedup",
        "render"
      ],
      "agentRecipe": "Run `npx rr add publisher-clean-html`. Build a registry: createModuleRegistry([{ id: 'base.body', render: (_p, kids) => ({ html: kids.join('') }) }, { id: 'demo.h', schema: { text: { type: 'text' } }, render: (p) => ({ html: `<h1>${p.text}</h1>`, css: 'h1{font-size:1.5rem}' }) }]). Tree = { rootNodeId, nodes: { [id]: { id, moduleId, props?, children?, classIds?, inlineStyles?, hidden? } } }. const { html } = publishPage(tree, registry, { title, cssEmission: 'inline' }). Preview: <PublishPreview html={html} />. Enable rich HTML/SVG by calling configureRichtextSanitizer(DOMPurify) once — without it, richtext/svg props fail closed (strip/empty). Props escape by schema control type, not key name."
    },
    {
      "slug": "content-loops",
      "title": "Content Loops",
      "category": "content",
      "kind": "ui",
      "version": "0.1.0",
      "description": "A data-source-driven repeater harvested from the Instatic CMS base.loop engine, decoupled from its publisher / page-tree / entryStack machinery into a plain React slice. Register pluggable LoopEntitySource backends (each declares display fields + an async fetch returning { items, totalItems }); drop <ContentLoop source|sourceId filters orderBy variants={[A, B]} /> to render one component per item, round-robining items across variants so alternating / featured layouts need no per-item branching. Ships a namespaced source registry (ids must be 'ns.name', so consumer sources can't shadow each other), createMockLoopSource for env-free previews + tests, and none/infinite pagination via useLoopPagination (a shadcn Load more button accumulates pageSize chunks). LoopItem.fields is a generic resolved-value bag — variants read item.fields.title directly, no second lookup. UI-only: no Convex tables shipped; point a source's fetch at Convex/REST when you have a backend. First slice of the feature-harvest ULTRAPLAN (docs/feature-harvest) and a dependency of the planned site-templates-engine + visual-page-canvas.",
      "source": "rahman-resources",
      "slicePath": "frontend/slices/content-loops",
      "convexPaths": [],
      "npm": [],
      "shadcn": [
        "button"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "content",
        "loop",
        "repeater",
        "list",
        "data-source",
        "pagination",
        "variants"
      ],
      "agentRecipe": "Run `npx rr add content-loops`. Env-free demo: createMockLoopSource() then <ContentLoop source={s} pagination='infinite' pageSize={6} variants={[CardA, CardB]} /> — variants round-robin (item i -> variants[i % n]). Real source: implement LoopEntitySource { id: 'blog.posts' (namespaced 'ns.name'), fields, async fetch({ filters, orderBy, direction, limit, offset }) returns { items, totalItems } }, call loopSourceRegistry.registerOrReplace(source), then <ContentLoop sourceId='blog.posts' variants={[...]} />. item.fields holds RESOLVED values — resolve media/author inside fetch."
    },
    {
      "slug": "markdown",
      "title": "Markdown — page container with CRUD tabs + diagrams",
      "category": "content",
      "kind": "ui",
      "version": "0.3.1",
      "description": "Markdown (.md) page container with optional CRUD surfaces. <MarkdownPage content={md} tabs={['read','write','review']}/> — Read renders rich text (headings, lists, todo, GitHub-style callouts, fenced code, KaTeX, tables, images, <details> toggles, inline marks); Write is a raw-source editor with snippet toolbar + live preview; Review overlays block-anchored comments (add/resolve, controlled via onAddComment/onResolveComment or internal fallback). Fenced ```mermaid blocks render as SVG diagrams (dynamic-imported mermaid) and ```chart blocks as recharts bar/line/area/pie from a JSON spec. Self-contained: ships its own parser (parseMarkdown → MdNode[]) + inline renderer, no notion runtime dependency. Sync is by shared grammar: the notion cluster's blocksToMarkdown / markdownToBlocks bridge (@notion/shared/lib/markdown) emits/consumes the exact same markdown this slice parses, so anything readable in the notion block page is readable here and vice-versa. No store, no Convex — comments CRUD is consumer-wired callbacks.",
      "source": "rahman-resources",
      "slicePath": "frontend/slices/markdown",
      "convexPaths": [],
      "npm": [
        "katex@^0.16",
        "mermaid@^11",
        "recharts@^3",
        "lucide-react@^0.400.0"
      ],
      "shadcn": [
        "button",
        "tabs",
        "textarea"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "content",
        "markdown",
        "reader",
        "editor",
        "review",
        "comments",
        "mermaid",
        "chart",
        "rich-text",
        "docs",
        "notion-sync"
      ],
      "agentRecipe": "Run `npx rr add markdown`. Read-only: `<MarkdownReader content={md}/>`. Full surface: `<MarkdownPage content={md} tabs={['read','write','review']} onContentChange={save} comments={list} onAddComment={add} onResolveComment={resolve}/>` (omit callbacks for internal-state demo mode). Diagrams: fence ```mermaid; charts: fence ```chart with { type: bar|line|area|pie, data: [...] }. To bridge from the notion editor call `blocksToMarkdown(page.blocks)` from `@notion/shared/lib/markdown`; reverse with `markdownToBlocks(md)`."
    },
    {
      "slug": "notion-app",
      "title": "Notion App — Block Editor",
      "category": "content",
      "kind": "full",
      "version": "1.1.1",
      "description": "Nested vertical slice (slice-of-slices) housing the full notion-page-clone block editor. Mount <PageEditor pageId/> inside <EditorAdapterProvider adapter/> — with `{}` it is a working plain-text/markdown block editor (slash menu, markdown triggers `# - > [] etc.`, dnd-kit drag with column layouts, per-block toolbar with turn-into/color/duplicate, per-block undo, paste-markdown import); host capabilities light up per optional adapter: data (block+page CRUD), selection (multi-select), comments (per-block popover), ai (Ask-AI panel), database (render + picker), mention (@-typeahead), page (nav/uploads/covers). Cluster-private shared layer under @notion/* — vendored block/page/database model, uid, inline markdown, page→md/html export. Pure convex block helpers (_blocks/_blockOps, unit-tested) ship in convex/features/notion. Same markdown grammar as the standalone `markdown` slice (blocksToMarkdown/markdownToBlocks bridge).",
      "source": "notion-page-clone",
      "slicePath": "frontend/slices/notion-app",
      "convexPaths": [
        "convex/features/notion"
      ],
      "npm": [
        "sonner@^2",
        "@dnd-kit/core@^6",
        "@dnd-kit/sortable@^10",
        "@dnd-kit/utilities@^3",
        "katex@^0.16"
      ],
      "shadcn": [
        "button",
        "dropdown-menu",
        "popover",
        "separator",
        "checkbox",
        "input",
        "switch",
        "skeleton"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "content",
        "notion",
        "editor",
        "block-editor",
        "rich-text",
        "slash-menu",
        "drag-drop",
        "adapter-seam"
      ],
      "agentRecipe": "Run `npx rr add notion-app`. Wire the `@notion/*` path alias to `./slices/notion-app/*` in tsconfig. Minimal mount: `<EditorAdapterProvider adapter={{ data }}><PageEditor pageId={id}/></EditorAdapterProvider>` where `data` implements EditorDataAdapter (block+page CRUD over your store — see lib/dataAdapter.ts; a localStorage reference impl lives in the rr preview). Add capabilities incrementally: `selection` for multi-select, `comments` for per-block threads, `database.renderDatabase` to mount your database renderer inside database blocks, `mention.search` for @-typeahead, `page.navigateToPage`/`uploadFile` for nav + media. Convex hosts: copy convex/features/notion (_blocks/_blockOps are pure, unit-tested array ops) and keep handlers thin."
    },
    {
      "slug": "sections",
      "title": "Sections — composable marketing/landing sections",
      "category": "content",
      "kind": "ui",
      "version": "0.4.0",
      "description": "Canonical landing-page composition slice — replaces the former standalone hero / cta / pricing-page / faq-section / feature-grid / testimonials-grid / blog-section / portfolio-section / changelog-feed slices (all merged here as `kind` variants in v0.2.0). Ships a pure reducer (v0.4.0: LANDING_UPSERT auto-shifts sibling `order` to keep positions unique; LANDING_DELETE closes the gap) + LandingProvider store adapter + admin LandingView/LandingEditorView built on the shared CRUD primitives, plus a per-section LandingSectionShell (background image + custom Tailwind className overlay + scroll-reveal). NEW in v0.4.0: a `sections/` library of config-driven public renderers (StatsSection, TestimonialsSection, FaqSection, PricingSection, NewsletterSection, CustomSection) that read `LandingSection.config` JSON merged over template defaults — content stays dashboard-controlled without per-template renderer code; plus `parse-config` helpers (parseConfigBadge/parseConfigField) and `sections/config` guards (parseConfigObject, cfg*). Sections carry { kind, order, title, subtitle, enabled, imageUrl, imageRatio, bgImageUrl, className, config (JSON) } with up/down reorder arrows. Lifted from the _templates fleet `_shared/landing` (2026-06-11) — the 8 standalone templates ship a byte-similar copy; this rr slice is the SSOT. Used by all 7 rr website templates.",
      "source": "rahman-resources (lifted from _templates fleet)",
      "slicePath": "frontend/slices/sections",
      "convexPaths": [],
      "npm": [
        "lucide-react@^0.400.0",
        "embla-carousel-autoplay@^8.6.0",
        "next@^15"
      ],
      "shadcn": [
        "accordion",
        "badge",
        "button",
        "card",
        "carousel",
        "dialog",
        "input",
        "label",
        "select",
        "switch",
        "table",
        "textarea"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "admin",
        "landing",
        "cms",
        "sections",
        "crud",
        "renderer"
      ],
      "agentRecipe": "Run `npx rr add sections`. Fold `landingReducer` into your root reducer (cases LANDING_UPSERT + LANDING_DELETE), seed State.landingSections with `defaultLandingSections()`, wrap your StoreProvider with `<LandingProvider value={adapter}/>` where adapter maps {items, publicBase, adminBase, create, update, remove} from your dispatch. Mount `<LandingView/>` at `/admin/landing` and `<LandingEditorView id={params.id}/>` at `/admin/landing/[id]`. In HomePage iterate `state.landingSections.filter(s => s.enabled).sort((a,b) => a.order - b.order)` and render each inside `<LandingSectionShell section={s}>`; for stats/testimonials/pricing/faq/newsletter/custom kinds drop in the shipped `<StatsSection/>` etc. (they read `section.config` JSON over your template defaults), or map the remaining kinds (hero/features/blog/etc.) to your own renderer. Use `parseConfigBadge(section.config)` for a section badge. Requires the template-base shared surface that ships in every rr website template: `@/components/templates/_shared/motion` (Reveal/Stagger/CountUp/Marquee/useInView — the motion-kit primitives), `@/components/templates/_shared/ui/section-head`, and `@/components/templates/_shared/crud/*`. Sections also use shadcn accordion/card/carousel + embla-carousel-autoplay."
    },
    {
      "slug": "motion-kit",
      "title": "Motion Kit — scroll reveals, carousel, accordion, micro-interactions",
      "category": "ui",
      "kind": "ui",
      "version": "0.1.0",
      "description": "Zero-dependency scroll-motion layer (IntersectionObserver + CSS) plus an embla carousel and a radix accordion, packaged so any page gets tasteful entrance animations without pulling in a motion library. Ships Reveal (fade-up/fade/fade-left/fade-right/zoom), Stagger (incremental per-child reveal for grids/lists), CountUp (rAF count-to-value with locale formatting; integers), Marquee (infinite logo/brand strip with hover-pause + edge fade), and the useInView hook behind them; plus Carousel (embla, optional Autoplay plugin) and Accordion (radix). All reveal + keyframe motion is gated behind prefers-reduced-motion. Consumers append globals-motion.css to their app/globals.css for the [data-reveal] transitions + accordion/marquee/blob keyframes. Lifted 2026-06-10 from the _templates fleet `_shared/motion` copy — the 8 standalone website templates already ship a byte-identical copy; this rr slice is the SSOT so future scaffolds get it via `npx rr add motion-kit`. Pairs with landing-sections (its renderers consume these primitives).",
      "source": "rahman-resources (lifted from _templates fleet)",
      "slicePath": "frontend/slices/motion-kit",
      "convexPaths": [],
      "npm": [
        "embla-carousel-react@^8.6.0",
        "embla-carousel-autoplay@^8.6.0",
        "radix-ui@^1.4.3",
        "lucide-react@^0.400.0"
      ],
      "shadcn": [
        "button"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "ui",
        "motion",
        "animation",
        "scroll",
        "reveal",
        "carousel",
        "accordion",
        "marquee",
        "countup",
        "embla"
      ],
      "agentRecipe": "Run `npx rr add motion-kit`. Append the contents of `globals-motion.css` to your `app/globals.css` (after `@import \"tailwindcss\";`) — without it `data-reveal` elements stay static and the accordion snaps. Then import from `@/features/motion-kit`: `<Reveal variant=\"fade-up\">`, `<Stagger itemClassName=\"h-full\">{cards}</Stagger>` for grids, `<CountUp value={4800} />` (integers), `<Marquee speed={32}>{logos}</Marquee>`. Carousel: pair with `Autoplay` from embla-carousel-autoplay. Any component consuming a passed render/icon fn AND these hooks must be `\"use client\"`. Hover-lift convention: `transition-[translate,box-shadow] duration-300 hover:-translate-y-1 hover:shadow-lg`."
    },
    {
      "slug": "storefront-checkout",
      "title": "Storefront Checkout — guest cart + checkout composition",
      "category": "content",
      "kind": "ui",
      "version": "0.2.0",
      "description": "Guest-friendly shopping cart for catalog storefronts. CartProvider holds items in React context with localStorage persistence (anonymous buyers keep their cart across reloads, zero backend). CartWidget is a header trigger with live count badge opening a slide-over Sheet: per-item qty steppers, remove, subtotal, checkout CTA to a host route. CheckoutSummary renders the order panel on the checkout page. Props-driven R3 — no convex/react anywhere; the host resolves a NUMERIC price per catalog item before add() and MUST re-price every line server-side when placing the order (client subtotal is display-only, never the charge). Proven end-to-end on wirausaha-os: catalog → cart → server-priced placeOrder action → DOKU Direct instructions → webhook flips paid (reactive). Pairs with doku-payment ≥0.2 (guest checkout: optional userId + buyer contact, key-guarded actions, guest-readable status query) or midtrans-payment.",
      "source": "wirausaha-os guest-checkout build-out 2026-06-10",
      "slicePath": "frontend/slices/storefront-checkout",
      "convexPaths": [],
      "npm": [],
      "shadcn": [
        "badge",
        "button",
        "card",
        "separator",
        "sheet"
      ],
      "env": [],
      "peers": [
        {
          "slug": "payment",
          "range": "^0.4",
          "reason": "Optional payment step — checkout page composes DokuDirectForm + DokuPaymentInstructions (or swap midtrans-payment)."
        }
      ],
      "providers": [],
      "tags": [
        "ecommerce",
        "cart",
        "checkout",
        "guest",
        "storefront",
        "payment",
        "localStorage",
        "sheet"
      ],
      "agentRecipe": "Run `npx rr add storefront-checkout`. Wrap your public layout once with `<CartProvider storageKey=\"my-shop-cart\">` and mount `<CartWidget checkoutHref=\"/checkout\" />` in the header extras. On product surfaces call `useCart().add({ slug, name, price, priceLabel, emoji })` with a host-resolved NUMERIC price. Build a /checkout route composing `<CheckoutSummary />` + a payment form (doku-payment's DokuDirectForm): its onSubmit calls YOUR Convex place-order action which re-prices each {slug, qty} from your catalog table server-side, generates an unguessable orderId, calls api.features.payment.actions.doku.createDirectPayment, records your domain order row, and returns { ok, orderId, instructions, expiresAt } ({ ok:false, notice } when DOKU creds are unset — surface it in the form and offer a contact fallback). After success render DokuPaymentInstructions + reactive status via api.features.payment.query.getOrderByOrderId. Reference: template-wirausaha-os convex/checkout.ts + slices/checkout/CheckoutPage.tsx."
    },
    {
      "slug": "theme-presets",
      "title": "Theme Presets — unified switcher with bundled tweakcn registry",
      "category": "ui",
      "kind": "ui",
      "version": "0.4.0",
      "description": "Single unified theme controller for next-themes apps. ThemePresetSwitcher ships a Palette-icon Popover trigger with three stacked sections: (1) sticky light/dark/system mode tabs, (2) sticky preset-count row with a Default reset button, (3) scrollable color-preset list grouped by mood (Profesional / Bold / Hangat / Artistik / Gelap + Lainnya). Hover-to-preview + click-to-commit + restore-on-close semantics. ThemePresetProvider context wraps state so deeply-nested consumers read via useThemePreset() instead of mounting the switcher directly. ThemeColorSync wrapper enables live tweakcn-CSS-variable preview on routes that need it. Tweakcn registry (~30 curated presets after HIDDEN_PRESETS filter drops Doom 64 / Cyberpunk / Neo Brutalism / Bubblegum / Candyland / Pastel Dreams) ships inside the slice as registry-data.json and loads lazily via dynamic import — code-splits into its own chunk, zero consumer public/ setup, no network roundtrip to a hosted URL. localStorage key `host:theme-preset` (rename via slice fork). CK-1F (2026-05-23) — collapsed prior TweakcnSwitcher + ThemePicker + phantom `theme-preset-switcher` catalog entry into this single component.",
      "source": "CareerPack + notion-page-clone",
      "slicePath": "frontend/slices/theme-presets",
      "convexPaths": [],
      "npm": [
        "next-themes@^0.4.6"
      ],
      "shadcn": [
        "button",
        "popover"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "ui",
        "theme",
        "tweakcn",
        "color",
        "preset",
        "switcher",
        "popover",
        "next-themes",
        "notion-like"
      ],
      "agentRecipe": "Run `npx rr add theme-presets` (registry-data.json ships inside the slice — no separate public/ copy step). Wrap your tree once with `<ThemePresetProvider>` (inside next-themes' ThemeProvider). Mount `<ThemePresetSwitcher />` anywhere in your header / sidebar / settings — one component handles light/dark/system + preset palette. Wrap dashboard with `<ThemeColorSync>` if you need live tweakcn variable preview on inner routes. Deeply-nested consumers read state via `useThemePreset()` (returns `{ presetName, registry, setPreset, preview, restore, isReady }`). For lower-level access: `applyTweakcnPreset(name)`, `previewTweakcnPreset(name)`, `restoreTweakcnPreset()`, `groupTweakcnPresets(items)`, `tweakcnSwatches(preset)` all exported from `@/features/theme-presets`. To rename localStorage key, fork `STORAGE_KEY` in `lib/tweakcn/types.ts`."
    },
    {
      "slug": "site-setup-wizard",
      "title": "Site Setup Wizard — first-run site setup",
      "category": "ui",
      "kind": "ui",
      "version": "0.2.0",
      "description": "Post-claim onboarding wizard for clone-to-own templates, graduated from the headless template surface (2026-06-06). Multi-step card flow (Identitas / Branding / Konten / Selesai) that stores ALL site config in the host backend via a props-driven save callback — a non-coder configures their site with zero code. Branding step ships a readable shadcn Select theme-preset picker (color swatches per preset + grouped headers + live preview callback — replaces the white-on-white native select), brand color quick-chips, light/dark/system default mode, logo/favicon upload via injected ImageField, and optional Analytics ID. Identity step hints invalid email format. 'Lewati setup' marks onboarded without fields and reverts any browsed-but-unsaved preset. Props-driven (R3): no convex/react import — host wires settings.upsert / seed.seedSample / setup.status into props; pairs naturally with the theme-presets slice (registry + tweakcnSwatches + previewTweakcnPreset) but works with any theme system or none.",
      "source": "personal-brand-os",
      "slicePath": "frontend/slices/site-setup-wizard",
      "convexPaths": [],
      "npm": [],
      "shadcn": [
        "button",
        "card",
        "input",
        "label",
        "progress",
        "select"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "ui",
        "onboarding",
        "wizard",
        "setup",
        "first-run",
        "branding",
        "theme",
        "clone-to-own",
        "templates"
      ],
      "agentRecipe": "Run `npx rr add site-setup-wizard`. Show from your admin gate when `setup.status().onboarded === false`: `<OnboardingWizard onDone={...} save={(f) => settingsUpsert(f)} seedSample={() => seedSample({})} seeded={status?.seeded} ImageField={ImageField} presetOptions={presets} onPresetPreview={(n) => preview(n)} />`. `save` receives Partial<OnboardingFields> + `markOnboarded: true` — back it with a `settings.upsert` mutation that patches only provided fields. Theme bridge (optional): with the theme-presets slice installed build `presetOptions` from `groupTweakcnPresets(registry.items)` + `tweakcnSwatches(p)` and pass `useThemePreset().preview` as `onPresetPreview` — the picker then live-previews while the user browses and `Lewati setup` reverts via `onPresetPreview(null)`. Omit `presetOptions` to hide the picker entirely; omit `ImageField` to hide logo/favicon upload. Full wiring recipe in the slice's HOST-SETUP.md."
    },
    {
      "slug": "file-upload",
      "title": "File Upload — pluggable upload + URL resolver with storage-adapter contract",
      "category": "data",
      "kind": "ui",
      "version": "0.3.0",
      "description": "Host-pluggable file upload + URL resolution. Ships <FileUploadButton>, <FileChip>, useFileUpload(), useFileUrl() — all reading from a FilesAdapter the host wires via <FilesAdapterProvider>. Bundled localStorage demo adapter stores blobs as data URLs (small files only). Drop in your own adapter for Convex / S3 / GCS / R2. The slice itself has zero backend coupling, proving the storage-adapter pattern for the rest of the open-silong blocked-pending-adapter wave (cover, workspace-io, templates, …).",
      "source": "notion-page-clone",
      "slicePath": "frontend/slices/file-upload",
      "convexPaths": [],
      "npm": [],
      "shadcn": [
        "button"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "data",
        "upload",
        "files",
        "storage",
        "adapter",
        "portable",
        "notion-like"
      ],
      "agentRecipe": "Run `npx rr add file-upload`. Wrap your tree with `<FilesAdapterProvider adapter={...}>` — pass `useLocalStorageFilesAdapter()` for a quick demo or implement `FilesAdapter` (upload + remove + useUrl) against your backend. Then drop `<FileUploadButton onUploaded={...}>` anywhere; pair with `<FileChip fileRef={...}>` for rendered chips. Hooks: `useFileUpload()` returns `{upload, uploading, progress, removeFromStorage}`; `useFileUrl(storageId)` resolves to a fetchable URL (Convex adapter uses useQuery for live invalidation; demo reads localStorage synchronously). To wire S3: implement the FilesAdapter interface with presigned URLs + DELETE; the slice doesn't care which backend you pick."
    },
    {
      "slug": "selection",
      "title": "Selection — marquee multi-select + bulk actions",
      "category": "ui",
      "kind": "ui",
      "version": "0.2.0",
      "description": "Framework-agnostic multi-selection for any vertical list (Notion-style blocks, table rows, cards). Hold-and-drag on empty space draws a rubber-band rectangle — AutoCAD-style: drag RIGHT selects only fully-enclosed items (solid ring), drag LEFT selects anything the rectangle touches (dashed green ring). Click an item's edge to select (Shift = range, Cmd/Ctrl = toggle). Selecting activates items with a ring + data-block-selected attribute. Backspace/Delete bulk-deletes, Escape and click-outside clear, and a floating count toolbar offers Delete/Clear. SelectionProvider owns only the id set — the host owns the data via onBulkDelete(ids). Pairs with notion-shell (the notion-clone template wires it onto the editor); lifted from notion-page-clone's block-selection slice.",
      "source": "notion-page-clone",
      "slicePath": "frontend/slices/selection",
      "convexPaths": [],
      "npm": [],
      "shadcn": [],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "ui",
        "selection",
        "marquee",
        "rubber-band",
        "multi-select",
        "bulk",
        "notion",
        "blocks",
        "list"
      ],
      "agentRecipe": "Run `npx rr add selection`. Zero deps (react-dom only). Wrap your list area in `<SelectionProvider onBulkDelete={(ids) => removeMany(ids)}>`, give the surface a `position: relative` div with a ref, drop `<SelectionMarquee containerRef={ref} />` inside it, and wrap each item in `<SelectableBlock id={item.id} orderedIds={allIds}>…</SelectableBlock>`. Hold-drag on empty space to rubber-band: drag RIGHT = window (only fully-enclosed, solid ring), drag LEFT = crossing (anything touched, dashed green). Edge-click an item to pick it (Shift = range, Cmd/Ctrl = toggle). Backspace/Delete bulk-deletes (focus outside a contentEditable), Escape + click-outside clear, floating `N selected · Delete · Clear` toolbar. Read state anywhere via `useSelection()`. The slice owns ONLY the id set — you own the data + the delete. Works on table rows / cards too, not just notion blocks."
    },
    {
      "slug": "notion-ui",
      "title": "Notion UI — page editor · database · sidebar primitives",
      "category": "ui",
      "kind": "ui",
      "version": "0.24.0",
      "description": "The pure, props-driven Notion-clone primitives suite behind one slug, over one shared domain-type model (Block / Page / Property / Database / DbView …). page: the page + block editor (NotionPage / NotionHeader / NotionBlock, SlashMenu, block renderers, inline-markdown decorator, built-in code (highlight.js) + equation (KaTeX)). database: a drop-in 11-view database (table/board/list/gallery/calendar/feed/chart/dashboard/form/map/timeline, 18 property/cell types, per-type column config, filter/sort/group/calculate, row peek + multi-select, cell drag-fill, formula engine, CSV/JSON import-export). sidebar: a standalone tree-nav sidebar (dnd reorder + reparent with depth projection, inline rename, per-row icon picker). All stateless + callback-CRUD — the host owns the data. Install one surface with `npx rr add notion-ui page|database|sidebar`, or all with `npx rr add notion-ui`; the shared/ domain type model is copied for every variant. NOT the full Notion app — that's the separate `notion` slice (adapter + Convex backed).",
      "source": "notion-page-clone",
      "slicePath": "frontend/slices/notion-ui",
      "convexPaths": [],
      "npm": [
        "@dnd-kit/core@^6",
        "@dnd-kit/sortable",
        "@dnd-kit/utilities",
        "katex@^0.16.45",
        "highlight.js@^11.11.1",
        "recharts@^3",
        "lucide-react"
      ],
      "shadcn": [
        "button",
        "checkbox",
        "dialog",
        "dropdown-menu",
        "input",
        "popover",
        "select",
        "separator",
        "sheet",
        "switch",
        "toggle-group",
        "tooltip"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "ui",
        "notion",
        "notion-like",
        "database",
        "table",
        "board",
        "list",
        "gallery",
        "calendar",
        "feed",
        "chart",
        "dashboard",
        "form",
        "map",
        "timeline",
        "gantt",
        "kanban",
        "views",
        "filter",
        "sort",
        "property",
        "files",
        "person",
        "formula",
        "timestamp",
        "unique-id",
        "csv",
        "json",
        "import",
        "export",
        "template",
        "data",
        "backup",
        "primitive",
        "optional",
        "embeddable"
      ],
      "agentRecipe": "**Controlled component.** `<NotionDatabase />` renders the whole surface — 11 views (table, board, list, gallery, calendar, feed, chart, dashboard, form, map, timeline), 18 cell types, filter / sort / group / calculate, row peek + multi-select, table cell drag-fill, CSV / JSON import-export. It is 100% props-driven: it owns NO data state — you hold `db` + `rows` and persist every change callback. The view tab strip scrolls horizontally and the card clips to its border, so it stays inside any container width.\n\n**1. Install** — `npx rr add notion-ui database`. Cascades the `notion-shell` peer (the domain types live there). Components import from `@/features/notion-ui`; types from `@/features/notion-ui`.\n\n**2. Minimal wire-up** — keep `db: Database` + `rows: Page[]` in your store (a Convex query result or `useState`) and pass change handlers:\n```tsx\nimport { NotionDatabase } from '@/features/notion-ui';\n\n<NotionDatabase\n  db={db}\n  rows={rows}\n  onRowAdd={addRow}\n  onRowUpdate={(rowId, propId, value) => setValue(rowId, propId, value)}\n  onRowRemove={removeRow}\n  onPropertyAdd={addProperty}\n  onViewActivate={setActiveView}\n  onViewAdd={addView}\n  onViewConfigChange={(viewId, patch) => patchView(viewId, patch)}\n/>\n```\nOmit any callback and that affordance goes read-only; pass `readOnly` to freeze everything at once.\n\n**3. Data shape** — `Database = { id, name, properties: Property[], views: DatabaseViewConfig[], activeViewId }`; each row `Page = { id, title, rowProps: Record<propId, PropertyValue> }`. For `relation` / `rollup` cells also pass `pages` + `databases`; for `person` / `created_by` cells pass `userLookup(id)`.\n\n**4. Import / export** — mount `<DatabaseIOActions db={db} rows={rows} onImport={handleImport} />` in your toolbar: CSV/JSON in (with schema-diff), CSV/JSON + live-schema templates out. New columns arrive with a `tempId` — map it to your real backend id before writing their `rowProps`.\n\n**5. Backend (optional)** — the UI is store-agnostic. For Convex persistence copy `template-base/database-silong/convex/` (handlers → `convex/`, schema fragment merges into `convex/schema.ts`). Pick `_shared/minimal/` (single-user, noop authz) or `_shared/full/` (`@convex-dev/auth` + workspaces). See CONVEX-BACKEND.md.\n\n**Just one view?** Import it directly — `import { TableView } from '@/features/notion-ui'` — and feed it `rows` + `renderCell` + `renderColumnHeader`.",
      "variants": {
        "default": "page",
        "shared": "shared",
        "items": [
          {
            "id": "page",
            "title": "Page",
            "description": "Page + block editor primitives (NotionPage / NotionBlock, SlashMenu, renderers)."
          },
          {
            "id": "database",
            "title": "Database",
            "description": "11-view database (NotionDatabase, filter/sort/group, formula, CSV/JSON I/O)."
          },
          {
            "id": "sidebar",
            "title": "Sidebar",
            "description": "Tree-nav sidebar (NotionSidebar, dnd reorder + reparent, inline rename)."
          }
        ]
      }
    },
    {
      "slug": "image-picker",
      "title": "Image Picker — one-button image/wallpaper chooser (gallery · upload · link · Unsplash · reposition)",
      "category": "ui",
      "kind": "ui",
      "version": "0.3.0",
      "description": "Generic image/wallpaper picker — not coupled to Notion. The headline API is ONE button (ImagePickerButton) that opens a dialog with 4 tabs: Gallery (12 colours + 8 gradients + Notion textures), Upload (drag/click, ≤8MB), Link (paste any https image URL), Unsplash (bundled curated landscapes + live search). On pick, onChange fires with an ImageValue ({ type, value, positionY?, metadata? }). ImageBanner is the optional reposition-able band — render an ImageValue as a full-width cover / profile header / card hero with hover controls: Change (opens the dialog), Reposition (drag the vertical focal point), Remove. The slice imports NO other slice and NO backend — the upload backend and Unsplash search are INJECTED as props (onUpload + searchUnsplash), so it drops into any app: wire onUpload to the `files` slice and searchUnsplash to a server route via unsplashSearchVia('/api/unsplash') that holds UNSPLASH_ACCESS_KEY server-side (never NEXT_PUBLIC). Ships a curated Unsplash fallback + gallery so it works with zero config. parseImage normalizes legacy raw-string values; imageStyle builds the focal-point CSS. Wired into the notion-page-clone template as the page cover via NotionPage's coverSlot.",
      "source": "notion-page-clone",
      "slicePath": "frontend/slices/image-picker",
      "convexPaths": [],
      "npm": [],
      "shadcn": [
        "dialog",
        "button",
        "input"
      ],
      "env": [
        {
          "name": "UNSPLASH_ACCESS_KEY",
          "scope": "server",
          "required": false,
          "description": "Server-side only (e.g. on the /api/unsplash route). Without it the Unsplash tab falls back to the curated set."
        }
      ],
      "peers": [],
      "providers": [],
      "tags": [
        "ui",
        "image",
        "picker",
        "wallpaper",
        "cover",
        "upload",
        "unsplash",
        "gallery",
        "reposition",
        "files",
        "primitive",
        "portable",
        "dialog"
      ],
      "agentRecipe": "Run `npx rr add image-picker`. The headline component is `<ImagePickerButton label=\"Change image\" onChange={(img)=>save(img)} onUpload={…} searchUnsplash={…} />` — ONE button that opens the 4-tab dialog (gallery / upload / link / Unsplash). For a reposition-able cover/hero band use `<ImageBanner image={value} onChange={save} resolvedUrl={…} onUpload={…} searchUnsplash={…} />` (also passable to notion-shell's `<NotionPage coverSlot={…} />`). Inject the backend: `onUpload` = the `files` slice's useFileUpload().upload (returns a FileRef); resolve upload images for display with `resolvedUrl` = files useFileUrl(parseFileRef(imageRef(parseImage(value))).storageId). `searchUnsplash` = `unsplashSearchVia('/api/unsplash')` — add a server route that proxies api.unsplash.com with UNSPLASH_ACCESS_KEY (never expose the key client-side). Ships a curated Unsplash + gallery fallback so it works with zero wiring. ImageValue = { type, value, positionY?, metadata? }; parseImage handles legacy string values."
    },
    {
      "slug": "workspace-shell",
      "title": "Workspace Shell — atomic (workspace × menuSet) NavContext",
      "category": "ui",
      "kind": "full",
      "version": "1.0.0",
      "description": "Unified workspace + menu navigation primitive. NavContext = (workspaceId, menuSetId) atomic pair. 2-tier dropdown switcher (workspace radio + menuSet picker), ContextBadge header chip, full editor with tabs (menus / workspace tree / settings), tiered RBAC (admin menus.manage, user menus.fork). Replaces silo'd menu-store + workspace-store slices in superspace. Resolver chain: user nav-context cache > user assignment > workspace default > system. Source: superspace.",
      "source": "superspace",
      "slicePath": "template-base/frontend/slices/workspace-shell",
      "convexPaths": [
        "template-base/convex/features/workspaceShell"
      ],
      "npm": [],
      "shadcn": [
        "dropdown-menu",
        "popover",
        "command",
        "tabs",
        "switch"
      ],
      "env": [],
      "peers": [
        {
          "slug": "convex-auth",
          "range": "^0.1",
          "reason": "User session required for menuSet assignment + nav-context cache."
        }
      ],
      "providers": [],
      "tags": [
        "ui",
        "navigation",
        "workspace",
        "menu",
        "shell",
        "convex",
        "rbac"
      ],
      "agentRecipe": "Run `npx rr add workspace-shell`. Tables prefixed `workspaceShell_*` (menuSets, menuItems, itemComponents, wsAssignments, userAssignments, rolePerms, navContext). Mount `<NavContextProvider workspaceId={wsId}>` inside your auth provider; use `useNavContext(wsId)` to read `{workspace, menuSet, source, effectiveMenuItems, setMenuSet, forkMenuSet}`. Drop-in `<WorkspaceSwitcher canFork />` in sidebar header. Tiered RBAC: `menus.manage` for workspace-default editing, `menus.fork` for user-personal copy. Resolver chain: user cache → user assignment → workspace default → none. Pair with audit-log slice for context-switch / fork events (graceful try/catch if absent). Effective items query applies role filter via workspaceShell_rolePerms (no rolePerms → show all, pre-RBAC compat)."
    },
    {
      "slug": "library",
      "title": "Library — resource hub (prompts · visuals · snippets · links)",
      "category": "data",
      "kind": "full",
      "version": "0.2.0",
      "description": "Grab-bag resource hub. One polymorphic `libraryItems` table holds six kinds — prompt, image, video, link, download, snippet — with per-kind payload fields switched on `kind` (no joins). Attribution-first: every item carries optional source/license/tools so re-shares stay correct. Collections group items. Convex-backed (schema + queries + unauthenticated mutations); SEO override fields reused from the `seo` peer slice so the surface matches blog/projects rows. Public view = filterable card grid + per-item detail with copy-to-clipboard for prompts/snippets and an opt-in upvote control. Lifted 2026-05-28 from rahmanef.com; 432-LOC mutations + 330-LOC detail split for the 200-LOC cap; Indonesian copy + custom primitives stripped (prop-driven English defaults); cross-slice auth + comments-votes coupling dropped (consumer wraps mutations + supplies the upvote handler).",
      "source": "rahmanef.com",
      "slicePath": "frontend/slices/library",
      "convexPaths": [
        "convex/features/library"
      ],
      "npm": [
        "convex@^1.17",
        "next@^15",
        "react@^18"
      ],
      "shadcn": [],
      "env": [],
      "peers": [
        {
          "slug": "seo",
          "range": "^0.2",
          "reason": "Library item SEO override fields reuse the seo slice's metadata shape so the surface matches blog/projects rows."
        }
      ],
      "providers": [],
      "tags": [
        "library",
        "resources",
        "prompts",
        "snippets",
        "moodboard",
        "downloads",
        "attribution",
        "seo",
        "personal-brand"
      ],
      "agentRecipe": "Run `npx rr add seo` (peer) then `npx rr add library`. Spread `seoTables` + `libraryTables` into your root Convex schema. Wrap the unauthenticated CRUD `internalMutation`s with your auth model (see README Install). Render `<LibraryIndex items={await fetchQuery(api.library.listPublic)} />` and `<LibraryDetail item={await fetchQuery(api.library.getBySlug, { slug })} />`. Pass `onUpvote` to enable voting (consumer-owned backend); override `copy` + `kindLabels` per consumer."
    },
    {
      "slug": "data-table",
      "title": "Data Table — TanStack + shadcn",
      "category": "data",
      "kind": "ui",
      "version": "0.2.0",
      "description": "Generic DataTable<TData> on TanStack Table v8 + shadcn Table. Sorting (3-state column headers), toolbar search bound to any column, pagination, checkbox row selection with count footer, column-visibility dropdown. density compact|comfortable + selectable on|off variant axes. Pure UI — consumer supplies columns + data.",
      "source": "rr original (shadcn data-table pattern)",
      "slicePath": "frontend/slices/data-table",
      "convexPaths": [],
      "npm": [
        "@tanstack/react-table@^8.21.0"
      ],
      "shadcn": [
        "table",
        "button",
        "input",
        "checkbox",
        "dropdown-menu",
        "badge",
        "select"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "table",
        "data-table",
        "datagrid",
        "sorting",
        "filtering",
        "pagination",
        "selection",
        "basics"
      ],
      "agentRecipe": "Run `npx rr add data-table`. Build ColumnDef<TData>[] (use sortable headers via DataTableColumnHeader), pass data + columns to <DataTable>. searchKey binds the toolbar input to one column; selectable prepends the checkbox column; density tightens row padding."
    },
    {
      "slug": "pages-cms",
      "title": "Pages CMS — block-composed multi-page editor",
      "category": "content",
      "kind": "ui",
      "version": "0.1.0",
      "description": "A small multi-page CMS. PagesView (list + CRUD: create/edit/duplicate/delete/publish) + PageEditorView (metadata form + block editor) + a read-only public BlockRenderer. Pages are composed of 11 block kinds: hero, text, feature-list, cta, logo-cloud, testimonial, video, image-gallery, faq, stats, pricing-table. Ships a localStorage adapter (LocalPagesProvider) + a generic Home/About/Pricing seed so it runs env-free — or wire the bundled pagesReducer + PagesProvider to your own backend (optional Convex copy-source included). Pure UI; no Convex required.",
      "source": "rr original (generalized from saas-marketing pages engine)",
      "slicePath": "frontend/slices/pages-cms",
      "convexPaths": [],
      "npm": [
        "lucide-react"
      ],
      "shadcn": [
        "badge",
        "button",
        "table",
        "input",
        "textarea",
        "label",
        "select",
        "switch",
        "card",
        "dialog"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "content",
        "cms",
        "pages",
        "blocks",
        "editor",
        "builder",
        "basics"
      ],
      "agentRecipe": "Run `npx rr add pages-cms`. Wrap your admin surface in <LocalPagesProvider seed={defaultPages()}> (localStorage, zero backend) or supply your own PagesStore via <PagesProvider>. Render <PagesView publicBase adminBase> for the list and <PageEditorView id publicBase adminBase> for the editor route. Public catch-all looks up the page by slug and renders <BlocksRenderer blocks={page.blocks} />. Add block kinds by extending the PageBlock union + emptyBlock + the renderer/editor switches."
    },
    {
      "slug": "feedback-states",
      "title": "Feedback States — loading skeletons + empty/error states",
      "category": "ui",
      "kind": "ui",
      "version": "0.2.0",
      "description": "Two co-located placeholder surfaces behind one slug. loading: a configurable LoadingSkeleton over the shadcn Skeleton (kind presets text / card / list / table / form / page / block, overridable count + columns) plus a spinner LoadingState (inline / block / overlay) for in-flight work. empty: a configurable EmptyState over the shadcn Empty (404 / 500 / 403 / no-results / empty-list / first-use, overridable icon/title/copy/actions) plus an ErrorPage full-page wrapper for app/not-found.tsx and app/error.tsx. Install one surface with `npx rr add feedback-states loading|empty`, or both with `npx rr add feedback-states`. Replaces ad-hoc animate-pulse divs, hand-rolled Loader2 spans, and one-off error pages.",
      "source": "rr original",
      "slicePath": "frontend/slices/feedback-states",
      "convexPaths": [],
      "npm": [
        "lucide-react@^0.400.0"
      ],
      "shadcn": [
        "skeleton",
        "spinner",
        "empty",
        "button"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "loading",
        "skeleton",
        "spinner",
        "empty-state",
        "404",
        "500",
        "403",
        "error-page",
        "fallback",
        "placeholder",
        "basics"
      ],
      "agentRecipe": "Run `npx rr add feedback-states` for both, or `npx rr add feedback-states loading` / `empty` for one surface. loading: <LoadingSkeleton kind=\"table\" count={8} /> mirrors streamed content, kind=\"page\" drops into route loading.tsx, <LoadingState variant=\"inline|block|overlay\" /> for in-flight work. empty: <EmptyState kind=\"no-results\" /> in zero-data spots, <ErrorPage kind=\"404\" /> in app/not-found.tsx and kind=\"500\" in app/error.tsx. Every preset overridable per use.",
      "variants": {
        "default": "loading",
        "items": [
          {
            "id": "loading",
            "title": "Loading",
            "description": "Skeletons + spinners for in-flight UI (LoadingSkeleton, LoadingState)."
          },
          {
            "id": "empty",
            "title": "Empty",
            "description": "404/500/403 + zero-data placeholders (EmptyState, ErrorPage)."
          }
        ]
      }
    },
    {
      "slug": "marketing-chrome",
      "title": "Marketing Chrome — Header + Footer",
      "category": "ui",
      "kind": "ui",
      "version": "0.2.0",
      "description": "MarketingHeader (split | centered | minimal layouts, sticky option, mobile sheet menu) + MarketingFooter (columns | slim layouts, link columns, social icons, legal bar). Brand / nav / CTA / columns all props — no hardcoded content. Lucide stand-ins for brand glyphs; swap a brand icon set post-copy (README).",
      "source": "rr original (extracted from template duplication)",
      "slicePath": "frontend/slices/marketing-chrome",
      "convexPaths": [],
      "npm": [],
      "shadcn": [
        "button",
        "sheet",
        "separator"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "header",
        "footer",
        "navbar",
        "marketing",
        "navigation",
        "chrome",
        "basics"
      ],
      "agentRecipe": "Run `npx rr add marketing-chrome`. Feed MarketingHeader { brand, nav[], cta, layout } and MarketingFooter { brand, columns[], social[], legal[], layout }. Header layout split is the default marketing pattern; footer columns for full sites, slim for single-pagers."
    },
    {
      "slug": "settings",
      "title": "Settings — account + appearance shells",
      "category": "ui",
      "kind": "ui",
      "version": "1.0.0",
      "description": "Two settings surfaces behind one slug, each adapter-driven so the slice owns no data. account: SettingsShell two-column surface (nav collapses to a Select on mobile) — Profile (avatar/name/email/bio), Preferences (theme/language/density), Notifications (switch rows), Danger zone (AlertDialog-confirmed delete) over an ASYNC SettingsAdapter { load, save(patch) } with optimistic save + rollback; createMemoryAdapter ships for demos. appearance: AppearancePanel (style/mode/accent/wallpaper/reduce-transparency/display) over a SYNC per-setting AppearanceAdapter, plus the generic SettingsSection / SettingsRow / Segmented / AccentSwatches primitives you compose custom panels from. Install one surface with `npx rr add settings account|appearance`, or both with `npx rr add settings`.",
      "source": "rr original",
      "slicePath": "frontend/slices/settings",
      "convexPaths": [],
      "npm": [
        "lucide-react@^0.400.0"
      ],
      "shadcn": [
        "alert-dialog",
        "avatar",
        "button",
        "card",
        "input",
        "label",
        "select",
        "separator",
        "skeleton",
        "switch",
        "textarea",
        "toggle-group"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "settings",
        "preferences",
        "account",
        "appearance",
        "theme",
        "adapter",
        "shell",
        "primitives",
        "ui",
        "basics"
      ],
      "agentRecipe": "Run `npx rr add settings` for both, or `npx rr add settings account` / `appearance` for one. account: implement SettingsAdapter { load, save } over your backend (Convex query + mutation), pass to <SettingsShell adapter>; save gets per-section partial patches (shallow-merge server-side); onDeleteAccount wires the danger zone. appearance: build an AppearanceAdapter (per-setting SegSetting values) from your appearance store, pass to <AppearancePanel appearance>; or compose custom panels from <SettingsSection>/<SettingsRow>/<Segmented>/<AccentSwatches>.",
      "variants": {
        "default": "account",
        "items": [
          {
            "id": "account",
            "title": "Account",
            "description": "Profile/preferences/notifications/danger-zone shell over an async load+save adapter."
          },
          {
            "id": "appearance",
            "title": "Appearance",
            "description": "Style/mode/accent/wallpaper/display shell over a sync per-setting adapter + the shared Section/Row/Segmented primitives."
          }
        ]
      }
    },
    {
      "slug": "notifications-center",
      "title": "Notifications Center — bell + inbox",
      "category": "ui",
      "kind": "ui",
      "version": "0.2.0",
      "description": "NotificationBell (ghost icon button, unread badge, popover or sheet surface) + NotificationList (All/Unread tabs, mark-all-read, clear, ScrollArea rows with kind icon, relative time, hover actions). NotificationsAdapter contract (list/markRead/markAllRead/dismiss/clear) with a useSyncExternalStore-friendly memory adapter included — swap in Convex for production (sketch in README).",
      "source": "rr original (appshell toast-log pattern, standalone)",
      "slicePath": "frontend/slices/notifications-center",
      "convexPaths": [],
      "npm": [],
      "shadcn": [
        "button",
        "popover",
        "sheet",
        "badge",
        "scroll-area",
        "separator",
        "tabs",
        "avatar"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "notifications",
        "inbox",
        "bell",
        "unread",
        "toast",
        "basics"
      ],
      "agentRecipe": "Run `npx rr add notifications-center`. Mount <NotificationBell adapter> in your topbar. Implement NotificationsAdapter over your feed (Convex query + mutations) or start with createMemoryNotificationsAdapter(seed). surface=\"sheet\" for mobile-heavy apps."
    },
    {
      "slug": "design-studio",
      "title": "Design Studio — photo / social design canvas",
      "category": "os",
      "kind": "ui",
      "version": "1.0.0",
      "description": "A layered canvas studio: image/text/shape layers with filters, masks, transforms, safe-area guides and aspect presets (1:1/4:5/9:16/16:9), plus an export modal (download / copy / import JSON). Runs fully offline on bundled gradient-SVG samples. Host wiring is one call: configureMediaStudio({ saveDoc, imageSources }) lights up Save-to-host and feeds real image sources. Self-contained: inspector hooks are inert seams in lib/host.ts.",
      "source": "rahmanef63/os-vps",
      "slicePath": "frontend/slices/design-studio",
      "convexPaths": [],
      "npm": [
        "lucide-react"
      ],
      "shadcn": [
        "button",
        "dialog",
        "badge",
        "tooltip",
        "scroll-area"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "canvas",
        "editor",
        "layers",
        "filters",
        "export",
        "design",
        "ui"
      ],
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. Layered canvas editor. Fully client-side; no backend required.\n\nSTEP 1 — Install. `npx rr add design-studio`. Ensure `@/features/design-studio` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: button, dialog, badge, tooltip, scroll-area.\n\nSTEP 3 — Mount. `<MediaStudio />` in a height-bearing box — unwired it edits bundled sample layers. Or register `mediaStudioApp` in an appshell manifest.\n\nSTEP 4 — Host wiring. `configureMediaStudio({ saveDoc, imageSources })` — saveDoc persists the serialized document (enables Save-to-host in the export modal); imageSources supplies image URLs for new layers."
    },
    {
      "slug": "quicklinks",
      "title": "Quicklinks — website shortcuts with favicons",
      "category": "os",
      "kind": "ui",
      "version": "1.0.0",
      "description": "A website-shortcut grid: add/remove links with auto favicons (Google s2) and new-tab open. State lives behind an injectable QuicklinksStore — createLocalStore persists to localStorage (SSR-safe hydrate), createMemoryStore suits previews/tests, configureQuicklinks swaps in a host store. Pairs with appshell: the useQuickLinks capability + QuicklinkIcon surface the same links in the dock/Launchpad/mobile grid.",
      "source": "rahmanef63/os-vps",
      "slicePath": "frontend/slices/quicklinks",
      "convexPaths": [],
      "npm": [
        "lucide-react"
      ],
      "shadcn": [
        "button"
      ],
      "env": [],
      "peers": [],
      "providers": [],
      "tags": [
        "shortcuts",
        "bookmarks",
        "favicons",
        "launcher",
        "ui"
      ],
      "agentRecipe": "Stack: Next 16 + React 19 + Tailwind 4 + shadcn/ui. Website shortcut grid. Fully client-side; no backend required.\n\nSTEP 1 — Install. `npx rr add quicklinks`. Ensure `@/features/quicklinks` resolves and Tailwind scans the slice folder.\n\nSTEP 2 — Deps. npm: `lucide-react`. shadcn: button.\n\nSTEP 3 — Mount. `<Quicklinks />` — unwired it persists to localStorage (\"rr:quicklinks\") with 4 demo seeds. Or register `quicklinksApp` in an appshell manifest.\n\nSTEP 4 — Host store. `configureQuicklinks(store)` with { get, subscribe, add, remove, hydrate? } — or feed appshell's useQuickLinks capability from the same store so dock shortcuts stay in sync."
    }
  ]
}
