rahman-resources 1.9.2 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/manifest.json CHANGED
@@ -1,6 +1,5 @@
1
1
  {
2
2
  "version": 2,
3
- "generatedAt": "2026-05-31T10:45:23.016Z",
4
3
  "repo": "rahmanef63/resource-site",
5
4
  "branch": "main",
6
5
  "layouts": [
@@ -421,20 +420,20 @@
421
420
  "title": "Notion Page Clone OS — localStorage demo (pointer to open-silong for production)",
422
421
  "category": "website-template",
423
422
  "status": "stable",
424
- "description": "localStorage-only DEMO of a Notion-clone surface — tree-structured sidebar + page editor + embedded databases. Built from rr's notion-shell wrappers (NotionSidebar / NotionPage / NotionBlock / NotionDatabase) + notion-blocks primitives (equation / code / notify / drag-fill grid) + createTemplateStore (localStorage + BroadcastChannel). No Convex, no auth, no multi-user — drop-in starter for evaluating the UI or embedding a Notion-style editor in your own project. **For the production-grade Convex-backed product (multi-workspace + auth + sharing + comments + snapshots + MCP), use the open-source open-silong repo: https://github.com/rahmanef63/open-silong (silong.rahmanef.com).** This rr template is the DEMO; the github repo is the PRODUCT.",
425
- "source": "synthesized + notion-shell wrappers + notion-blocks bundle; production stack at github.com/rahmanef63/open-silong",
423
+ "description": "localStorage-only DEMO of a Notion-clone surface — tree-structured sidebar + page editor + embedded databases. It is the COMBINATION of independently-reusable rr slices: notion-sidebar (tree nav + page CRUD — double-click rename, drag-reorder/reparent, icon picker), notion-shell (NotionPage / NotionBlock page editor — code + equation blocks built-in), notion-database (11 views + drag-fill grid + relation/rollup), image-picker (one-button image/wallpaper chooser — gallery / upload / link / Unsplash + reposition, wired to the files slice + an /api/unsplash proxy; here it's the page cover), icon-picker, and files — glued by createTemplateStore (localStorage + BroadcastChannel). No Convex, no auth, no multi-user — drop-in starter for evaluating the UI or embedding a Notion-style editor in your own project. **For the production-grade Convex-backed product (multi-workspace + auth + sharing + comments + snapshots + MCP), use the open-source open-silong repo: https://github.com/rahmanef63/open-silong (silong.rahmanef.com).** This rr template is the DEMO; the github repo is the PRODUCT.",
424
+ "source": "synthesized + notion-shell wrappers (built-in code/equation); production stack at github.com/rahmanef63/open-silong",
426
425
  "repoPath": "app/preview/notion-page-clone-os",
427
426
  "pullPaths": [
428
427
  "app/preview/notion-page-clone-os",
429
428
  "components/templates/_shared",
430
429
  "components/templates/notion-page-clone",
431
- "frontend/slices/notion-blocks",
430
+ "frontend/slices/notion-sidebar",
432
431
  "frontend/slices/notion-shell",
432
+ "frontend/slices/notion-database",
433
+ "frontend/slices/image-picker",
434
+ "frontend/slices/files",
433
435
  "frontend/slices/icon-picker",
434
- "frontend/slices/equation",
435
- "frontend/slices/code-block",
436
- "frontend/slices/notifications",
437
- "frontend/slices/database-cell-selection"
436
+ "app/api/unsplash"
438
437
  ],
439
438
  "files": [
440
439
  "app/preview/notion-page-clone-os/public/layout.tsx",
@@ -453,6 +452,7 @@
453
452
  "components/templates/notion-page-clone/slices/admin/snippets/SnippetsView.tsx",
454
453
  "components/templates/notion-page-clone/slices/notion-app/Dashboard.tsx",
455
454
  "components/templates/notion-page-clone/slices/notion-app/DocView.tsx",
455
+ "components/templates/notion-page-clone/slices/notion-app/DocCover.tsx",
456
456
  "components/templates/notion-page-clone/slices/notion-app/DatabaseView.tsx",
457
457
  "components/templates/notion-page-clone/slices/notion-app/hooks.ts",
458
458
  "components/templates/notion-page-clone/slices/notion-app/block-renderers.tsx",
@@ -481,7 +481,7 @@
481
481
  "select",
482
482
  "dialog"
483
483
  ],
484
- "agentRecipe": "Run `npx rr init <app> --template notion-page-clone-os`. Cascades notion-shell (wrappers) + notion-blocks (4 editor primitives) + icon-picker. Edit components/templates/notion-page-clone/shared/site-config.ts to set brand; seed.ts to bootstrap docs + databases. Sidebar CRUD already wired — hover a row → +/✎/🗑.",
484
+ "agentRecipe": "Run `npx rr init <app> --template notion-page-clone-os`. Cascades notion-shell (wrappers, built-in code/equation blocks) + notion-database + icon-picker. Edit components/templates/notion-page-clone/shared/site-config.ts to set brand; seed.ts to bootstrap docs + databases. Sidebar CRUD already wired — hover a row → +/✎/🗑.",
485
485
  "tags": [
486
486
  "template",
487
487
  "notion",
@@ -500,7 +500,7 @@
500
500
  "category": "website-template",
501
501
  "status": "stable",
502
502
  "description": "Marketing site for a SaaS product — landing, pricing, features, blog, changelog, about, contact — backed by a full admin panel (Pages, Posts, Pricing, Features, Customers, Subscriptions, Leads, Changelog, Settings). Same grouped Pages + Features sidebar pattern as every other template.",
503
- "source": "synthesized + mdx-blog feature",
503
+ "source": "synthesized",
504
504
  "repoPath": "app/preview/saas-marketing-os",
505
505
  "pullPaths": [
506
506
  "app/preview/saas-marketing-os",
@@ -575,7 +575,7 @@
575
575
  "sheet",
576
576
  "textarea"
577
577
  ],
578
- "agentRecipe": "Run `npx rr init <app> --template saas-marketing-os`. SaaS Marketing OS = public-only marketing template. Blog + changelog use MDX (add the mdx-blog feature). Edit components/templates/saas-marketing/shared/site-config.ts to set product name, tagline, pricing tiers, contact email.",
578
+ "agentRecipe": "Run `npx rr init <app> --template saas-marketing-os`. SaaS Marketing OS = public-only marketing template. Edit components/templates/saas-marketing/shared/site-config.ts to set product name, tagline, pricing tiers, contact email.",
579
579
  "tags": [
580
580
  "template",
581
581
  "saas",
@@ -1357,11 +1357,75 @@
1357
1357
  ],
1358
1358
  "recipes": [],
1359
1359
  "features": [
1360
+ {
1361
+ "slug": "image-editor",
1362
+ "title": "Image Editor — Photoshop-style canvas (Konva)",
1363
+ "category": "ui",
1364
+ "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 (brightness/contrast/hue/saturation/blur/grayscale/invert/sepia, applied via Konva.Filters), canvas resize/aspect presets, and Photoshop-style LAYER STYLES: stroke, drop shadow (angle/distance/size/opacity), outer glow, clipping mask (clip to layer below), per-layer blend mode. One-click BACKGROUND REMOVAL runs fully in-browser via @imgly/background-removal (free, MIT, no API key, no server — downloads a small ONNX model to the browser cache on first use) and drops the cutout back as a transparent layer. Undo/redo, zoom/pan, keyboard shortcuts, and PNG/JPG/WebP export at 1×/2×/3×. Self-contained: image I/O is via props (initialImage / onSave) so it drops into any app with zero backend.",
1365
+ "source": "rahmanef63/os-vps",
1366
+ "install": "npx rahman-resources add image-editor",
1367
+ "npmPackages": [],
1368
+ "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}",
1369
+ "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.",
1370
+ "tags": [
1371
+ "image-editor",
1372
+ "photoshop",
1373
+ "canvas",
1374
+ "konva",
1375
+ "layers",
1376
+ "filters",
1377
+ "background-removal",
1378
+ "paint",
1379
+ "crop",
1380
+ "ui"
1381
+ ]
1382
+ },
1383
+ {
1384
+ "slug": "file-explorer",
1385
+ "title": "File Explorer — Tree + CRUD + Breadcrumb",
1386
+ "category": "ui",
1387
+ "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.",
1388
+ "source": "rahmanef63/os-vps",
1389
+ "install": "npx rahman-resources add file-explorer",
1390
+ "npmPackages": [],
1391
+ "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}",
1392
+ "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.",
1393
+ "tags": [
1394
+ "files",
1395
+ "file-manager",
1396
+ "explorer",
1397
+ "tree",
1398
+ "breadcrumb",
1399
+ "crud",
1400
+ "sidebar",
1401
+ "ui"
1402
+ ]
1403
+ },
1404
+ {
1405
+ "slug": "appshell",
1406
+ "title": "AppShell — Desktop + Mobile OS Shell",
1407
+ "category": "ui",
1408
+ "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).",
1409
+ "source": "rahmanef63/os-vps",
1410
+ "install": "npx rahman-resources add appshell",
1411
+ "npmPackages": [],
1412
+ "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}",
1413
+ "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\").",
1414
+ "tags": [
1415
+ "shell",
1416
+ "window-manager",
1417
+ "desktop",
1418
+ "mobile",
1419
+ "responsive",
1420
+ "framework",
1421
+ "ui"
1422
+ ]
1423
+ },
1360
1424
  {
1361
1425
  "slug": "convex-auth",
1362
1426
  "title": "Convex Auth — Multi-Provider Sign-in",
1363
1427
  "category": "auth",
1364
- "description": "@convex-dev/auth with Password (PBKDF2-SHA256 100k, self-hosted-friendly), Anonymous (guest), Google OAuth, and Resend magic-link. Ships a production SignInPage with i18n, prop-driven provider list, and split Login/Register tabs. No Clerk.",
1428
+ "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.",
1365
1429
  "source": "rahmanef63/resource-site",
1366
1430
  "docsUrl": "https://labs.convex.dev/auth",
1367
1431
  "install": "npm i @convex-dev/auth @auth/core resend",
@@ -1429,7 +1493,7 @@
1429
1493
  "slug": "resend-newsletter",
1430
1494
  "title": "Resend — Transactional & Newsletter",
1431
1495
  "category": "email",
1432
- "description": "Transactional email + newsletter blast via Resend. Double opt-in flow + audience segmentation. Magic-link delivery for Convex Auth.",
1496
+ "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.",
1433
1497
  "source": "rahmanef63/resource-site",
1434
1498
  "docsUrl": "https://resend.com/docs",
1435
1499
  "install": "npm i resend react-email @react-email/components",
@@ -1579,29 +1643,6 @@
1579
1643
  "rag"
1580
1644
  ]
1581
1645
  },
1582
- {
1583
- "slug": "mdx-blog",
1584
- "title": "MDX Blog",
1585
- "category": "content",
1586
- "description": "Markdown-with-JSX untuk blog post. File-based MDX content collection. Portable defineMdxBlog(opts) factory dengan 4 config props (basePath, contentDir, labels.list, nav) — defaults preserve legacy /blog + content/blog. Auto-generate ToC, reading-time, syntax highlight, plus embed React components inline.",
1587
- "source": "rahmanef63/resource-site",
1588
- "docsUrl": "https://github.com/hashicorp/next-mdx-remote",
1589
- "install": "npm i next-mdx-remote rehype-pretty-code remark-gfm reading-time",
1590
- "npmPackages": [
1591
- "next-mdx-remote",
1592
- "rehype-pretty-code",
1593
- "remark-gfm",
1594
- "reading-time"
1595
- ],
1596
- "exampleCode": "",
1597
- "agentRecipe": "Run `npx rr add mdx-blog`. Store post body sebagai markdown di content/blog/*.mdx. Render dengan MDXRemote di [slug]/page.tsx. Auto-extract headings ke ToC via remark plugin custom.",
1598
- "tags": [
1599
- "content",
1600
- "blog",
1601
- "mdx",
1602
- "static"
1603
- ]
1604
- },
1605
1646
  {
1606
1647
  "slug": "cal-com-booking",
1607
1648
  "title": "Cal.com Booking",
@@ -1622,25 +1663,6 @@
1622
1663
  "bookings"
1623
1664
  ]
1624
1665
  },
1625
- {
1626
- "slug": "full-width-toggle",
1627
- "title": "Full Width Toggle",
1628
- "category": "ui",
1629
- "description": "Page-container width toggle (contained / wide / full). Per-device localStorage + cross-tab sync. Ships useFullWidth hook + FullWidthToggle button (icon/button/segment variants) + WidthContainer wrapper. Zero backend, zero env.",
1630
- "source": "rahmanef63/resource-site",
1631
- "docsUrl": "",
1632
- "install": "",
1633
- "npmPackages": [],
1634
- "exampleCode": "",
1635
- "agentRecipe": "Run `npx rr add full-width-toggle`. Drop <WidthContainer> around page content, <FullWidthToggle variant='icon' /> in topbar. Variant 'segment' best for settings page. Hook useFullWidth() returns [mode, setMode, cycle]. SSR-safe — defaults to 'contained' until hydrate.",
1636
- "tags": [
1637
- "ui",
1638
- "layout",
1639
- "preference",
1640
- "localstorage",
1641
- "dashboard"
1642
- ]
1643
- },
1644
1666
  {
1645
1667
  "slug": "command-menu",
1646
1668
  "title": "Command Menu",
@@ -1767,20 +1789,43 @@
1767
1789
  },
1768
1790
  {
1769
1791
  "slug": "rbac-roles",
1770
- "title": "RBAC — Tiered System Roles",
1792
+ "title": "RBAC — Roles & Permissions",
1771
1793
  "category": "auth",
1772
- "description": "Workspace-scoped RBAC with 6 system roles (owner/admin/manager/staff/client/guest) and three tier presets solo, influencer, organization. Env-based platform admin bypass via PLATFORM_ADMIN_EMAILS. checkPermission / requirePermission helpers, role seeding mutation, @convex-dev/auth aware (no Clerk).",
1794
+ "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.",
1773
1795
  "source": "superspace",
1774
1796
  "install": "npx rahman-resources add rbac-roles",
1775
1797
  "npmPackages": [],
1776
1798
  "exampleCode": "",
1777
- "agentRecipe": "Run `npx rr add rbac-roles`. Three tier presets pick which system roles to seed: solo (owner+admin), influencer (+manager), organization (6 roles). Platform admin via env PLATFORM_ADMIN_EMAILS bypasses all checks. Resolution: platform admin workspace owner membership.additionalPermissions role.permissions.",
1799
+ "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).",
1778
1800
  "tags": [
1779
1801
  "rbac",
1780
1802
  "auth",
1781
1803
  "permissions",
1782
1804
  "roles",
1783
- "workspaces"
1805
+ "authorization",
1806
+ "no-clerk",
1807
+ "convex"
1808
+ ]
1809
+ },
1810
+ {
1811
+ "slug": "user-management",
1812
+ "title": "User Management",
1813
+ "category": "auth",
1814
+ "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.",
1815
+ "source": "superspace",
1816
+ "install": "npx rahman-resources add user-management",
1817
+ "npmPackages": [],
1818
+ "exampleCode": "",
1819
+ "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.",
1820
+ "tags": [
1821
+ "user-management",
1822
+ "members",
1823
+ "rbac",
1824
+ "auth",
1825
+ "team",
1826
+ "admin",
1827
+ "convex",
1828
+ "no-clerk"
1784
1829
  ]
1785
1830
  },
1786
1831
  {
@@ -1864,64 +1909,6 @@
1864
1909
  "personal-brand"
1865
1910
  ]
1866
1911
  },
1867
- {
1868
- "slug": "i18n-translate",
1869
- "title": "i18n — Google Translate widget",
1870
- "category": "ui",
1871
- "description": "Drop-in Google Translate widget. Replaces hand-maintained locale dictionaries with on-the-fly translation to a curated locale list (16 default, prop-override). No API key, no Google Cloud billing. Auto-detect browser language on first visit, persist user choice via localStorage, click-to-reload language switching with router-refresh + in-place fallback strategies. Lifted 2026-05-27 from rahmanef.com; 510-LOC monolith split into 8 sub-files for the 200-LOC cap; project-specific Tailwind utilities stripped from defaults.",
1872
- "source": "rahmanef.com",
1873
- "install": "npx rahman-resources add i18n-translate",
1874
- "npmPackages": [],
1875
- "exampleCode": "",
1876
- "agentRecipe": "Run `npx rr add i18n-translate`. Mount `<GoogleTranslate />` anywhere (e.g. header). Add the CSP allowlist from README.md to your middleware/proxy — without it Google's script fails silently. Override `languages`, `storageKey`, and the four `*ClassName` props for per-project styling. Default `fallbackRefresh=\"reload\"` is the only path that works reliably across Next Cache Components — only opt into `\"router\"` or `\"none\"` if you've tested it on your tree.",
1877
- "tags": [
1878
- "i18n",
1879
- "translate",
1880
- "google-translate",
1881
- "ui",
1882
- "language-switcher",
1883
- "locale",
1884
- "widget"
1885
- ]
1886
- },
1887
- {
1888
- "slug": "cta",
1889
- "title": "Call to Action",
1890
- "category": "ui",
1891
- "description": "Brutalist call-to-action section — eyebrow label, serif headline, body, arrow CTA. Pair with CtaButton standalone for inline placements. Lifted 2026-05-16 from rahmanef.com; assumes Tailwind tracking-brutal / tracking-brutal-sm utilities OR drop them for the default tracking scale.",
1892
- "source": "rahmanef.com",
1893
- "install": "npx rahman-resources add cta",
1894
- "npmPackages": [],
1895
- "exampleCode": "",
1896
- "agentRecipe": "Run `npx rr add cta`. <CtaView eyebrow title body href ctaLabel /> renders the full section; <CtaButton href label /> drops a standalone arrow button anywhere. Override tracking-brutal utilities in tailwind.config or swap for tracking-wide if your design system has no brutal preset.",
1897
- "tags": [
1898
- "ui",
1899
- "marketing",
1900
- "cta",
1901
- "section",
1902
- "brutalist"
1903
- ]
1904
- },
1905
- {
1906
- "slug": "hero",
1907
- "title": "Hero",
1908
- "category": "ui",
1909
- "description": "Editorial split-grid landing hero — eyebrow pill + large serif H1 + italic pull-quote + 1-2 button CTA row + right-column portrait card with optional caption. Fully props-driven (title/quote/ctas/image). Sanitized from rahmanef.com on 2026-05-16: SITE_CONFIG hardcode dropped, custom Heading/Section primitives replaced with raw semantic elements + stock Tailwind tracking-widest so the slice ships without consumer preset utilities.",
1910
- "source": "rahmanef.com",
1911
- "install": "npx rahman-resources add hero",
1912
- "npmPackages": [],
1913
- "exampleCode": "",
1914
- "agentRecipe": "Run `npx rr add hero`. <HeroView title eyebrow quote ctas image imageCaption /> — all props optional except title. Pass `image={undefined}` for text-only hero (auto-collapses to single 12-column row). Pairs visually with cta slice (same brutalist border + serif scale).",
1915
- "tags": [
1916
- "ui",
1917
- "hero",
1918
- "marketing",
1919
- "landing",
1920
- "section",
1921
- "editorial",
1922
- "brutalist"
1923
- ]
1924
- },
1925
1912
  {
1926
1913
  "slug": "rate-limit",
1927
1914
  "title": "Rate Limit",
@@ -1940,24 +1927,6 @@
1940
1927
  "throttle"
1941
1928
  ]
1942
1929
  },
1943
- {
1944
- "slug": "subscribers",
1945
- "title": "Subscribers",
1946
- "category": "email",
1947
- "description": "Newsletter list with honeypot + per-email rate-limit + token-based unsubscribe + admin remove. Public `subscribe` returns status strings (`created` / `already` / `resubscribed` / `honeypot`); admin `listAll` / `count` queries gated by `requireAdmin` (rr `_shared/auth`). Lifted 2026-05-16 from rahmanef.com; sanitized: token args dropped, sibling `analyticsEvents` insert removed — wrap subscribe in a consumer action if you want funnel telemetry.",
1948
- "source": "rahmanef.com",
1949
- "install": "npx rahman-resources add subscribers",
1950
- "npmPackages": [],
1951
- "exampleCode": "",
1952
- "agentRecipe": "Run `npx rr add subscribers`. Compose `subscribersTables` into root convex/schema.ts. Public form posts `api.features.subscribers.mutations.subscribe({ email, source, website })` — `website` is the honeypot, leave it `\"\"` from the form. Render unsubscribe link `/unsubscribe?t=<token>` and call `unsubscribe({ token })`.",
1953
- "tags": [
1954
- "email",
1955
- "newsletter",
1956
- "subscribers",
1957
- "convex",
1958
- "backend"
1959
- ]
1960
- },
1961
1930
  {
1962
1931
  "slug": "testimonials",
1963
1932
  "title": "Testimonials",
@@ -1995,25 +1964,6 @@
1995
1964
  "agency"
1996
1965
  ]
1997
1966
  },
1998
- {
1999
- "slug": "socials",
2000
- "title": "Socials",
2001
- "category": "content",
2002
- "description": "Single source of truth for profile/social links. Powers JSON-LD `Person.sameAs` (Google entity graph), IndieWeb `<link rel=\"me\">` tags, and footer/contact/about UI surfaces. URL-deduped, ordered, `visible` / `featured` / `relMe` / `sameAs` flags. Lifted 2026-05-16 from rahmanef.com; token-based admin gate swapped, baked-in 14-platform rahmanef seed dropped — `seed` now takes items via args so each adopter ships their own list.",
2003
- "source": "rahmanef.com",
2004
- "install": "npx rahman-resources add socials",
2005
- "npmPackages": [],
2006
- "exampleCode": "",
2007
- "agentRecipe": "Run `npx rr add socials`. Compose `socialsTables` into root schema. Bootstrap with `npx convex run internal.features.socials.mutations.seed '{\"items\":[{\"platform\":\"github\",\"url\":\"https://github.com/<you>\",\"order\":1,\"visible\":true,\"featured\":true,\"sameAs\":true,\"relMe\":true}]}'`. Wire `useQuery(api.features.socials.queries.listVisible)` into footer for entity-graph SEO.",
2008
- "tags": [
2009
- "content",
2010
- "socials",
2011
- "seo",
2012
- "indieweb",
2013
- "convex",
2014
- "backend"
2015
- ]
2016
- },
2017
1967
  {
2018
1968
  "slug": "create-your-mcp",
2019
1969
  "title": "Create Your MCP",
@@ -2110,7 +2060,7 @@
2110
2060
  "slug": "comments",
2111
2061
  "title": "Comments — Threaded",
2112
2062
  "category": "content",
2113
- "description": "Polymorphic-target threaded comments. Consumer picks `TargetRef = { kind, id, subId? }` (e.g. page+block, blog+slug, task+id). Renderless <CommentsThread> + <CommentsAnchor> wrappers. useComments(bindings, opts) hook returns items + openCount + CRUD + forbiddenWords guard. Adapter pattern — see contract-negotiations §1.",
2063
+ "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.",
2114
2064
  "source": "rahmanef63/resource-site",
2115
2065
  "install": "npx rahman-resources add comments",
2116
2066
  "npmPackages": [],
@@ -2143,67 +2093,34 @@
2143
2093
  ]
2144
2094
  },
2145
2095
  {
2146
- "slug": "document-checklist",
2147
- "title": "Document Checklist Job-Search Doc Tracker",
2096
+ "slug": "markdown",
2097
+ "title": "Markdownpage container with CRUD tabs + diagrams",
2148
2098
  "category": "content",
2149
- "description": "Track required job-search documents (CV, KTP, ijazah, etc.) with country-scoped seed templates and per-user completion state. Ships an Indonesian default checklist. Toggle completed + notes + expiry per item.",
2150
- "source": "rahmanef63/CareerPack",
2151
- "install": "npx rahman-resources add document-checklist",
2152
- "npmPackages": [],
2153
- "exampleCode": "",
2154
- "agentRecipe": "Run `rr add document-checklist`. Wire <DocumentChecklist bindings={{ current, seed, updateStatus }} countryTemplateSlot={<CountryTemplateCard bindings={{ templates, getTemplate, instantiate }} />} /> — bindings sourced from api.features['document-checklist'].* queries/mutations.",
2155
- "tags": [
2156
- "career",
2157
- "documents",
2158
- "checklist",
2159
- "job-search",
2160
- "indonesia"
2161
- ]
2162
- },
2163
- {
2164
- "slug": "pricing-page",
2165
- "title": "Pricing Page",
2166
- "category": "ui",
2167
- "description": "Canonical pricing tier section — eyebrow + headline + 2/3/4 column tier grid with optional FAQ accordion below. Tiers fully data-driven (name/price/period/bullets/cta/featured/badge). Featured variant configurable (ring/scale/tint). Single SSOT — every saas/marketing template consumes this slice for pricing pages so admin-edited tiers propagate without per-template rewriting.",
2168
- "source": "rahman-resources",
2169
- "install": "npx rahman-resources add pricing-page",
2170
- "npmPackages": [],
2171
- "exampleCode": "",
2172
- "agentRecipe": "Run `npx rr add pricing-page`. <PricingSection eyebrow title subtitle tiers columns faq faqTitle featuredVariant /> — only `title` + `tiers` required. Each tier: `{ id, name, price, period?, blurb?, bullets[], cta?, featured?, badge? }`. Pass `featuredVariant=\"scale\"` for a popped-forward card or `\"tint\"` for a colored background. Wire admin CRUD via your store hook → useTiers() → pass array.",
2173
- "tags": [
2174
- "ui",
2175
- "pricing",
2176
- "section",
2177
- "marketing",
2178
- "saas",
2179
- "tiers",
2180
- "faq"
2181
- ]
2182
- },
2183
- {
2184
- "slug": "feature-grid",
2185
- "title": "Feature Grid",
2186
- "category": "ui",
2187
- "description": "Canonical features grid section — eyebrow + headline + 1/2/3/4 column item grid in three layout variants (cards, minimal, alternating). Items accept Lucide icon component OR string label, optional image (next/image), optional link CTA. Single SSOT — every template consumes this slice for features pages so admin-edited items propagate without per-template duplication.",
2099
+ "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.",
2188
2100
  "source": "rahman-resources",
2189
- "install": "npx rahman-resources add feature-grid",
2101
+ "install": "npx rahman-resources add markdown",
2190
2102
  "npmPackages": [],
2191
2103
  "exampleCode": "",
2192
- "agentRecipe": "Run `npx rr add feature-grid`. <FeatureGridSection eyebrow title subtitle items columns layout align /> — only `items` required. Each item: `{ id, title, body, icon?, image?, link? }`. `icon` can be a LucideIcon component (rendered as 5×5 inline) or a string (rendered as letter fallback). `layout=\"alternating\"` produces image+text rows that flip per index set `image` per item for that variant.",
2104
+ "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)`.",
2193
2105
  "tags": [
2194
- "ui",
2195
- "features",
2196
- "section",
2197
- "marketing",
2198
- "grid",
2199
- "saas"
2106
+ "content",
2107
+ "markdown",
2108
+ "reader",
2109
+ "editor",
2110
+ "review",
2111
+ "comments",
2112
+ "mermaid",
2113
+ "chart",
2114
+ "rich-text",
2115
+ "docs",
2116
+ "notion-sync"
2200
2117
  ]
2201
2118
  },
2202
2119
  {
2203
2120
  "slug": "landing-sections",
2204
2121
  "title": "Landing Sections",
2205
2122
  "category": "infra",
2206
- "description": "CRUD-driven admin editor for the public landing-page composition. Ships a pure reducer + LandingProvider store adapter + admin LandingView/LandingEditorView built on the shared CRUD primitives, plus a per-section LandingSectionShell that handles background image + custom Tailwind className overlay. Sections carry { kind, order, title, subtitle, enabled, imageUrl, imageRatio, bgImageUrl, className, config (JSON) } with up/down reorder arrows. Consumers map each `kind` (hero, features, pricing, blog, changelog, testimonials, portfolio, services, stats, newsletter, faq, cta, custom) to their own renderer wrapped in <LandingSectionShell>. Canonical pattern used by all 7 rr website templates.",
2123
+ "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 + LandingProvider store adapter + admin LandingView/LandingEditorView built on the shared CRUD primitives, plus a per-section LandingSectionShell that handles background image + custom Tailwind className overlay. Sections carry { kind, order, title, subtitle, enabled, imageUrl, imageRatio, bgImageUrl, className, config (JSON) } with up/down reorder arrows. Consumers map each `kind` (hero, features, pricing, blog, changelog, testimonials, portfolio, services, stats, newsletter, faq, cta, custom) to their own renderer wrapped in <LandingSectionShell>. Used by all 7 rr website templates.",
2207
2124
  "source": "rahman-resources",
2208
2125
  "install": "npx rahman-resources add landing-sections",
2209
2126
  "npmPackages": [],
@@ -2217,102 +2134,6 @@
2217
2134
  "crud"
2218
2135
  ]
2219
2136
  },
2220
- {
2221
- "slug": "faq-section",
2222
- "title": "FAQ Section",
2223
- "category": "ui",
2224
- "description": "Canonical FAQ accordion section — eyebrow + headline + accordion item list. Three layouts (single column, two-column, grouped by category). Optional footer CTA (\"Still have questions?\"). Items fully data-driven. Single SSOT — every template consumes this slice for FAQ blocks so admin-edited Q&A propagates without per-template rewrite.",
2225
- "source": "rahman-resources",
2226
- "install": "npx rahman-resources add faq-section",
2227
- "npmPackages": [],
2228
- "exampleCode": "",
2229
- "agentRecipe": "Run `npx rr add faq-section`. <FAQSection items title subtitle layout multiple defaultOpen footerCta /> — only `items` required. Each item: `{ id, q, a, category? }`. `layout=\"grouped\"` buckets by `category`. `multiple` lets users open several at once. `footerCta={{ label, href }}` wires a contact link below the accordion.",
2230
- "tags": [
2231
- "ui",
2232
- "faq",
2233
- "section",
2234
- "accordion",
2235
- "marketing"
2236
- ]
2237
- },
2238
- {
2239
- "slug": "testimonials-grid",
2240
- "title": "Testimonials Grid",
2241
- "category": "ui",
2242
- "description": "Canonical testimonials section — quote + author + role/company + optional avatar + optional star rating. Three layouts (uniform cards grid, centered quote-stack, CSS masonry). `featured` testimonials get a ring accent. Pairs naturally with the `testimonials` backend slice (Convex queries) but has zero coupling — pass any item array.",
2243
- "source": "rahman-resources",
2244
- "install": "npx rahman-resources add testimonials-grid",
2245
- "npmPackages": [],
2246
- "exampleCode": "",
2247
- "agentRecipe": "Run `npx rr add testimonials-grid`. <TestimonialsGridSection items title subtitle columns layout align /> — only `items` required. Each item: `{ id, quote, author, role?, company?, avatar?, rating?, featured? }`. `layout=\"quote-stack\"` renders a centered no-card scroll for editorial sites. `layout=\"masonry\"` uses CSS columns for variable-height quotes.",
2248
- "tags": [
2249
- "ui",
2250
- "testimonials",
2251
- "section",
2252
- "marketing",
2253
- "social-proof",
2254
- "saas"
2255
- ]
2256
- },
2257
- {
2258
- "slug": "blog-section",
2259
- "title": "Blog Section",
2260
- "category": "ui",
2261
- "description": "Canonical blog list + detail section. <BlogListSection> renders 3 layouts (cards grid, minimal list, featured-split with hero + side rail). <BlogPostView> renders the single-post page with cover + meta + paragraph-split body. Both pass through `hrefFor`/`backHref` so each template controls routing — single SSOT for /blog and /blog/[slug] across all templates.",
2262
- "source": "rahman-resources",
2263
- "install": "npx rahman-resources add blog-section",
2264
- "npmPackages": [],
2265
- "exampleCode": "",
2266
- "agentRecipe": "Run `npx rr add blog-section`. <BlogListSection posts hrefFor title columns layout limit /> for /blog — `hrefFor(post)` returns the per-post URL. <BlogPostView post backHref renderBody /> for /blog/[slug] — `renderBody` defaults to paragraph-split on `\\n\\n` (swap for an MDX renderer if you use mdx-blog).",
2267
- "tags": [
2268
- "ui",
2269
- "blog",
2270
- "section",
2271
- "marketing",
2272
- "content",
2273
- "list",
2274
- "detail"
2275
- ]
2276
- },
2277
- {
2278
- "slug": "changelog-feed",
2279
- "title": "Changelog Feed",
2280
- "category": "ui",
2281
- "description": "Canonical /changelog or /whats-new section. Entries support 5 kinds (feature/improvement/fix/chore/breaking) with color-coded badges. Three layouts (timeline with date-rail, large cards, minimal list). Optional `limit` for \"Recent updates\" excerpts on home pages. Optional `groups` per entry for sub-sectioned bullet lists.",
2282
- "source": "rahman-resources",
2283
- "install": "npx rahman-resources add changelog-feed",
2284
- "npmPackages": [],
2285
- "exampleCode": "",
2286
- "agentRecipe": "Run `npx rr add changelog-feed`. <ChangelogFeedSection entries title subtitle layout sortDescending limit /> — only `entries` required. Each entry: `{ id, version, date, kind, title, body, bullets?, groups? }`. `layout=\"timeline\"` adds a left date-rail; `layout=\"list\"` is the most compact. Pass `limit={3}` on home pages to show recent releases.",
2287
- "tags": [
2288
- "ui",
2289
- "changelog",
2290
- "section",
2291
- "saas",
2292
- "release-notes",
2293
- "marketing"
2294
- ]
2295
- },
2296
- {
2297
- "slug": "portfolio-section",
2298
- "title": "Portfolio Section",
2299
- "category": "ui",
2300
- "description": "Canonical portfolio list + detail section. <PortfolioListSection> renders 3 layouts (uniform 16:9 grid, CSS masonry, asymmetric with featured hero). <PortfolioDetailView> renders title + meta + cover + body + gallery + external link + related items. Both pass through `hrefFor`/`backHref` so each template controls routing — single SSOT for /portfolio and /portfolio/[slug] across agency-studio and personal-brand.",
2301
- "source": "rahman-resources",
2302
- "install": "npx rahman-resources add portfolio-section",
2303
- "npmPackages": [],
2304
- "exampleCode": "",
2305
- "agentRecipe": "Run `npx rr add portfolio-section`. <PortfolioListSection items hrefFor title columns layout limit /> for /portfolio — each item `{ id, slug, title, summary?, year?, client?, role?, tags?, cover: {src,alt}, gallery?, link? }`. <PortfolioDetailView item backHref renderBody related hrefForRelated /> for /portfolio/[slug] — `renderBody` defaults to paragraph split; override for project-specific layouts (problem/approach/result, brief/outcome, etc).",
2306
- "tags": [
2307
- "ui",
2308
- "portfolio",
2309
- "section",
2310
- "marketing",
2311
- "case-study",
2312
- "list",
2313
- "detail"
2314
- ]
2315
- },
2316
2137
  {
2317
2138
  "slug": "theme-presets",
2318
2139
  "title": "Theme Presets — unified switcher with bundled tweakcn registry",
@@ -2356,206 +2177,160 @@
2356
2177
  ]
2357
2178
  },
2358
2179
  {
2359
- "slug": "equation",
2360
- "title": "EquationNotion-style KaTeX block primitive",
2180
+ "slug": "selection",
2181
+ "title": "Selectionmarquee multi-select + bulk actions",
2361
2182
  "category": "ui",
2362
- "description": "Inline-or-display LaTeX equation block Notion-inspired primitive. KaTeX-rendered with edit/preview toggle, raw-text fallback when KaTeX fails to parse. Pure UI primitive (zero Convex tables, zero global state). Lifted from notion-page-clone (Nosion). Use standalone OR bundled via the notion-blocks bundle. Drop into any React surface docs, marketing landing, editor.",
2183
+ "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.",
2363
2184
  "source": "notion-page-clone",
2364
- "install": "npx rahman-resources add equation",
2185
+ "install": "npx rahman-resources add selection",
2365
2186
  "npmPackages": [],
2366
2187
  "exampleCode": "",
2367
- "agentRecipe": "Run `npx rr add equation`. Single npm dep: katex. Import `import { EquationBlock } from \"@/features/equation\"`. Props-driven: pass `value` (LaTeX string) + `onChange`. For display-mode (block-level) pass `displayMode`. Renders raw text if KaTeX parse fails. Bundled inside notion-blocks if you also want code/notify/drag-fill.",
2188
+ "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.",
2368
2189
  "tags": [
2369
2190
  "ui",
2191
+ "selection",
2192
+ "marquee",
2193
+ "rubber-band",
2194
+ "multi-select",
2195
+ "bulk",
2370
2196
  "notion",
2371
- "notion-like",
2372
- "equation",
2373
- "katex",
2374
- "latex",
2375
- "math",
2376
- "block",
2377
- "primitive",
2378
- "editor"
2197
+ "blocks",
2198
+ "list"
2379
2199
  ]
2380
2200
  },
2381
2201
  {
2382
- "slug": "code-block",
2383
- "title": "Code Block — Notion-style syntax-highlighted code primitive",
2202
+ "slug": "notion-database",
2203
+ "title": "Notion Database",
2384
2204
  "category": "ui",
2385
- "description": "Highlight.js-powered code block — Notion-inspired primitive. Language selector dropdown (auto-detect + 50+ language packs), copy-to-clipboard button, line-wrap toggle. Pure-UI primitive no Convex tables. Lifted from notion-page-clone (Nosion). Use standalone OR bundled via notion-blocks.",
2386
- "source": "notion-page-clone",
2387
- "install": "npx rahman-resources add code-block",
2205
+ "description": "Drop-in Notion-style database surface. 11 views (table, board, list, gallery, calendar, feed, chart, dashboard, form, map, timeline), 18 property/cell types, and a per-type column-header config menu (number format, date ranges, select, relation, rollup, formula) plus filter / sort / group / calculate, row peek, row multi-select, table cell selection + drag-to-fill (click a cell, drag the handle to copy down — merged from the former database-cell-selection slice in v0.16), and CSV + JSON import-export. Pure and props-driventhe host owns the data and dispatches change callbacks. Domain types live in notion-shell (install it as the peer). Full release history in CHANGELOG.md.",
2206
+ "source": "open-silong",
2207
+ "install": "npx rahman-resources add notion-database",
2388
2208
  "npmPackages": [],
2389
2209
  "exampleCode": "",
2390
- "agentRecipe": "Run `npx rr add code-block`. Single npm dep: highlight.js. Import `import { CodeBlock, languageLabel } from \"@/features/code-block\"`. Props: `value` + `onChange` + `language` + `onLanguageChange`. Bundled inside notion-blocks if you also want equation/notify/drag-fill.",
2210
+ "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-database`. Cascades the `notion-shell` peer (the domain types live there). Components import from `@/features/notion-database`; types from `@/features/notion-shell`.\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-database';\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-database'` — and feed it `rows` + `renderCell` + `renderColumnHeader`.",
2391
2211
  "tags": [
2392
2212
  "ui",
2393
2213
  "notion",
2394
2214
  "notion-like",
2395
- "code",
2396
- "syntax",
2397
- "highlight",
2398
- "highlight.js",
2399
- "block",
2215
+ "database",
2216
+ "table",
2217
+ "board",
2218
+ "list",
2219
+ "gallery",
2220
+ "calendar",
2221
+ "feed",
2222
+ "chart",
2223
+ "dashboard",
2224
+ "form",
2225
+ "map",
2226
+ "timeline",
2227
+ "gantt",
2228
+ "kanban",
2229
+ "views",
2230
+ "filter",
2231
+ "sort",
2232
+ "property",
2233
+ "files",
2234
+ "person",
2235
+ "formula",
2236
+ "timestamp",
2237
+ "unique-id",
2238
+ "csv",
2239
+ "json",
2240
+ "import",
2241
+ "export",
2242
+ "template",
2243
+ "data",
2244
+ "backup",
2400
2245
  "primitive",
2401
- "editor"
2246
+ "optional",
2247
+ "embeddable"
2402
2248
  ]
2403
2249
  },
2404
2250
  {
2405
- "slug": "notifications",
2406
- "title": "NotificationsNotion-style per-page Notify Me",
2251
+ "slug": "image-picker",
2252
+ "title": "Image Picker one-button image/wallpaper chooser (gallery · upload · link · Unsplash · reposition)",
2407
2253
  "category": "ui",
2408
- "description": "Pure-client per-page subscription primitive — Notion-inspired bell button + popover. State stored in localStorage (no backend needed). Shipped as a `NotifyMePopover` toggled from a page-action bell. Frequency choices: instant / daily digest / weekly digest. Lifted from notion-page-clone (Nosion). Use standalone OR bundled via notion-blocks.",
2254
+ "description": "Generic image/wallpaper pickernot 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.",
2409
2255
  "source": "notion-page-clone",
2410
- "install": "npx rahman-resources add notifications",
2256
+ "install": "npx rahman-resources add image-picker",
2411
2257
  "npmPackages": [],
2412
2258
  "exampleCode": "",
2413
- "agentRecipe": "Run `npx rr add notifications`. Zero npm deps (only shadcn button + popover). Import `import { NotifyMePopover, useSubscription } from \"@/features/notifications\"`. Drop the popover anywhere; useSubscription(pageId) hook returns `{ isSubscribed, frequency, subscribe, unsubscribe, setFrequency }` reading from localStorage. To wire a real backend, swap the localStorage hook for your own.",
2259
+ "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.",
2414
2260
  "tags": [
2415
2261
  "ui",
2416
- "notion",
2417
- "notion-like",
2418
- "notifications",
2419
- "subscribe",
2420
- "notify",
2421
- "bell",
2422
- "popover",
2423
- "localstorage",
2424
- "primitive"
2425
- ]
2426
- },
2427
- {
2428
- "slug": "database-cell-selection",
2429
- "title": "Database Cell Selection — Notion-style drag-fill + multi-select",
2430
- "category": "ui",
2431
- "description": "Notion-style grid cell interaction primitives: drag-fill (Sheets/Excel-style range fill), multi-cell selection with shift-click + arrow-key extension, paste-from-clipboard column adapter. Pure-UI hooks + components, no Convex tables. Lifted from notion-page-clone (Nosion). Pair with any tabular UI (notion-shell databases, ag-grid, custom React table, etc.).",
2432
- "source": "notion-page-clone",
2433
- "install": "npx rahman-resources add database-cell-selection",
2434
- "npmPackages": [],
2435
- "exampleCode": "",
2436
- "agentRecipe": "Run `npx rr add database-cell-selection`. Zero deps. Import `import { useDragFill, SelectableCell, useCellSelection } from \"@/features/database-cell-selection\"`. Wrap your grid container with the selection hook; per-cell `<SelectableCell row col>` provides the click-and-drag affordance. Drag handles supplied by useDragFill. Composable with notion-shell's NotionDatabase or any custom grid.",
2437
- "tags": [
2438
- "ui",
2439
- "notion",
2440
- "notion-like",
2441
- "database",
2442
- "grid",
2443
- "cell",
2444
- "selection",
2445
- "drag-fill",
2446
- "spreadsheet",
2447
- "primitive",
2448
- "table"
2449
- ]
2450
- },
2451
- {
2452
- "slug": "notion-database",
2453
- "title": "Notion-like Database Table — full table with import/export + row peek + relation/rollup + row multi-select + calendar drag + DB-level menu + full-page shell + AST formula engine (11 views · 18 cells · CSV + JSON)",
2454
- "category": "ui",
2455
- "description": "Portable Notion-style database table surface — full capability in one slice. Optional companion to notion-shell — install shell alone for pages + sidebar + block editor, add notion-database when you want embedded databases with full table capability. Ships NotionDatabase (full DB UI w/ ViewTabs + ViewOptions + per-column menu + FilterBuilder/SortBuilder popovers), NotionProperty (value + schema editor), 16 property-cell types (text / number / checkbox / select / multi_select / status / date / url / email / phone / files / person / formula / created_time / last_edited_time / unique_id), 11 built-in views: Table / Board / List / Gallery / Calendar / Feed PLUS Chart (recharts bar/line/area/pie/donut + inline kind/X/agg/Y pickers) / Dashboard (KPI strip + group breakdowns + recent updates) / Form (public-facing submit-to-create — title + per-property inputs, optional required-field validation, configurable show/hide + success message via inline Settings panel) / Map (SVG world + lat/lng pins, no leaflet) / Timeline (Gantt-style with drag-to-shift / drag-to-resize). FilterBuilder + SortBuilder exported standalone for toolbar embedding. Formula cells use a pure expression engine ({{title}}/{{prop}} interpolation + concat/upper/lower/round/if/etc fns + `=expr` math). Files cells store URL refs (paste-URL workflow; host can plug `files` slice adapter for upload). Person cells are simplified vs upstream — no user directory lookup, just initials chips. Created_time / last_edited_time read row.createdAt / row.updatedAt directly. unique_id auto-derives from row position + optional prefix. Pure helpers: applyView, groupBy, bucketByDate. Domain types live in notion-shell (single source of truth — Page.rowOfDatabaseId + rowProps reference them) and re-exported here. Relation + rollup property types deferred to upstream open-silong mega-bundle (need cross-DB context). v0.5 added drop-in Convex backend templates (dual-mode: minimal single-user OR full multi-workspace) from open-silong's template-base/. v0.6 (Phase 7.10) merges former database-io slice in-tree: DatabaseIOActions toolbar (Export CSV/JSON · Import CSV/JSON · Download dynamic CSV/JSON templates), CsvImportDialog (auto-map columns + create-new-of-type picker), JsonImportDialog (schema diff + import), exportDatabase / exportDatabaseToCsv / parseExport / parseCsv / buildCsvTemplate / buildJsonTemplate helpers — all from `@/features/notion-database`. CsvNewProperty + JsonImportResult.newProperties now expose `tempId` so host can remap rowProps keys when persisting (single import handler serves both formats). Cell editor UX consolidated v0.5.3 — SelectCell + MultiSelectCell share OptionPicker (shared/identical popover: search-as-create + per-option rename/color/delete). Property-type lists single-source via PROPERTY_TYPE_META registry (v0.5.2). v0.7 (CK-1D Phase 1) lifts row-detail subsystem from notion-page-clone: RowPeek (sheet + dialog + persisted mode toggle via useRowOpenMode localStorage hook), RowDetailSheet (right drawer), RowDetailDialog (centered modal), RowDetailBody (shared chrome), RowOpenModeSwitcher (sheet/dialog/page toggle). Pure slot-driven — host supplies icon picker, properties form, and block editor via render slots (iconSlot, propertiesSlot, blocksSlot); no Convex / comments / editor coupling. onOpenAsPage callback wires one-shot navigation without changing the persisted default. v0.8 (CK-1D Phase 2) lifts relation + rollup cells: RelationCell (cross-database link picker w/ search + create-new-row affordance + stale-link healing) and RollupCell (read-only aggregate display — count / count_unique / values / sum / avg / min / max / earliest / latest / checked / percent_checked). PropertyType union extended with 'relation' and 'rollup'. Property gained relationDatabaseId / rollupRelationPropertyId / rollupTargetPropertyId / rollupAggregate fields. NotionDatabase added new props pages, databases, onCreateRelatedRow so host stays the source of truth — cells gracefully no-op when omitted. v0.9 (CK-1D Phase 3) lifts row multi-select subsystem: RowSelectionProvider (React Context holding selected id set + anchor; drops stale ids when rowOrder shrinks), RowMarqueeOverlay (drag-to-select rubber-band over any container w/ data-row-shell-id markers — AutoCAD window/crossing modes, threshold + long-press text-origin activation, additive shift-drag), RowSelectionToolbar (floating bottom-center action bar w/ N-rows-selected count, optional locked badge, host-supplied extraSlot, Delete button via onDelete callback, Clear via Esc/X), RowSelectionKeyboard (Esc clear + Del/Backspace bulk delete + outside-click dismiss). TableView automatically tags rows with data-row-shell-id and applies a primary-tinted ring when wrapped in RowSelectionProvider. Marquee primitive + useMarqueeDrag hook exported for reuse on Board / Gallery / custom views. v0.10 (CK-1D Phase 5) adds HeaderCheckboxGutter (tri-state select-all/clear w/ aria-checked='mixed' indeterminate) + RowCheckbox (per-row toggle) — TableView auto-renders a checkbox gutter column whenever a RowSelectionProvider is in scope. Pure calendarDrag helpers (parseExistingDate, formatDateValue, shiftYmd, computeDateShift, parseDropTargetId) exported for hosts wiring CalendarView/Timeline drag-to-move without taking on @dnd-kit coupling inside the slice. Column drag-reorder + row drag-reorder primitives deferred — upstream's flexbox-table refactor conflicts with rr's semantic <table> + 200-LOC view cap. v0.11 (CK-1D Phase 7) lifts Intl-based number + date formatters: lib/numberFormat.ts (resolveNumberFormat / formatPropertyNumber + COMMON_CURRENCIES 16-code picker) and lib/dateFormat.ts (parseYmdToLocal / formatYmd / formatTime / formatDateValue + DATE_FORMAT_LABELS / TIME_FORMAT_LABELS). Property gained numberCurrencyCode + dateFormat + timeFormat + dateIncludeTime fields. NumberCell currency now honours per-property ISO code; DateCell accepts an optional `prop` and routes through formatDateValue when any date-related field is set on it. Notion-shell DatabaseViewConfig split into ./view-config-types.ts to keep types.ts under the 200-LOC cap. v0.12 (CK-1D Phase 4) adds database-shell subsystem: DatabaseMenu (rename / duplicate {structure | with rows} / lock-toggle / delete popover — every action hidden when its callback is omitted; native window.confirm + window.prompt fallbacks keep zero new dialog deps) and DatabasePage (full-page wrapper composing a big header — icon slot + inline title input + DatabaseMenu — over a NotionDatabase body). NotionDatabase grew a `headerActions` render slot so hosts can drop a DatabaseMenu inline without switching to DatabasePage. Database type gained an optional `locked` flag. Strip vs upstream: useDbAdapter (Convex coupling) + SubItemsPicker (sub-items tree) + IconPickerPopover (lives in icon-picker slice) + DataMenu (database-json slice) deferred — host wires those externally. v0.13 (CK-1D Phase 6) replaces the flat formula.ts evaluator with a typed AST engine under lib/formulaEngine/ (types, coerce, dateUtils, ParserClass, parser, functions, evaluator, deps): recursive-descent parser w/ source-position tracking; typed FormulaValue (string/number/boolean/date/null/list) instead of string-only; circular-reference guard via visited set + per-row memoisation cache; new fn surface — substring, dateAdd, dateSubtract, dateBetween, formatDate, count, sum, join (on top of existing concat/lower/upper/length/if/and/or/not/empty/contains/replace/round/floor/ceil/abs/min/max/now/today). Relation refs in formulas now resolve via the workspace pages passed through NotionDatabase. FormulaCell upgraded — popover now shows parse-error message + source position; cell display flips to destructive style on invalid. Legacy evaluateFormula() string wrapper preserved for existing callers; new code should import evalFormula / formatFormulaValue from `@/features/notion-database`. collectDeps() exported for hosts wiring formula-dependency invalidation.",
2456
- "source": "open-silong",
2457
- "install": "npx rahman-resources add notion-database",
2458
- "npmPackages": [],
2459
- "exampleCode": "",
2460
- "agentRecipe": "Run `npx rr add notion-database` (cascades notion-shell as peer). Import: `import { NotionDatabase, NotionProperty, VIEW_REGISTRY, DatabaseIOActions, RowPeek } from \"@/features/notion-database\"`. NotionDatabase ships full props-driven DB UI — host owns rows + dispatches CRUD callbacks. For just one view in isolation, import the specific view component (TableView / BoardView / etc.). Property cells auto-render via renderPropertyCell helper. Pure helpers: applyView / groupBy / bucketByDate. For import/export, mount `<DatabaseIOActions db={db} rows={rows} onImport={async ({ newProperties, rows }) => { const tempToReal: Record<string, string> = {}; for (const np of newProperties) { const realId = await dispatchAddProperty(np); tempToReal[np.tempId] = realId; } for (const r of rows) { const rowId = await dispatchAddRow(r.title); for (const [propKey, v] of Object.entries(r.rowProps)) { await dispatchSetValue(rowId, tempToReal[propKey] ?? propKey, v); } } }} />` next to your DB toolbar — exports CSV/JSON + imports w/ schema diff + downloads dynamic templates from live db.properties. tempId on each new property lets host remap rowProps keys to its real backend ids. For backend persistence, copy template-base/database-silong/convex/ from the open-silong repo: handlers go to convex/, schema fragment merges into convex/schema.ts. Pick _shared/minimal/ (single-user, noop authz) or _shared/full/ (requires @convex-dev/auth + workspaces tables). See CONVEX-BACKEND.md.",
2461
- "tags": [
2462
- "ui",
2463
- "notion",
2464
- "notion-like",
2465
- "database",
2466
- "table",
2467
- "board",
2468
- "list",
2262
+ "image",
2263
+ "picker",
2264
+ "wallpaper",
2265
+ "cover",
2266
+ "upload",
2267
+ "unsplash",
2469
2268
  "gallery",
2470
- "calendar",
2471
- "feed",
2472
- "chart",
2473
- "dashboard",
2474
- "form",
2475
- "map",
2476
- "timeline",
2477
- "gantt",
2478
- "kanban",
2479
- "views",
2480
- "filter",
2481
- "sort",
2482
- "property",
2269
+ "reposition",
2483
2270
  "files",
2484
- "person",
2485
- "formula",
2486
- "timestamp",
2487
- "unique-id",
2488
- "csv",
2489
- "json",
2490
- "import",
2491
- "export",
2492
- "template",
2493
- "data",
2494
- "backup",
2495
2271
  "primitive",
2496
- "optional",
2497
- "embeddable"
2272
+ "portable",
2273
+ "dialog"
2498
2274
  ]
2499
2275
  },
2500
2276
  {
2501
- "slug": "database-io",
2502
- "title": "[DEPRECATED] Database IO merged into notion-database v0.6",
2277
+ "slug": "notion-sidebar",
2278
+ "title": "Notion Sidebartree nav + page CRUD (rename · drag · icon picker)",
2503
2279
  "category": "ui",
2504
- "description": "DEPRECATED all functionality merged into `notion-database` v0.6 (Phase 7.10, 2026-05-22). This slice is now a thin re-export shim from `@/features/notion-database` to keep existing consumers compiling. New code should `npx rr add notion-database` (now bundles CSV + JSON import/export + dynamic templates) instead of installing this separately. Slice will be removed in v1.0. Original surface (DatabaseIOActions / CsvImportDialog / JsonImportDialog / exportDatabase / buildCsvTemplate / buildJsonTemplate) remains exported from notion-database see its catalog entry. Merge rationale: 100% peer coupling to notion-database (every file imported Database/Page/Property types from it) + zero independent install path (always installed alongside notion-database in practice) = no modularity benefit from separation.",
2280
+ "description": "Standalone Notion-style tree-nav sidebar with full page CRUD, lifted out of notion-shell so it is reusable on its own. Props-driven + fully decoupled owns its own lightweight NotionSidebarPage type (id / title / icon / parentId), imports no other slice. Capabilities: click a row to open; DOUBLE-CLICK a title to rename inline; drag the grip to reorder AND reparent (a @dnd-kit sortable tree with horizontal-offset depth projection); collapse/expand subtrees; hover a row for +subpage / delete. Optional per-row icon PICKER — wire `renderIconPicker` + `onIconChange` (e.g. @/features/icon-picker's IconPickerPopover) so clicking a row icon opens the picker. The host owns the data and dispatches onSelect / onCreate / onRename / onDelete / onMove / onIconChange. Compose with notion-shell (page editor) + notion-database (embedded DBs) for the full Notion-clone OS — see the notion-page-clone-os template.",
2505
2281
  "source": "notion-page-clone",
2506
- "install": "npx rahman-resources add database-io",
2282
+ "install": "npx rahman-resources add notion-sidebar",
2507
2283
  "npmPackages": [],
2508
2284
  "exampleCode": "",
2509
- "agentRecipe": "⚠️ DEPRECATED — use `npx rr add notion-database` (now bundles import/export). This slice is a thin re-export shim from `@/features/notion-database` for back-compat. New code: `import { DatabaseIOActions } from \"@/features/notion-database\"`. Remove when migration complete; slice scheduled for removal in v1.0.",
2285
+ "agentRecipe": "Run `npx rr add notion-sidebar`. Import `import { NotionSidebar, type NotionSidebarPage } from \"@/features/notion-sidebar\"`. Feed it a flat `pages: NotionSidebarPage[]` ({ id, title, icon, parentId }) — the sidebar builds the tree. Wire callbacks: onSelect(id), onCreate(parentId|null), onRename(id, title) [double-click a title to trigger], onDelete(id), onMove(id, parentId, beforeId) [drag the grip — reorders + reparents], onIconChange(id, icon). For rich icons pass `renderIcon` (display) + `renderIconPicker` (click-to-pick) wired to `@/features/icon-picker` (DynamicIcon + IconPickerPopover). npm: @dnd-kit/core + sortable + utilities. Pair with notion-shell (page editor) + notion-database (embedded DBs) the notion-page-clone-os template shows the full reducer wiring.",
2510
2286
  "tags": [
2511
2287
  "ui",
2512
2288
  "notion",
2513
- "notion-like",
2514
- "database",
2515
- "csv",
2516
- "json",
2517
- "import",
2518
- "export",
2519
- "template",
2520
- "data",
2521
- "backup",
2522
- "spreadsheet",
2523
- "wire-format",
2289
+ "sidebar",
2290
+ "tree",
2291
+ "nav",
2292
+ "page",
2293
+ "crud",
2294
+ "rename",
2295
+ "drag",
2296
+ "dnd",
2297
+ "reorder",
2298
+ "reparent",
2299
+ "icon-picker",
2524
2300
  "primitive",
2525
- "optional"
2301
+ "portable",
2302
+ "notion-like"
2526
2303
  ]
2527
2304
  },
2528
2305
  {
2529
2306
  "slug": "notion-shell",
2530
- "title": "Notion Shell — page + sidebar + block editor primitives (pure, no database)",
2307
+ "title": "Notion Shell — page + block editor primitives (pure, no sidebar/database)",
2531
2308
  "category": "ui",
2532
- "description": "Portable Notion-style PAGE + SIDEBAR + BLOCK editor primitives. CI-wave (2026-05-21) split the database surface out install the optional `notion-database` peer for embedded TableView / BoardView / ListView / GalleryView / CalendarView / FeedView, NotionDatabase, NotionProperty, ViewTabs, ViewOptions, ColumnHeaderMenu, property-cells. notion-shell alone gives you Notion-clone pages + sidebar + editor without the database weight. Domain types (Database, Property, PropertyValue, DbView, DatabaseViewConfig, DatabaseFilter, DatabaseSort) remain in notion-shell as the single source of truth (Page.rowOfDatabaseId + rowProps reference them). FULL OLD DESC BELOW: Portable Notion-style wrapper primitives. PAGE EDITOR: NotionPage (optional cover image band + header + body), NotionHeader / NotionSidebar / NotionBlock (live inline-markdown decorator, hover actions menu, optional dragHandle slot), SlashMenu (searchable block-type picker w/ keyboard nav), BlockActionsMenu (turn-into / duplicate / delete), InsertBlockButton (`+` trigger w/ SlashMenu), SortableBlockList (@dnd-kit render-prop wrapper for block reorder), PageActionsMenu (header dropdown: cover/favorite/duplicate/export/trash). DATABASE: NotionDatabase (full DB surface w/ tabs + options + per-column menu), NotionProperty (10 property-cell types), 6 built-in views (Table/Board/List/Gallery/Calendar/Feed), ViewTabs, ViewOptions (sort + filter + search popover), ColumnHeaderMenu. SPECIALISED BLOCK RENDERERS: ImageRenderer (URL + caption + preview), EmbedRenderer (YouTube/Vimeo/Loom/Figma/CodePen/Spotify auto-detect + iframe fallback). Pure helpers: applyView, groupBy, bucketByDate. Pure / props-driven — host owns data + change handlers.",
2309
+ "description": "Portable Notion-style PAGE EDITOR primitives. v0.22 split the tree-nav SIDEBAR out into the standalone `notion-sidebar` slice (so the page editor and the sidebar are independently reusable); embedded DATABASES already live in the `notion-database` peer. notion-shell ships: NotionPage (optional cover image band + header + body), NotionHeader, NotionBlock (live inline-markdown decorator, hover actions menu, optional dragHandle slot, BUILT-IN code (highlight.js) + equation (KaTeX) blocks), SlashMenu (searchable block-type picker w/ keyboard nav), BlockActionsMenu (turn-into / duplicate / delete), InsertBlockButton (`+` trigger w/ SlashMenu), SortableBlockList (@dnd-kit render-prop wrapper for block reorder), PageActionsMenu (header dropdown: cover/favorite/duplicate/export/trash), InlineFormatToolbar + BlockColorPicker (colour) + MentionTypeahead + PageLayoutSection (layout). SPECIALISED BLOCK RENDERERS: ImageRenderer, EmbedRenderer (YouTube/Vimeo/Loom/Figma/CodePen/Spotify auto-detect). Domain types (Database, Property, PropertyValue, DbView, DatabaseViewConfig, DatabaseFilter, DatabaseSort) remain in notion-shell as the single source of truth (Page.rowOfDatabaseId + rowProps reference them). Pure / props-driven — host owns data + change handlers. Compose notion-sidebar + notion-shell + notion-database for the full Notion-clone OS.",
2533
2310
  "source": "notion-page-clone",
2534
2311
  "install": "npx rahman-resources add notion-shell",
2535
2312
  "npmPackages": [],
2536
2313
  "exampleCode": "",
2537
- "agentRecipe": "Run `npx rr add notion-shell` for the portable UI wrappers ONLY (no backend). NPM deps: @dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities. Import: `import { NotionPage, NotionSidebar, NotionBlock, NotionDatabase, SortableBlockList, PageActionsMenu, InsertBlockButton, ViewTabs, ImageRenderer, EmbedRenderer } from \"@/features/notion-shell\"`. NotionBlock ships slash menu + decorator + actions menu + dragHandle slot. NotionPage ships optional cover prop. SortableBlockList wraps a render-prop callback `(id, dragProps) => <NotionBlock dragHandle={...} />`. NotionDatabase ships 6 views via VIEW_REGISTRY. Property cells: text/number/checkbox/select/multi-select/status/date/url/email/phone all built in. For rich icon UX wire `renderIcon` + `renderIconPicker` to `@/features/icon-picker`. **PRODUCT POINTER: the full Convex-backed Notion-clone OS (multi-workspace + auth + sharing + comments + snapshots + MCP) lives at https://github.com/rahmanef63/open-silong — clone that repo for the production stack; use this slice when you only need to embed the Notion-style UI in another project.**",
2314
+ "agentRecipe": "Run `npx rr add notion-shell` for the portable PAGE EDITOR wrappers ONLY (no backend; the tree-nav sidebar is the separate `notion-sidebar` slice). NPM deps: @dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities. Import: `import { NotionPage, NotionBlock, SortableBlockList, PageActionsMenu, InsertBlockButton, InlineFormatToolbar, ImageRenderer, EmbedRenderer } from \"@/features/notion-shell\"`. NotionBlock ships slash menu + decorator + actions menu + dragHandle slot. **`createDefaultBlockRenderers()` returns the block-renderer registry — pass it to `<NotionBlock blockRenderers={…}>` so callout (icon+kind picker), table (editable grid), divider, image, embed, code (highlight.js) + equation (KaTeX) all render. code + equation are now BUILT-IN to notion-shell (npm: katex + highlight.js) — no adapter needed. Only `database` + `toc` are injected at the app level (they depend on host data + the sibling notion-database slice).** NotionPage ships optional cover prop. SortableBlockList wraps a render-prop callback `(id, dragProps) => <NotionBlock dragHandle={...} />`. NotionDatabase ships 6 views via VIEW_REGISTRY. Property cells: text/number/checkbox/select/multi-select/status/date/url/email/phone all built in. For rich icon UX wire `renderIcon` + `renderIconPicker` to `@/features/icon-picker`. **v0.17 — Notion-canonical editing keys (`blockKeyHandler.ts`): Enter splits at the caret into a new block (lists continue their type; an empty list item exits to paragraph); Backspace on an empty non-paragraph downgrades it to a plain paragraph (re-triggerable with `/`); a second Backspace on an empty paragraph merges into the previous block; Arrow up/down at a line edge hops blocks. Wire the host callbacks on `<NotionBlock>`: `onInsertAfter(type, init) => newId`, `onMergeBack()`, `onFocusSibling(dir)` — plus `focusBlock(id, offset?)` exported to move the caret after a host state change. The preview `page-demo.tsx` and the notion-clone template `DocView` show full array- and reducer-based wirings.** PRODUCT POINTER: the full Convex-backed Notion-clone OS (multi-workspace + auth + sharing + comments + snapshots + MCP) lives at https://github.com/rahmanef63/open-silong — clone that repo for the production stack; use this slice when you only need to embed the Notion-style UI in another project.**",
2538
2315
  "tags": [
2539
2316
  "ui",
2540
2317
  "notion",
2541
2318
  "shell",
2542
2319
  "wrapper",
2543
- "sidebar",
2544
2320
  "page",
2545
- "database",
2321
+ "block",
2322
+ "editor",
2546
2323
  "primitive",
2547
2324
  "portable",
2548
2325
  "slash-menu",
2549
2326
  "decorator",
2550
2327
  "wysiwyg",
2551
- "views",
2552
- "kanban",
2553
- "calendar",
2554
- "gallery",
2555
2328
  "drag",
2556
2329
  "cover",
2557
2330
  "embed",
2558
2331
  "image",
2332
+ "code",
2333
+ "equation",
2559
2334
  "notion-like"
2560
2335
  ]
2561
2336
  },
@@ -2604,13 +2379,137 @@
2604
2379
  }
2605
2380
  ],
2606
2381
  "slices": [
2382
+ {
2383
+ "slug": "image-editor",
2384
+ "title": "Image Editor — Photoshop-style canvas (Konva)",
2385
+ "category": "ui",
2386
+ "kind": "full",
2387
+ "version": "1.0.0",
2388
+ "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 (brightness/contrast/hue/saturation/blur/grayscale/invert/sepia, applied via Konva.Filters), canvas resize/aspect presets, and Photoshop-style LAYER STYLES: stroke, drop shadow (angle/distance/size/opacity), outer glow, clipping mask (clip to layer below), per-layer blend mode. One-click BACKGROUND REMOVAL runs fully in-browser via @imgly/background-removal (free, MIT, no API key, no server — downloads a small ONNX model to the browser cache on first use) and drops the cutout back as a transparent layer. Undo/redo, zoom/pan, keyboard shortcuts, and PNG/JPG/WebP export at 1×/2×/3×. Self-contained: image I/O is via props (initialImage / onSave) so it drops into any app with zero backend.",
2389
+ "source": "rahmanef63/os-vps",
2390
+ "slicePath": "frontend/slices/image-editor",
2391
+ "convexPaths": [],
2392
+ "npm": [
2393
+ "konva",
2394
+ "react-konva",
2395
+ "@imgly/background-removal",
2396
+ "lucide-react"
2397
+ ],
2398
+ "shadcn": [
2399
+ "button",
2400
+ "input",
2401
+ "slider",
2402
+ "select",
2403
+ "tabs",
2404
+ "scroll-area",
2405
+ "separator",
2406
+ "tooltip",
2407
+ "label",
2408
+ "switch",
2409
+ "popover",
2410
+ "resizable"
2411
+ ],
2412
+ "env": [],
2413
+ "peers": [],
2414
+ "providers": [],
2415
+ "tags": [
2416
+ "image-editor",
2417
+ "photoshop",
2418
+ "canvas",
2419
+ "konva",
2420
+ "layers",
2421
+ "filters",
2422
+ "background-removal",
2423
+ "paint",
2424
+ "crop",
2425
+ "ui"
2426
+ ],
2427
+ "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."
2428
+ },
2429
+ {
2430
+ "slug": "file-explorer",
2431
+ "title": "File Explorer — Tree + CRUD + Breadcrumb",
2432
+ "category": "ui",
2433
+ "kind": "full",
2434
+ "version": "1.0.0",
2435
+ "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.",
2436
+ "source": "rahmanef63/os-vps",
2437
+ "slicePath": "frontend/slices/file-explorer",
2438
+ "convexPaths": [],
2439
+ "npm": [
2440
+ "lucide-react"
2441
+ ],
2442
+ "shadcn": [
2443
+ "button",
2444
+ "input",
2445
+ "scroll-area",
2446
+ "separator",
2447
+ "dropdown-menu",
2448
+ "sheet"
2449
+ ],
2450
+ "env": [],
2451
+ "peers": [],
2452
+ "providers": [],
2453
+ "tags": [
2454
+ "files",
2455
+ "file-manager",
2456
+ "explorer",
2457
+ "tree",
2458
+ "breadcrumb",
2459
+ "crud",
2460
+ "sidebar",
2461
+ "ui"
2462
+ ],
2463
+ "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."
2464
+ },
2465
+ {
2466
+ "slug": "appshell",
2467
+ "title": "AppShell — Desktop + Mobile OS Shell",
2468
+ "category": "ui",
2469
+ "kind": "full",
2470
+ "version": "1.0.0",
2471
+ "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).",
2472
+ "source": "rahmanef63/os-vps",
2473
+ "slicePath": "frontend/slices/appshell",
2474
+ "convexPaths": [],
2475
+ "npm": [
2476
+ "lucide-react",
2477
+ "class-variance-authority",
2478
+ "clsx",
2479
+ "tailwind-merge",
2480
+ "vaul"
2481
+ ],
2482
+ "shadcn": [
2483
+ "button",
2484
+ "tooltip",
2485
+ "scroll-area",
2486
+ "sheet",
2487
+ "drawer",
2488
+ "dialog",
2489
+ "alert-dialog",
2490
+ "dropdown-menu"
2491
+ ],
2492
+ "env": [],
2493
+ "peers": [],
2494
+ "providers": [],
2495
+ "tags": [
2496
+ "shell",
2497
+ "window-manager",
2498
+ "desktop",
2499
+ "mobile",
2500
+ "responsive",
2501
+ "framework",
2502
+ "ui"
2503
+ ],
2504
+ "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\")."
2505
+ },
2607
2506
  {
2608
2507
  "slug": "convex-auth",
2609
2508
  "title": "Convex Auth — Multi-Provider Sign-in",
2610
2509
  "category": "auth",
2611
2510
  "kind": "backend",
2612
- "version": "0.2.1",
2613
- "description": "@convex-dev/auth with Password (PBKDF2-SHA256 100k, self-hosted-friendly), Anonymous (guest), Google OAuth, and Resend magic-link. Ships a production SignInPage with i18n, prop-driven provider list, and split Login/Register tabs. No Clerk.",
2511
+ "version": "0.3.0",
2512
+ "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.",
2614
2513
  "source": "rahmanef63/resource-site",
2615
2514
  "slicePath": "frontend/slices/convex-auth",
2616
2515
  "convexPaths": [
@@ -2627,7 +2526,8 @@
2627
2526
  "input",
2628
2527
  "label",
2629
2528
  "tabs",
2630
- "alert"
2529
+ "alert",
2530
+ "input-otp"
2631
2531
  ],
2632
2532
  "env": [
2633
2533
  {
@@ -2795,12 +2695,13 @@
2795
2695
  "title": "Resend — Transactional & Newsletter",
2796
2696
  "category": "email",
2797
2697
  "kind": "backend",
2798
- "version": "0.1.2",
2799
- "description": "Transactional email + newsletter blast via Resend. Double opt-in flow + audience segmentation. Magic-link delivery for Convex Auth.",
2698
+ "version": "0.1.3",
2699
+ "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.",
2800
2700
  "source": "rahmanef63/resource-site",
2801
2701
  "slicePath": "frontend/slices/resend-newsletter",
2802
2702
  "convexPaths": [
2803
- "convex/features/newsletter"
2703
+ "convex/features/newsletter",
2704
+ "convex/features/subscribers"
2804
2705
  ],
2805
2706
  "npm": [
2806
2707
  "resend@^4.0.0"
@@ -2838,7 +2739,7 @@
2838
2739
  "title": "AI Chat — Workbench / Sidebar / Search",
2839
2740
  "category": "ai",
2840
2741
  "kind": "full",
2841
- "version": "0.1.0",
2742
+ "version": "0.2.0",
2842
2743
  "description": "One conversational AI feature, three render modes. Same Convex backend (threads + streaming + tool calls + RAG), pick the surface via prop:\n\n • workbench — Claude.ai / ChatGPT three-column page (default)\n • sidebar — collapsible copilot panel inside another CRUD app\n • search — single-question + answer + citations (Perplexity)\n\nUse cases:\n – Customer-support chatbot embedded in your marketing site\n – Developer copilot in your PR/docs admin\n – Knowledge-base search over your blog + docs corpus\n – Internal AI assistant in your dashboard\n\nWhat it ships: multi-provider (Anthropic / OpenAI / Google / Mistral / Ollama), multimodal (text + image + PDF + audio), typed tool calls with inline inspector, agent mode (plan→execute→reflect), branching threads, RAG citations, resumable streams, usage telemetry. Public surface = consumer chat; admin surface = persona, fallback, guardrails per-bot.",
2843
2744
  "source": "rahmanef63/resource-site",
2844
2745
  "slicePath": "frontend/slices/ai-chat",
@@ -3178,35 +3079,6 @@
3178
3079
  ],
3179
3080
  "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."
3180
3081
  },
3181
- {
3182
- "slug": "mdx-blog",
3183
- "title": "MDX Blog",
3184
- "category": "content",
3185
- "kind": "ui",
3186
- "version": "0.2.0",
3187
- "description": "Markdown-with-JSX untuk blog post. File-based MDX content collection. Portable defineMdxBlog(opts) factory dengan 4 config props (basePath, contentDir, labels.list, nav) — defaults preserve legacy /blog + content/blog. Auto-generate ToC, reading-time, syntax highlight, plus embed React components inline.",
3188
- "source": "rahmanef63/resource-site",
3189
- "slicePath": "frontend/slices/mdx-blog",
3190
- "convexPaths": [],
3191
- "npm": [
3192
- "@next/mdx@^16.0.0",
3193
- "gray-matter@^4.0.3",
3194
- "rehype-pretty-code@^0.14.0"
3195
- ],
3196
- "shadcn": [
3197
- "card"
3198
- ],
3199
- "env": [],
3200
- "peers": [],
3201
- "providers": [],
3202
- "tags": [
3203
- "content",
3204
- "blog",
3205
- "mdx",
3206
- "static"
3207
- ],
3208
- "agentRecipe": "Run `npx rr add mdx-blog`. Store post body sebagai markdown di content/blog/*.mdx. Render dengan MDXRemote di [slug]/page.tsx. Auto-extract headings ke ToC via remark plugin custom."
3209
- },
3210
3082
  {
3211
3083
  "slug": "cal-com-booking",
3212
3084
  "title": "Cal.com Booking",
@@ -3247,32 +3119,6 @@
3247
3119
  ],
3248
3120
  "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."
3249
3121
  },
3250
- {
3251
- "slug": "full-width-toggle",
3252
- "title": "Full Width Toggle",
3253
- "category": "ui",
3254
- "kind": "ui",
3255
- "version": "0.1.1",
3256
- "description": "Page-container width toggle (contained / wide / full). Per-device localStorage + cross-tab sync. Ships useFullWidth hook + FullWidthToggle button (icon/button/segment variants) + WidthContainer wrapper. Zero backend, zero env.",
3257
- "source": "rahmanef63/resource-site",
3258
- "slicePath": "frontend/slices/full-width-toggle",
3259
- "convexPaths": [],
3260
- "npm": [],
3261
- "shadcn": [
3262
- "button"
3263
- ],
3264
- "env": [],
3265
- "peers": [],
3266
- "providers": [],
3267
- "tags": [
3268
- "ui",
3269
- "layout",
3270
- "preference",
3271
- "localstorage",
3272
- "dashboard"
3273
- ],
3274
- "agentRecipe": "Run `npx rr add full-width-toggle`. Drop <WidthContainer> around page content, <FullWidthToggle variant='icon' /> in topbar. Variant 'segment' best for settings page. Hook useFullWidth() returns [mode, setMode, cycle]. SSR-safe — defaults to 'contained' until hydrate."
3275
- },
3276
3122
  {
3277
3123
  "slug": "command-menu",
3278
3124
  "title": "Command Menu",
@@ -3376,13 +3222,7 @@
3376
3222
  "tooltip"
3377
3223
  ],
3378
3224
  "env": [],
3379
- "peers": [
3380
- {
3381
- "slug": "full-width-toggle",
3382
- "range": "^0.1",
3383
- "reason": "Topbar surfaces the width toggle when this is mounted."
3384
- }
3385
- ],
3225
+ "peers": [],
3386
3226
  "providers": [],
3387
3227
  "tags": [
3388
3228
  "ui",
@@ -3451,30 +3291,34 @@
3451
3291
  },
3452
3292
  {
3453
3293
  "slug": "rbac-roles",
3454
- "title": "RBAC — Tiered System Roles",
3294
+ "title": "RBAC — Roles & Permissions",
3455
3295
  "category": "auth",
3456
- "kind": "backend",
3457
- "version": "0.1.0",
3458
- "description": "Workspace-scoped RBAC with 6 system roles (owner/admin/manager/staff/client/guest) and three tier presets solo, influencer, organization. Env-based platform admin bypass via PLATFORM_ADMIN_EMAILS. checkPermission / requirePermission helpers, role seeding mutation, @convex-dev/auth aware (no Clerk).",
3296
+ "kind": "full",
3297
+ "version": "0.2.0",
3298
+ "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.",
3459
3299
  "source": "superspace",
3460
- "slicePath": "",
3300
+ "slicePath": "frontend/slices/rbac-roles",
3461
3301
  "convexPaths": [
3462
- "template-base/convex/lib/rbac"
3302
+ "convex/features/rbac-roles"
3463
3303
  ],
3464
3304
  "npm": [],
3465
- "shadcn": [],
3305
+ "shadcn": [
3306
+ "badge",
3307
+ "checkbox",
3308
+ "label"
3309
+ ],
3466
3310
  "env": [
3467
3311
  {
3468
3312
  "name": "PLATFORM_ADMIN_EMAILS",
3469
3313
  "scope": "convex",
3470
- "description": "Comma-separated emails granted cross-workspace admin."
3314
+ "description": "Comma-separated emails granted cross-tenant superadmin (`*`)."
3471
3315
  }
3472
3316
  ],
3473
3317
  "peers": [
3474
3318
  {
3475
3319
  "slug": "convex-auth",
3476
3320
  "range": "^0.1",
3477
- "reason": "RBAC checks the authed user identity."
3321
+ "reason": "RBAC checks resolve the authed user via getAuthUserId."
3478
3322
  }
3479
3323
  ],
3480
3324
  "providers": [],
@@ -3483,35 +3327,91 @@
3483
3327
  "auth",
3484
3328
  "permissions",
3485
3329
  "roles",
3486
- "workspaces"
3330
+ "authorization",
3331
+ "no-clerk",
3332
+ "convex"
3487
3333
  ],
3488
- "agentRecipe": "Run `npx rr add rbac-roles`. Three tier presets pick which system roles to seed: solo (owner+admin), influencer (+manager), organization (6 roles). Platform admin via env PLATFORM_ADMIN_EMAILS bypasses all checks. Resolution: platform admin workspace owner membership.additionalPermissions role.permissions."
3334
+ "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)."
3489
3335
  },
3490
3336
  {
3491
- "slug": "admin-panel",
3492
- "title": "Admin Panel — Unified Product Admin",
3493
- "category": "infra",
3337
+ "slug": "user-management",
3338
+ "title": "User Management",
3339
+ "category": "auth",
3494
3340
  "kind": "full",
3495
- "version": "0.1.0",
3496
- "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.",
3497
- "source": "superspace + spec",
3498
- "slicePath": "template-base/frontend/slices/admin-panel",
3341
+ "version": "0.6.0",
3342
+ "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.",
3343
+ "source": "superspace",
3344
+ "slicePath": "frontend/slices/user-management",
3499
3345
  "convexPaths": [
3500
- "template-base/convex/features/admin-panel"
3346
+ "convex/features/user-management"
3501
3347
  ],
3502
3348
  "npm": [],
3503
3349
  "shadcn": [
3504
- "card",
3350
+ "avatar",
3505
3351
  "badge",
3506
- "button"
3352
+ "button",
3353
+ "checkbox",
3354
+ "dialog",
3355
+ "dropdown-menu",
3356
+ "input",
3357
+ "label",
3358
+ "select",
3359
+ "switch",
3360
+ "table",
3361
+ "tabs",
3362
+ "textarea"
3507
3363
  ],
3508
3364
  "env": [],
3509
3365
  "peers": [
3510
3366
  {
3511
3367
  "slug": "rbac-roles",
3512
- "range": "^0.1",
3513
- "reason": "Admin sections require RBAC perms must seed roles first."
3514
- }
3368
+ "range": "^0.2",
3369
+ "reason": "Roles + resolved permissions + convex permission helpers (requirePermission, getActorPermissions)."
3370
+ },
3371
+ {
3372
+ "slug": "convex-auth",
3373
+ "range": "^0.1",
3374
+ "reason": "Member identity (name/email/avatar) joined from the users table."
3375
+ }
3376
+ ],
3377
+ "providers": [],
3378
+ "tags": [
3379
+ "user-management",
3380
+ "members",
3381
+ "rbac",
3382
+ "auth",
3383
+ "team",
3384
+ "admin",
3385
+ "convex",
3386
+ "no-clerk"
3387
+ ],
3388
+ "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."
3389
+ },
3390
+ {
3391
+ "slug": "admin-panel",
3392
+ "title": "Admin Panel — Unified Product Admin",
3393
+ "category": "infra",
3394
+ "kind": "full",
3395
+ "version": "0.1.0",
3396
+ "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.",
3397
+ "source": "superspace + spec",
3398
+ "slicePath": "template-base/frontend/slices/admin-panel",
3399
+ "convexPaths": [
3400
+ "template-base/convex/features/admin-panel"
3401
+ ],
3402
+ "npm": [],
3403
+ "shadcn": [
3404
+ "card",
3405
+ "badge",
3406
+ "button"
3407
+ ],
3408
+ "env": [],
3409
+ "peers": [
3410
+ {
3411
+ "slug": "rbac-roles",
3412
+ "range": "^0.1",
3413
+ "reason": "Admin sections require RBAC perms — must seed roles first."
3414
+ }
3515
3415
  ],
3516
3416
  "providers": [],
3517
3417
  "tags": [
@@ -3629,90 +3529,6 @@
3629
3529
  ],
3630
3530
  "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."
3631
3531
  },
3632
- {
3633
- "slug": "i18n-translate",
3634
- "title": "i18n — Google Translate widget",
3635
- "category": "ui",
3636
- "kind": "ui",
3637
- "version": "0.1.0",
3638
- "description": "Drop-in Google Translate widget. Replaces hand-maintained locale dictionaries with on-the-fly translation to a curated locale list (16 default, prop-override). No API key, no Google Cloud billing. Auto-detect browser language on first visit, persist user choice via localStorage, click-to-reload language switching with router-refresh + in-place fallback strategies. Lifted 2026-05-27 from rahmanef.com; 510-LOC monolith split into 8 sub-files for the 200-LOC cap; project-specific Tailwind utilities stripped from defaults.",
3639
- "source": "rahmanef.com",
3640
- "slicePath": "frontend/slices/i18n-translate",
3641
- "convexPaths": [],
3642
- "npm": [
3643
- "lucide-react@^0.400.0",
3644
- "next@^15",
3645
- "react@^18"
3646
- ],
3647
- "shadcn": [],
3648
- "env": [],
3649
- "peers": [],
3650
- "providers": [],
3651
- "tags": [
3652
- "i18n",
3653
- "translate",
3654
- "google-translate",
3655
- "ui",
3656
- "language-switcher",
3657
- "locale",
3658
- "widget"
3659
- ],
3660
- "agentRecipe": "Run `npx rr add i18n-translate`. Mount `<GoogleTranslate />` anywhere (e.g. header). Add the CSP allowlist from README.md to your middleware/proxy — without it Google's script fails silently. Override `languages`, `storageKey`, and the four `*ClassName` props for per-project styling. Default `fallbackRefresh=\"reload\"` is the only path that works reliably across Next Cache Components — only opt into `\"router\"` or `\"none\"` if you've tested it on your tree."
3661
- },
3662
- {
3663
- "slug": "cta",
3664
- "title": "Call to Action",
3665
- "category": "ui",
3666
- "kind": "ui",
3667
- "version": "0.1.0",
3668
- "description": "Brutalist call-to-action section — eyebrow label, serif headline, body, arrow CTA. Pair with CtaButton standalone for inline placements. Lifted 2026-05-16 from rahmanef.com; assumes Tailwind tracking-brutal / tracking-brutal-sm utilities OR drop them for the default tracking scale.",
3669
- "source": "rahmanef.com",
3670
- "slicePath": "frontend/slices/cta",
3671
- "convexPaths": [],
3672
- "npm": [
3673
- "lucide-react@^0.400.0"
3674
- ],
3675
- "shadcn": [],
3676
- "env": [],
3677
- "peers": [],
3678
- "providers": [],
3679
- "tags": [
3680
- "ui",
3681
- "marketing",
3682
- "cta",
3683
- "section",
3684
- "brutalist"
3685
- ],
3686
- "agentRecipe": "Run `npx rr add cta`. <CtaView eyebrow title body href ctaLabel /> renders the full section; <CtaButton href label /> drops a standalone arrow button anywhere. Override tracking-brutal utilities in tailwind.config or swap for tracking-wide if your design system has no brutal preset."
3687
- },
3688
- {
3689
- "slug": "hero",
3690
- "title": "Hero",
3691
- "category": "ui",
3692
- "kind": "ui",
3693
- "version": "0.1.1",
3694
- "description": "Editorial split-grid landing hero — eyebrow pill + large serif H1 + italic pull-quote + 1-2 button CTA row + right-column portrait card with optional caption. Fully props-driven (title/quote/ctas/image). Sanitized from rahmanef.com on 2026-05-16: SITE_CONFIG hardcode dropped, custom Heading/Section primitives replaced with raw semantic elements + stock Tailwind tracking-widest so the slice ships without consumer preset utilities.",
3695
- "source": "rahmanef.com",
3696
- "slicePath": "frontend/slices/hero",
3697
- "convexPaths": [],
3698
- "npm": [
3699
- "lucide-react@^0.400.0"
3700
- ],
3701
- "shadcn": [],
3702
- "env": [],
3703
- "peers": [],
3704
- "providers": [],
3705
- "tags": [
3706
- "ui",
3707
- "hero",
3708
- "marketing",
3709
- "landing",
3710
- "section",
3711
- "editorial",
3712
- "brutalist"
3713
- ],
3714
- "agentRecipe": "Run `npx rr add hero`. <HeroView title eyebrow quote ctas image imageCaption /> — all props optional except title. Pass `image={undefined}` for text-only hero (auto-collapses to single 12-column row). Pairs visually with cta slice (same brutalist border + serif scale)."
3715
- },
3716
3532
  {
3717
3533
  "slug": "rate-limit",
3718
3534
  "title": "Rate Limit",
@@ -3739,45 +3555,6 @@
3739
3555
  ],
3740
3556
  "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. Call `api.features.rate_limit.mutations.consume({ key, limit, windowMs })` from server-side handlers — keep a fail-open wrapper so a Convex outage doesn't 503 the route."
3741
3557
  },
3742
- {
3743
- "slug": "subscribers",
3744
- "title": "Subscribers",
3745
- "category": "email",
3746
- "kind": "backend",
3747
- "version": "0.1.0",
3748
- "description": "Newsletter list with honeypot + per-email rate-limit + token-based unsubscribe + admin remove. Public `subscribe` returns status strings (`created` / `already` / `resubscribed` / `honeypot`); admin `listAll` / `count` queries gated by `requireAdmin` (rr `_shared/auth`). Lifted 2026-05-16 from rahmanef.com; sanitized: token args dropped, sibling `analyticsEvents` insert removed — wrap subscribe in a consumer action if you want funnel telemetry.",
3749
- "source": "rahmanef.com",
3750
- "slicePath": "frontend/slices/subscribers",
3751
- "convexPaths": [
3752
- "convex/features/subscribers"
3753
- ],
3754
- "npm": [],
3755
- "shadcn": [],
3756
- "env": [
3757
- {
3758
- "name": "SUPER_ADMIN_EMAIL",
3759
- "scope": "convex",
3760
- "required": false,
3761
- "description": "Optional super-admin gate for admin queries."
3762
- }
3763
- ],
3764
- "peers": [
3765
- {
3766
- "slug": "convex-auth",
3767
- "range": "^0.1",
3768
- "reason": "requireAdmin uses getAuthUserId from @convex-dev/auth."
3769
- }
3770
- ],
3771
- "providers": [],
3772
- "tags": [
3773
- "email",
3774
- "newsletter",
3775
- "subscribers",
3776
- "convex",
3777
- "backend"
3778
- ],
3779
- "agentRecipe": "Run `npx rr add subscribers`. Compose `subscribersTables` into root convex/schema.ts. Public form posts `api.features.subscribers.mutations.subscribe({ email, source, website })` — `website` is the honeypot, leave it `\"\"` from the form. Render unsubscribe link `/unsubscribe?t=<token>` and call `unsubscribe({ token })`."
3780
- },
3781
3558
  {
3782
3559
  "slug": "testimonials",
3783
3560
  "title": "Testimonials",
@@ -3855,45 +3632,6 @@
3855
3632
  ],
3856
3633
  "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."
3857
3634
  },
3858
- {
3859
- "slug": "socials",
3860
- "title": "Socials",
3861
- "category": "content",
3862
- "kind": "backend",
3863
- "version": "0.1.1",
3864
- "description": "Single source of truth for profile/social links. Powers JSON-LD `Person.sameAs` (Google entity graph), IndieWeb `<link rel=\"me\">` tags, and footer/contact/about UI surfaces. URL-deduped, ordered, `visible` / `featured` / `relMe` / `sameAs` flags. Lifted 2026-05-16 from rahmanef.com; token-based admin gate swapped, baked-in 14-platform rahmanef seed dropped — `seed` now takes items via args so each adopter ships their own list.",
3865
- "source": "rahmanef.com",
3866
- "slicePath": "frontend/slices/socials",
3867
- "convexPaths": [
3868
- "convex/features/socials"
3869
- ],
3870
- "npm": [],
3871
- "shadcn": [],
3872
- "env": [
3873
- {
3874
- "name": "SUPER_ADMIN_EMAIL",
3875
- "scope": "convex",
3876
- "required": false
3877
- }
3878
- ],
3879
- "peers": [
3880
- {
3881
- "slug": "convex-auth",
3882
- "range": "^0.1",
3883
- "reason": "requireAdmin uses getAuthUserId from @convex-dev/auth."
3884
- }
3885
- ],
3886
- "providers": [],
3887
- "tags": [
3888
- "content",
3889
- "socials",
3890
- "seo",
3891
- "indieweb",
3892
- "convex",
3893
- "backend"
3894
- ],
3895
- "agentRecipe": "Run `npx rr add socials`. Compose `socialsTables` into root schema. Bootstrap with `npx convex run internal.features.socials.mutations.seed '{\"items\":[{\"platform\":\"github\",\"url\":\"https://github.com/<you>\",\"order\":1,\"visible\":true,\"featured\":true,\"sameAs\":true,\"relMe\":true}]}'`. Wire `useQuery(api.features.socials.queries.listVisible)` into footer for entity-graph SEO."
3896
- },
3897
3635
  {
3898
3636
  "slug": "create-your-mcp",
3899
3637
  "title": "Create Your MCP",
@@ -4119,7 +3857,7 @@
4119
3857
  "category": "content",
4120
3858
  "kind": "full",
4121
3859
  "version": "0.2.1",
4122
- "description": "Polymorphic-target threaded comments. Consumer picks `TargetRef = { kind, id, subId? }` (e.g. page+block, blog+slug, task+id). Renderless <CommentsThread> + <CommentsAnchor> wrappers. useComments(bindings, opts) hook returns items + openCount + CRUD + forbiddenWords guard. Adapter pattern — see contract-negotiations §1.",
3860
+ "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.",
4123
3861
  "source": "rahmanef63/resource-site",
4124
3862
  "slicePath": "frontend/slices/comments",
4125
3863
  "convexPaths": [
@@ -4188,121 +3926,51 @@
4188
3926
  "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."
4189
3927
  },
4190
3928
  {
4191
- "slug": "document-checklist",
4192
- "title": "Document Checklist Job-Search Doc Tracker",
3929
+ "slug": "markdown",
3930
+ "title": "Markdownpage container with CRUD tabs + diagrams",
4193
3931
  "category": "content",
4194
- "kind": "full",
4195
- "version": "0.1.0",
4196
- "description": "Track required job-search documents (CV, KTP, ijazah, etc.) with country-scoped seed templates and per-user completion state. Ships an Indonesian default checklist. Toggle completed + notes + expiry per item.",
4197
- "source": "rahmanef63/CareerPack",
4198
- "slicePath": "frontend/slices/document-checklist",
4199
- "convexPaths": [
4200
- "convex/features/document-checklist"
4201
- ],
4202
- "npm": [
4203
- "lucide-react"
4204
- ],
4205
- "shadcn": [
4206
- "badge",
4207
- "button",
4208
- "card",
4209
- "dialog",
4210
- "label",
4211
- "popover",
4212
- "calendar",
4213
- "progress",
4214
- "scroll-area",
4215
- "skeleton",
4216
- "tabs",
4217
- "textarea"
4218
- ],
4219
- "env": [],
4220
- "peers": [
4221
- {
4222
- "slug": "convex-auth",
4223
- "range": "^0.1",
4224
- "reason": "Auth identity for user-scoped checklist state."
4225
- }
4226
- ],
4227
- "providers": [],
4228
- "tags": [
4229
- "career",
4230
- "documents",
4231
- "checklist",
4232
- "job-search",
4233
- "indonesia"
4234
- ],
4235
- "agentRecipe": "Run `rr add document-checklist`. Wire <DocumentChecklist bindings={{ current, seed, updateStatus }} countryTemplateSlot={<CountryTemplateCard bindings={{ templates, getTemplate, instantiate }} />} /> — bindings sourced from api.features['document-checklist'].* queries/mutations."
4236
- },
4237
- {
4238
- "slug": "pricing-page",
4239
- "title": "Pricing Page",
4240
- "category": "ui",
4241
3932
  "kind": "ui",
4242
- "version": "0.1.0",
4243
- "description": "Canonical pricing tier sectioneyebrow + headline + 2/3/4 column tier grid with optional FAQ accordion below. Tiers fully data-driven (name/price/period/bullets/cta/featured/badge). Featured variant configurable (ring/scale/tint). Single SSOT every saas/marketing template consumes this slice for pricing pages so admin-edited tiers propagate without per-template rewriting.",
4244
- "source": "rahman-resources",
4245
- "slicePath": "frontend/slices/pricing-page",
4246
- "convexPaths": [],
4247
- "npm": [
4248
- "lucide-react@^0.400.0"
4249
- ],
4250
- "shadcn": [
4251
- "button",
4252
- "card",
4253
- "accordion"
4254
- ],
4255
- "env": [],
4256
- "peers": [],
4257
- "providers": [],
4258
- "tags": [
4259
- "ui",
4260
- "pricing",
4261
- "section",
4262
- "marketing",
4263
- "saas",
4264
- "tiers",
4265
- "faq"
4266
- ],
4267
- "agentRecipe": "Run `npx rr add pricing-page`. <PricingSection eyebrow title subtitle tiers columns faq faqTitle featuredVariant /> — only `title` + `tiers` required. Each tier: `{ id, name, price, period?, blurb?, bullets[], cta?, featured?, badge? }`. Pass `featuredVariant=\"scale\"` for a popped-forward card or `\"tint\"` for a colored background. Wire admin CRUD via your store hook → useTiers() → pass array."
4268
- },
4269
- {
4270
- "slug": "feature-grid",
4271
- "title": "Feature Grid",
4272
- "category": "ui",
4273
- "kind": "ui",
4274
- "version": "0.1.0",
4275
- "description": "Canonical features grid section — eyebrow + headline + 1/2/3/4 column item grid in three layout variants (cards, minimal, alternating). Items accept Lucide icon component OR string label, optional image (next/image), optional link CTA. Single SSOT — every template consumes this slice for features pages so admin-edited items propagate without per-template duplication.",
3933
+ "version": "0.2.0",
3934
+ "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.",
4276
3935
  "source": "rahman-resources",
4277
- "slicePath": "frontend/slices/feature-grid",
3936
+ "slicePath": "frontend/slices/markdown",
4278
3937
  "convexPaths": [],
4279
3938
  "npm": [
3939
+ "katex@^0.16",
3940
+ "mermaid@^11",
3941
+ "recharts@^3",
4280
3942
  "lucide-react@^0.400.0"
4281
3943
  ],
4282
3944
  "shadcn": [
4283
3945
  "button",
4284
- "card"
3946
+ "tabs",
3947
+ "textarea"
4285
3948
  ],
4286
3949
  "env": [],
4287
3950
  "peers": [],
4288
3951
  "providers": [],
4289
3952
  "tags": [
4290
- "ui",
4291
- "features",
4292
- "section",
4293
- "marketing",
4294
- "grid",
4295
- "saas"
3953
+ "content",
3954
+ "markdown",
3955
+ "reader",
3956
+ "editor",
3957
+ "review",
3958
+ "comments",
3959
+ "mermaid",
3960
+ "chart",
3961
+ "rich-text",
3962
+ "docs",
3963
+ "notion-sync"
4296
3964
  ],
4297
- "agentRecipe": "Run `npx rr add feature-grid`. <FeatureGridSection eyebrow title subtitle items columns layout align /> — only `items` required. Each item: `{ id, title, body, icon?, image?, link? }`. `icon` can be a LucideIcon component (rendered as 5×5 inline) or a string (rendered as letter fallback). `layout=\"alternating\"` produces image+text rows that flip per index set `image` per item for that variant."
3965
+ "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)`."
4298
3966
  },
4299
3967
  {
4300
3968
  "slug": "landing-sections",
4301
3969
  "title": "Landing Sections",
4302
3970
  "category": "infra",
4303
3971
  "kind": "ui",
4304
- "version": "0.1.0",
4305
- "description": "CRUD-driven admin editor for the public landing-page composition. Ships a pure reducer + LandingProvider store adapter + admin LandingView/LandingEditorView built on the shared CRUD primitives, plus a per-section LandingSectionShell that handles background image + custom Tailwind className overlay. Sections carry { kind, order, title, subtitle, enabled, imageUrl, imageRatio, bgImageUrl, className, config (JSON) } with up/down reorder arrows. Consumers map each `kind` (hero, features, pricing, blog, changelog, testimonials, portfolio, services, stats, newsletter, faq, cta, custom) to their own renderer wrapped in <LandingSectionShell>. Canonical pattern used by all 7 rr website templates.",
3972
+ "version": "0.2.0",
3973
+ "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 + LandingProvider store adapter + admin LandingView/LandingEditorView built on the shared CRUD primitives, plus a per-section LandingSectionShell that handles background image + custom Tailwind className overlay. Sections carry { kind, order, title, subtitle, enabled, imageUrl, imageRatio, bgImageUrl, className, config (JSON) } with up/down reorder arrows. Consumers map each `kind` (hero, features, pricing, blog, changelog, testimonials, portfolio, services, stats, newsletter, faq, cta, custom) to their own renderer wrapped in <LandingSectionShell>. Used by all 7 rr website templates.",
4306
3974
  "source": "rahman-resources",
4307
3975
  "slicePath": "frontend/slices/landing-sections",
4308
3976
  "convexPaths": [],
@@ -4332,171 +4000,6 @@
4332
4000
  ],
4333
4001
  "agentRecipe": "Run `npx rr add landing-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 through `<LandingSectionShell section={s}>` wrapping your own per-`kind` renderer."
4334
4002
  },
4335
- {
4336
- "slug": "faq-section",
4337
- "title": "FAQ Section",
4338
- "category": "ui",
4339
- "kind": "ui",
4340
- "version": "0.1.0",
4341
- "description": "Canonical FAQ accordion section — eyebrow + headline + accordion item list. Three layouts (single column, two-column, grouped by category). Optional footer CTA (\"Still have questions?\"). Items fully data-driven. Single SSOT — every template consumes this slice for FAQ blocks so admin-edited Q&A propagates without per-template rewrite.",
4342
- "source": "rahman-resources",
4343
- "slicePath": "frontend/slices/faq-section",
4344
- "convexPaths": [],
4345
- "npm": [],
4346
- "shadcn": [
4347
- "accordion",
4348
- "button"
4349
- ],
4350
- "env": [],
4351
- "peers": [],
4352
- "providers": [],
4353
- "tags": [
4354
- "ui",
4355
- "faq",
4356
- "section",
4357
- "accordion",
4358
- "marketing"
4359
- ],
4360
- "agentRecipe": "Run `npx rr add faq-section`. <FAQSection items title subtitle layout multiple defaultOpen footerCta /> — only `items` required. Each item: `{ id, q, a, category? }`. `layout=\"grouped\"` buckets by `category`. `multiple` lets users open several at once. `footerCta={{ label, href }}` wires a contact link below the accordion."
4361
- },
4362
- {
4363
- "slug": "testimonials-grid",
4364
- "title": "Testimonials Grid",
4365
- "category": "ui",
4366
- "kind": "ui",
4367
- "version": "0.1.0",
4368
- "description": "Canonical testimonials section — quote + author + role/company + optional avatar + optional star rating. Three layouts (uniform cards grid, centered quote-stack, CSS masonry). `featured` testimonials get a ring accent. Pairs naturally with the `testimonials` backend slice (Convex queries) but has zero coupling — pass any item array.",
4369
- "source": "rahman-resources",
4370
- "slicePath": "frontend/slices/testimonials-grid",
4371
- "convexPaths": [],
4372
- "npm": [
4373
- "lucide-react@^0.400.0"
4374
- ],
4375
- "shadcn": [
4376
- "avatar",
4377
- "button",
4378
- "card"
4379
- ],
4380
- "env": [],
4381
- "peers": [
4382
- {
4383
- "slug": "testimonials",
4384
- "range": "^0.1",
4385
- "reason": "Optional — pair with backend testimonials slice for full admin CRUD + storage."
4386
- }
4387
- ],
4388
- "providers": [],
4389
- "tags": [
4390
- "ui",
4391
- "testimonials",
4392
- "section",
4393
- "marketing",
4394
- "social-proof",
4395
- "saas"
4396
- ],
4397
- "agentRecipe": "Run `npx rr add testimonials-grid`. <TestimonialsGridSection items title subtitle columns layout align /> — only `items` required. Each item: `{ id, quote, author, role?, company?, avatar?, rating?, featured? }`. `layout=\"quote-stack\"` renders a centered no-card scroll for editorial sites. `layout=\"masonry\"` uses CSS columns for variable-height quotes."
4398
- },
4399
- {
4400
- "slug": "blog-section",
4401
- "title": "Blog Section",
4402
- "category": "ui",
4403
- "kind": "ui",
4404
- "version": "0.1.0",
4405
- "description": "Canonical blog list + detail section. <BlogListSection> renders 3 layouts (cards grid, minimal list, featured-split with hero + side rail). <BlogPostView> renders the single-post page with cover + meta + paragraph-split body. Both pass through `hrefFor`/`backHref` so each template controls routing — single SSOT for /blog and /blog/[slug] across all templates.",
4406
- "source": "rahman-resources",
4407
- "slicePath": "frontend/slices/blog-section",
4408
- "convexPaths": [],
4409
- "npm": [
4410
- "lucide-react@^0.400.0"
4411
- ],
4412
- "shadcn": [
4413
- "badge",
4414
- "button",
4415
- "card",
4416
- "separator"
4417
- ],
4418
- "env": [],
4419
- "peers": [
4420
- {
4421
- "slug": "mdx-blog",
4422
- "range": "^0.1",
4423
- "reason": "Optional — pair with mdx-blog backend slice for MDX-rendered posts."
4424
- }
4425
- ],
4426
- "providers": [],
4427
- "tags": [
4428
- "ui",
4429
- "blog",
4430
- "section",
4431
- "marketing",
4432
- "content",
4433
- "list",
4434
- "detail"
4435
- ],
4436
- "agentRecipe": "Run `npx rr add blog-section`. <BlogListSection posts hrefFor title columns layout limit /> for /blog — `hrefFor(post)` returns the per-post URL. <BlogPostView post backHref renderBody /> for /blog/[slug] — `renderBody` defaults to paragraph-split on `\\n\\n` (swap for an MDX renderer if you use mdx-blog)."
4437
- },
4438
- {
4439
- "slug": "changelog-feed",
4440
- "title": "Changelog Feed",
4441
- "category": "ui",
4442
- "kind": "ui",
4443
- "version": "0.1.0",
4444
- "description": "Canonical /changelog or /whats-new section. Entries support 5 kinds (feature/improvement/fix/chore/breaking) with color-coded badges. Three layouts (timeline with date-rail, large cards, minimal list). Optional `limit` for \"Recent updates\" excerpts on home pages. Optional `groups` per entry for sub-sectioned bullet lists.",
4445
- "source": "rahman-resources",
4446
- "slicePath": "frontend/slices/changelog-feed",
4447
- "convexPaths": [],
4448
- "npm": [],
4449
- "shadcn": [
4450
- "badge",
4451
- "card",
4452
- "separator"
4453
- ],
4454
- "env": [],
4455
- "peers": [],
4456
- "providers": [],
4457
- "tags": [
4458
- "ui",
4459
- "changelog",
4460
- "section",
4461
- "saas",
4462
- "release-notes",
4463
- "marketing"
4464
- ],
4465
- "agentRecipe": "Run `npx rr add changelog-feed`. <ChangelogFeedSection entries title subtitle layout sortDescending limit /> — only `entries` required. Each entry: `{ id, version, date, kind, title, body, bullets?, groups? }`. `layout=\"timeline\"` adds a left date-rail; `layout=\"list\"` is the most compact. Pass `limit={3}` on home pages to show recent releases."
4466
- },
4467
- {
4468
- "slug": "portfolio-section",
4469
- "title": "Portfolio Section",
4470
- "category": "ui",
4471
- "kind": "ui",
4472
- "version": "0.1.0",
4473
- "description": "Canonical portfolio list + detail section. <PortfolioListSection> renders 3 layouts (uniform 16:9 grid, CSS masonry, asymmetric with featured hero). <PortfolioDetailView> renders title + meta + cover + body + gallery + external link + related items. Both pass through `hrefFor`/`backHref` so each template controls routing — single SSOT for /portfolio and /portfolio/[slug] across agency-studio and personal-brand.",
4474
- "source": "rahman-resources",
4475
- "slicePath": "frontend/slices/portfolio-section",
4476
- "convexPaths": [],
4477
- "npm": [
4478
- "lucide-react@^0.400.0"
4479
- ],
4480
- "shadcn": [
4481
- "badge",
4482
- "button",
4483
- "card",
4484
- "separator"
4485
- ],
4486
- "env": [],
4487
- "peers": [],
4488
- "providers": [],
4489
- "tags": [
4490
- "ui",
4491
- "portfolio",
4492
- "section",
4493
- "marketing",
4494
- "case-study",
4495
- "list",
4496
- "detail"
4497
- ],
4498
- "agentRecipe": "Run `npx rr add portfolio-section`. <PortfolioListSection items hrefFor title columns layout limit /> for /portfolio — each item `{ id, slug, title, summary?, year?, client?, role?, tags?, cover: {src,alt}, gallery?, link? }`. <PortfolioDetailView item backHref renderBody related hrefForRelated /> for /portfolio/[slug] — `renderBody` defaults to paragraph split; override for project-specific layouts (problem/approach/result, brief/outcome, etc)."
4499
- },
4500
4003
  {
4501
4004
  "slug": "theme-presets",
4502
4005
  "title": "Theme Presets — unified switcher with bundled tweakcn registry",
@@ -4559,113 +4062,14 @@
4559
4062
  "agentRecipe": "Run `npx rr add files`. 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."
4560
4063
  },
4561
4064
  {
4562
- "slug": "equation",
4563
- "title": "EquationNotion-style KaTeX block primitive",
4564
- "category": "ui",
4565
- "kind": "ui",
4566
- "version": "0.1.0",
4567
- "description": "Inline-or-display LaTeX equation block — Notion-inspired primitive. KaTeX-rendered with edit/preview toggle, raw-text fallback when KaTeX fails to parse. Pure UI primitive (zero Convex tables, zero global state). Lifted from notion-page-clone (Nosion). Use standalone OR bundled via the notion-blocks bundle. Drop into any React surface — docs, marketing landing, editor.",
4568
- "source": "notion-page-clone",
4569
- "slicePath": "frontend/slices/equation",
4570
- "convexPaths": [],
4571
- "npm": [
4572
- "katex@^0.16.45"
4573
- ],
4574
- "shadcn": [
4575
- "button"
4576
- ],
4577
- "env": [],
4578
- "peers": [],
4579
- "providers": [],
4580
- "tags": [
4581
- "ui",
4582
- "notion",
4583
- "notion-like",
4584
- "equation",
4585
- "katex",
4586
- "latex",
4587
- "math",
4588
- "block",
4589
- "primitive",
4590
- "editor"
4591
- ],
4592
- "agentRecipe": "Run `npx rr add equation`. Single npm dep: katex. Import `import { EquationBlock } from \"@/features/equation\"`. Props-driven: pass `value` (LaTeX string) + `onChange`. For display-mode (block-level) pass `displayMode`. Renders raw text if KaTeX parse fails. Bundled inside notion-blocks if you also want code/notify/drag-fill."
4593
- },
4594
- {
4595
- "slug": "code-block",
4596
- "title": "Code Block — Notion-style syntax-highlighted code primitive",
4065
+ "slug": "selection",
4066
+ "title": "Selectionmarquee multi-select + bulk actions",
4597
4067
  "category": "ui",
4598
4068
  "kind": "ui",
4599
- "version": "0.1.0",
4600
- "description": "Highlight.js-powered code block Notion-inspired primitive. Language selector dropdown (auto-detect + 50+ language packs), copy-to-clipboard button, line-wrap toggle. Pure-UI primitiveno Convex tables. Lifted from notion-page-clone (Nosion). Use standalone OR bundled via notion-blocks.",
4601
- "source": "notion-page-clone",
4602
- "slicePath": "frontend/slices/code-block",
4603
- "convexPaths": [],
4604
- "npm": [
4605
- "highlight.js@^11.11.1"
4606
- ],
4607
- "shadcn": [
4608
- "button",
4609
- "dropdown-menu"
4610
- ],
4611
- "env": [],
4612
- "peers": [],
4613
- "providers": [],
4614
- "tags": [
4615
- "ui",
4616
- "notion",
4617
- "notion-like",
4618
- "code",
4619
- "syntax",
4620
- "highlight",
4621
- "highlight.js",
4622
- "block",
4623
- "primitive",
4624
- "editor"
4625
- ],
4626
- "agentRecipe": "Run `npx rr add code-block`. Single npm dep: highlight.js. Import `import { CodeBlock, languageLabel } from \"@/features/code-block\"`. Props: `value` + `onChange` + `language` + `onLanguageChange`. Bundled inside notion-blocks if you also want equation/notify/drag-fill."
4627
- },
4628
- {
4629
- "slug": "notifications",
4630
- "title": "Notifications — Notion-style per-page Notify Me",
4631
- "category": "ui",
4632
- "kind": "ui",
4633
- "version": "0.1.0",
4634
- "description": "Pure-client per-page subscription primitive — Notion-inspired bell button + popover. State stored in localStorage (no backend needed). Shipped as a `NotifyMePopover` toggled from a page-action bell. Frequency choices: instant / daily digest / weekly digest. Lifted from notion-page-clone (Nosion). Use standalone OR bundled via notion-blocks.",
4635
- "source": "notion-page-clone",
4636
- "slicePath": "frontend/slices/notifications",
4637
- "convexPaths": [],
4638
- "npm": [],
4639
- "shadcn": [
4640
- "button",
4641
- "popover"
4642
- ],
4643
- "env": [],
4644
- "peers": [],
4645
- "providers": [],
4646
- "tags": [
4647
- "ui",
4648
- "notion",
4649
- "notion-like",
4650
- "notifications",
4651
- "subscribe",
4652
- "notify",
4653
- "bell",
4654
- "popover",
4655
- "localstorage",
4656
- "primitive"
4657
- ],
4658
- "agentRecipe": "Run `npx rr add notifications`. Zero npm deps (only shadcn button + popover). Import `import { NotifyMePopover, useSubscription } from \"@/features/notifications\"`. Drop the popover anywhere; useSubscription(pageId) hook returns `{ isSubscribed, frequency, subscribe, unsubscribe, setFrequency }` reading from localStorage. To wire a real backend, swap the localStorage hook for your own."
4659
- },
4660
- {
4661
- "slug": "database-cell-selection",
4662
- "title": "Database Cell Selection — Notion-style drag-fill + multi-select",
4663
- "category": "ui",
4664
- "kind": "ui",
4665
- "version": "0.1.0",
4666
- "description": "Notion-style grid cell interaction primitives: drag-fill (Sheets/Excel-style range fill), multi-cell selection with shift-click + arrow-key extension, paste-from-clipboard column adapter. Pure-UI hooks + components, no Convex tables. Lifted from notion-page-clone (Nosion). Pair with any tabular UI (notion-shell databases, ag-grid, custom React table, etc.).",
4069
+ "version": "0.2.0",
4070
+ "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.",
4667
4071
  "source": "notion-page-clone",
4668
- "slicePath": "frontend/slices/database-cell-selection",
4072
+ "slicePath": "frontend/slices/selection",
4669
4073
  "convexPaths": [],
4670
4074
  "npm": [],
4671
4075
  "shadcn": [],
@@ -4674,26 +4078,24 @@
4674
4078
  "providers": [],
4675
4079
  "tags": [
4676
4080
  "ui",
4677
- "notion",
4678
- "notion-like",
4679
- "database",
4680
- "grid",
4681
- "cell",
4682
4081
  "selection",
4683
- "drag-fill",
4684
- "spreadsheet",
4685
- "primitive",
4686
- "table"
4082
+ "marquee",
4083
+ "rubber-band",
4084
+ "multi-select",
4085
+ "bulk",
4086
+ "notion",
4087
+ "blocks",
4088
+ "list"
4687
4089
  ],
4688
- "agentRecipe": "Run `npx rr add database-cell-selection`. Zero deps. Import `import { useDragFill, SelectableCell, useCellSelection } from \"@/features/database-cell-selection\"`. Wrap your grid container with the selection hook; per-cell `<SelectableCell row col>` provides the click-and-drag affordance. Drag handles supplied by useDragFill. Composable with notion-shell's NotionDatabase or any custom grid."
4090
+ "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."
4689
4091
  },
4690
4092
  {
4691
4093
  "slug": "notion-database",
4692
- "title": "Notion-like Database Table — full table with import/export + row peek + relation/rollup + row multi-select + calendar drag + DB-level menu + full-page shell + AST formula engine (11 views · 18 cells · CSV + JSON)",
4094
+ "title": "Notion Database",
4693
4095
  "category": "ui",
4694
4096
  "kind": "ui",
4695
- "version": "0.13.0",
4696
- "description": "Portable Notion-style database table surface — full capability in one slice. Optional companion to notion-shell — install shell alone for pages + sidebar + block editor, add notion-database when you want embedded databases with full table capability. Ships NotionDatabase (full DB UI w/ ViewTabs + ViewOptions + per-column menu + FilterBuilder/SortBuilder popovers), NotionProperty (value + schema editor), 16 property-cell types (text / number / checkbox / select / multi_select / status / date / url / email / phone / files / person / formula / created_time / last_edited_time / unique_id), 11 built-in views: Table / Board / List / Gallery / Calendar / Feed PLUS Chart (recharts bar/line/area/pie/donut + inline kind/X/agg/Y pickers) / Dashboard (KPI strip + group breakdowns + recent updates) / Form (public-facing submit-to-create — title + per-property inputs, optional required-field validation, configurable show/hide + success message via inline Settings panel) / Map (SVG world + lat/lng pins, no leaflet) / Timeline (Gantt-style with drag-to-shift / drag-to-resize). FilterBuilder + SortBuilder exported standalone for toolbar embedding. Formula cells use a pure expression engine ({{title}}/{{prop}} interpolation + concat/upper/lower/round/if/etc fns + `=expr` math). Files cells store URL refs (paste-URL workflow; host can plug `files` slice adapter for upload). Person cells are simplified vs upstream — no user directory lookup, just initials chips. Created_time / last_edited_time read row.createdAt / row.updatedAt directly. unique_id auto-derives from row position + optional prefix. Pure helpers: applyView, groupBy, bucketByDate. Domain types live in notion-shell (single source of truth — Page.rowOfDatabaseId + rowProps reference them) and re-exported here. Relation + rollup property types deferred to upstream open-silong mega-bundle (need cross-DB context). v0.5 added drop-in Convex backend templates (dual-mode: minimal single-user OR full multi-workspace) from open-silong's template-base/. v0.6 (Phase 7.10) merges former database-io slice in-tree: DatabaseIOActions toolbar (Export CSV/JSON · Import CSV/JSON · Download dynamic CSV/JSON templates), CsvImportDialog (auto-map columns + create-new-of-type picker), JsonImportDialog (schema diff + import), exportDatabase / exportDatabaseToCsv / parseExport / parseCsv / buildCsvTemplate / buildJsonTemplate helpers — all from `@/features/notion-database`. CsvNewProperty + JsonImportResult.newProperties now expose `tempId` so host can remap rowProps keys when persisting (single import handler serves both formats). Cell editor UX consolidated v0.5.3 — SelectCell + MultiSelectCell share OptionPicker (shared/identical popover: search-as-create + per-option rename/color/delete). Property-type lists single-source via PROPERTY_TYPE_META registry (v0.5.2). v0.7 (CK-1D Phase 1) lifts row-detail subsystem from notion-page-clone: RowPeek (sheet + dialog + persisted mode toggle via useRowOpenMode localStorage hook), RowDetailSheet (right drawer), RowDetailDialog (centered modal), RowDetailBody (shared chrome), RowOpenModeSwitcher (sheet/dialog/page toggle). Pure slot-driven — host supplies icon picker, properties form, and block editor via render slots (iconSlot, propertiesSlot, blocksSlot); no Convex / comments / editor coupling. onOpenAsPage callback wires one-shot navigation without changing the persisted default. v0.8 (CK-1D Phase 2) lifts relation + rollup cells: RelationCell (cross-database link picker w/ search + create-new-row affordance + stale-link healing) and RollupCell (read-only aggregate display — count / count_unique / values / sum / avg / min / max / earliest / latest / checked / percent_checked). PropertyType union extended with 'relation' and 'rollup'. Property gained relationDatabaseId / rollupRelationPropertyId / rollupTargetPropertyId / rollupAggregate fields. NotionDatabase added new props pages, databases, onCreateRelatedRow so host stays the source of truth — cells gracefully no-op when omitted. v0.9 (CK-1D Phase 3) lifts row multi-select subsystem: RowSelectionProvider (React Context holding selected id set + anchor; drops stale ids when rowOrder shrinks), RowMarqueeOverlay (drag-to-select rubber-band over any container w/ data-row-shell-id markers — AutoCAD window/crossing modes, threshold + long-press text-origin activation, additive shift-drag), RowSelectionToolbar (floating bottom-center action bar w/ N-rows-selected count, optional locked badge, host-supplied extraSlot, Delete button via onDelete callback, Clear via Esc/X), RowSelectionKeyboard (Esc clear + Del/Backspace bulk delete + outside-click dismiss). TableView automatically tags rows with data-row-shell-id and applies a primary-tinted ring when wrapped in RowSelectionProvider. Marquee primitive + useMarqueeDrag hook exported for reuse on Board / Gallery / custom views. v0.10 (CK-1D Phase 5) adds HeaderCheckboxGutter (tri-state select-all/clear w/ aria-checked='mixed' indeterminate) + RowCheckbox (per-row toggle) — TableView auto-renders a checkbox gutter column whenever a RowSelectionProvider is in scope. Pure calendarDrag helpers (parseExistingDate, formatDateValue, shiftYmd, computeDateShift, parseDropTargetId) exported for hosts wiring CalendarView/Timeline drag-to-move without taking on @dnd-kit coupling inside the slice. Column drag-reorder + row drag-reorder primitives deferred — upstream's flexbox-table refactor conflicts with rr's semantic <table> + 200-LOC view cap. v0.11 (CK-1D Phase 7) lifts Intl-based number + date formatters: lib/numberFormat.ts (resolveNumberFormat / formatPropertyNumber + COMMON_CURRENCIES 16-code picker) and lib/dateFormat.ts (parseYmdToLocal / formatYmd / formatTime / formatDateValue + DATE_FORMAT_LABELS / TIME_FORMAT_LABELS). Property gained numberCurrencyCode + dateFormat + timeFormat + dateIncludeTime fields. NumberCell currency now honours per-property ISO code; DateCell accepts an optional `prop` and routes through formatDateValue when any date-related field is set on it. Notion-shell DatabaseViewConfig split into ./view-config-types.ts to keep types.ts under the 200-LOC cap. v0.12 (CK-1D Phase 4) adds database-shell subsystem: DatabaseMenu (rename / duplicate {structure | with rows} / lock-toggle / delete popover — every action hidden when its callback is omitted; native window.confirm + window.prompt fallbacks keep zero new dialog deps) and DatabasePage (full-page wrapper composing a big header — icon slot + inline title input + DatabaseMenu — over a NotionDatabase body). NotionDatabase grew a `headerActions` render slot so hosts can drop a DatabaseMenu inline without switching to DatabasePage. Database type gained an optional `locked` flag. Strip vs upstream: useDbAdapter (Convex coupling) + SubItemsPicker (sub-items tree) + IconPickerPopover (lives in icon-picker slice) + DataMenu (database-json slice) deferred host wires those externally. v0.13 (CK-1D Phase 6) replaces the flat formula.ts evaluator with a typed AST engine under lib/formulaEngine/ (types, coerce, dateUtils, ParserClass, parser, functions, evaluator, deps): recursive-descent parser w/ source-position tracking; typed FormulaValue (string/number/boolean/date/null/list) instead of string-only; circular-reference guard via visited set + per-row memoisation cache; new fn surface — substring, dateAdd, dateSubtract, dateBetween, formatDate, count, sum, join (on top of existing concat/lower/upper/length/if/and/or/not/empty/contains/replace/round/floor/ceil/abs/min/max/now/today). Relation refs in formulas now resolve via the workspace pages passed through NotionDatabase. FormulaCell upgraded — popover now shows parse-error message + source position; cell display flips to destructive style on invalid. Legacy evaluateFormula() string wrapper preserved for existing callers; new code should import evalFormula / formatFormulaValue from `@/features/notion-database`. collectDeps() exported for hosts wiring formula-dependency invalidation.",
4097
+ "version": "0.17.1",
4098
+ "description": "Drop-in Notion-style database surface. 11 views (table, board, list, gallery, calendar, feed, chart, dashboard, form, map, timeline), 18 property/cell types, and a per-type column-header config menu (number format, date ranges, select, relation, rollup, formula) plus filter / sort / group / calculate, row peek, row multi-select, table cell selection + drag-to-fill (click a cell, drag the handle to copy down merged from the former database-cell-selection slice in v0.16), and CSV + JSON import-export. Pure and props-driven the host owns the data and dispatches change callbacks. Domain types live in notion-shell (install it as the peer). Full release history in CHANGELOG.md.",
4697
4099
  "source": "open-silong",
4698
4100
  "slicePath": "frontend/slices/notion-database",
4699
4101
  "convexPaths": [
@@ -4764,66 +4166,109 @@
4764
4166
  "optional",
4765
4167
  "embeddable"
4766
4168
  ],
4767
- "agentRecipe": "Run `npx rr add notion-database` (cascades notion-shell as peer). Import: `import { NotionDatabase, NotionProperty, VIEW_REGISTRY, DatabaseIOActions, RowPeek } from \"@/features/notion-database\"`. NotionDatabase ships full props-driven DB UIhost owns rows + dispatches CRUD callbacks. For just one view in isolation, import the specific view component (TableView / BoardView / etc.). Property cells auto-render via renderPropertyCell helper. Pure helpers: applyView / groupBy / bucketByDate. For import/export, mount `<DatabaseIOActions db={db} rows={rows} onImport={async ({ newProperties, rows }) => { const tempToReal: Record<string, string> = {}; for (const np of newProperties) { const realId = await dispatchAddProperty(np); tempToReal[np.tempId] = realId; } for (const r of rows) { const rowId = await dispatchAddRow(r.title); for (const [propKey, v] of Object.entries(r.rowProps)) { await dispatchSetValue(rowId, tempToReal[propKey] ?? propKey, v); } } }} />` next to your DB toolbar exports CSV/JSON + imports w/ schema diff + downloads dynamic templates from live db.properties. tempId on each new property lets host remap rowProps keys to its real backend ids. For backend persistence, copy template-base/database-silong/convex/ from the open-silong repo: handlers go to convex/, schema fragment merges into convex/schema.ts. Pick _shared/minimal/ (single-user, noop authz) or _shared/full/ (requires @convex-dev/auth + workspaces tables). See CONVEX-BACKEND.md."
4169
+ "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-database`. Cascades the `notion-shell` peer (the domain types live there). Components import from `@/features/notion-database`; types from `@/features/notion-shell`.\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-database';\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-database'` — and feed it `rows` + `renderCell` + `renderColumnHeader`."
4768
4170
  },
4769
4171
  {
4770
- "slug": "database-io",
4771
- "title": "[DEPRECATED] Database IO merged into notion-database v0.6",
4172
+ "slug": "image-picker",
4173
+ "title": "Image Pickerone-button image/wallpaper chooser (gallery · upload · link · Unsplash · reposition)",
4772
4174
  "category": "ui",
4773
4175
  "kind": "ui",
4774
- "version": "0.2.0",
4775
- "description": "DEPRECATED all functionality merged into `notion-database` v0.6 (Phase 7.10, 2026-05-22). This slice is now a thin re-export shim from `@/features/notion-database` to keep existing consumers compiling. New code should `npx rr add notion-database` (now bundles CSV + JSON import/export + dynamic templates) instead of installing this separately. Slice will be removed in v1.0. Original surface (DatabaseIOActions / CsvImportDialog / JsonImportDialog / exportDatabase / buildCsvTemplate / buildJsonTemplate) remains exported from notion-databasesee its catalog entry. Merge rationale: 100% peer coupling to notion-database (every file imported Database/Page/Property types from it) + zero independent install path (always installed alongside notion-database in practice) = no modularity benefit from separation.",
4176
+ "version": "0.1.0",
4177
+ "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.",
4776
4178
  "source": "notion-page-clone",
4777
- "slicePath": "frontend/slices/database-io",
4179
+ "slicePath": "frontend/slices/image-picker",
4778
4180
  "convexPaths": [],
4779
4181
  "npm": [],
4780
4182
  "shadcn": [
4781
- "button",
4782
4183
  "dialog",
4783
- "dropdown-menu"
4184
+ "button",
4185
+ "input"
4784
4186
  ],
4785
- "env": [],
4786
- "peers": [
4187
+ "env": [
4787
4188
  {
4788
- "slug": "notion-database",
4789
- "range": "^0.3",
4790
- "reason": "Reuses Database / Page / Property / PropertyValue / PropertyType / SelectOption / DatabaseViewConfig types."
4189
+ "name": "UNSPLASH_ACCESS_KEY",
4190
+ "scope": "server",
4191
+ "required": false,
4192
+ "description": "Server-side only (e.g. on the /api/unsplash route). Without it the Unsplash tab falls back to the curated set."
4791
4193
  }
4792
4194
  ],
4195
+ "peers": [],
4196
+ "providers": [],
4197
+ "tags": [
4198
+ "ui",
4199
+ "image",
4200
+ "picker",
4201
+ "wallpaper",
4202
+ "cover",
4203
+ "upload",
4204
+ "unsplash",
4205
+ "gallery",
4206
+ "reposition",
4207
+ "files",
4208
+ "primitive",
4209
+ "portable",
4210
+ "dialog"
4211
+ ],
4212
+ "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."
4213
+ },
4214
+ {
4215
+ "slug": "notion-sidebar",
4216
+ "title": "Notion Sidebar — tree nav + page CRUD (rename · drag · icon picker)",
4217
+ "category": "ui",
4218
+ "kind": "ui",
4219
+ "version": "0.1.0",
4220
+ "description": "Standalone Notion-style tree-nav sidebar with full page CRUD, lifted out of notion-shell so it is reusable on its own. Props-driven + fully decoupled — owns its own lightweight NotionSidebarPage type (id / title / icon / parentId), imports no other slice. Capabilities: click a row to open; DOUBLE-CLICK a title to rename inline; drag the grip to reorder AND reparent (a @dnd-kit sortable tree with horizontal-offset depth projection); collapse/expand subtrees; hover a row for +subpage / delete. Optional per-row icon PICKER — wire `renderIconPicker` + `onIconChange` (e.g. @/features/icon-picker's IconPickerPopover) so clicking a row icon opens the picker. The host owns the data and dispatches onSelect / onCreate / onRename / onDelete / onMove / onIconChange. Compose with notion-shell (page editor) + notion-database (embedded DBs) for the full Notion-clone OS — see the notion-page-clone-os template.",
4221
+ "source": "notion-page-clone",
4222
+ "slicePath": "frontend/slices/notion-sidebar",
4223
+ "convexPaths": [],
4224
+ "npm": [
4225
+ "@dnd-kit/core",
4226
+ "@dnd-kit/sortable",
4227
+ "@dnd-kit/utilities"
4228
+ ],
4229
+ "shadcn": [
4230
+ "button",
4231
+ "input"
4232
+ ],
4233
+ "env": [],
4234
+ "peers": [],
4793
4235
  "providers": [],
4794
4236
  "tags": [
4795
4237
  "ui",
4796
4238
  "notion",
4797
- "notion-like",
4798
- "database",
4799
- "csv",
4800
- "json",
4801
- "import",
4802
- "export",
4803
- "template",
4804
- "data",
4805
- "backup",
4806
- "spreadsheet",
4807
- "wire-format",
4239
+ "sidebar",
4240
+ "tree",
4241
+ "nav",
4242
+ "page",
4243
+ "crud",
4244
+ "rename",
4245
+ "drag",
4246
+ "dnd",
4247
+ "reorder",
4248
+ "reparent",
4249
+ "icon-picker",
4808
4250
  "primitive",
4809
- "optional"
4251
+ "portable",
4252
+ "notion-like"
4810
4253
  ],
4811
- "agentRecipe": "⚠️ DEPRECATED — use `npx rr add notion-database` (now bundles import/export). This slice is a thin re-export shim from `@/features/notion-database` for back-compat. New code: `import { DatabaseIOActions } from \"@/features/notion-database\"`. Remove when migration complete; slice scheduled for removal in v1.0."
4254
+ "agentRecipe": "Run `npx rr add notion-sidebar`. Import `import { NotionSidebar, type NotionSidebarPage } from \"@/features/notion-sidebar\"`. Feed it a flat `pages: NotionSidebarPage[]` ({ id, title, icon, parentId }) — the sidebar builds the tree. Wire callbacks: onSelect(id), onCreate(parentId|null), onRename(id, title) [double-click a title to trigger], onDelete(id), onMove(id, parentId, beforeId) [drag the grip — reorders + reparents], onIconChange(id, icon). For rich icons pass `renderIcon` (display) + `renderIconPicker` (click-to-pick) wired to `@/features/icon-picker` (DynamicIcon + IconPickerPopover). npm: @dnd-kit/core + sortable + utilities. Pair with notion-shell (page editor) + notion-database (embedded DBs) the notion-page-clone-os template shows the full reducer wiring."
4812
4255
  },
4813
4256
  {
4814
4257
  "slug": "notion-shell",
4815
- "title": "Notion Shell — page + sidebar + block editor primitives (pure, no database)",
4258
+ "title": "Notion Shell — page + block editor primitives (pure, no sidebar/database)",
4816
4259
  "category": "ui",
4817
4260
  "kind": "ui",
4818
- "version": "0.7.1",
4819
- "description": "Portable Notion-style PAGE + SIDEBAR + BLOCK editor primitives. CI-wave (2026-05-21) split the database surface out install the optional `notion-database` peer for embedded TableView / BoardView / ListView / GalleryView / CalendarView / FeedView, NotionDatabase, NotionProperty, ViewTabs, ViewOptions, ColumnHeaderMenu, property-cells. notion-shell alone gives you Notion-clone pages + sidebar + editor without the database weight. Domain types (Database, Property, PropertyValue, DbView, DatabaseViewConfig, DatabaseFilter, DatabaseSort) remain in notion-shell as the single source of truth (Page.rowOfDatabaseId + rowProps reference them). FULL OLD DESC BELOW: Portable Notion-style wrapper primitives. PAGE EDITOR: NotionPage (optional cover image band + header + body), NotionHeader / NotionSidebar / NotionBlock (live inline-markdown decorator, hover actions menu, optional dragHandle slot), SlashMenu (searchable block-type picker w/ keyboard nav), BlockActionsMenu (turn-into / duplicate / delete), InsertBlockButton (`+` trigger w/ SlashMenu), SortableBlockList (@dnd-kit render-prop wrapper for block reorder), PageActionsMenu (header dropdown: cover/favorite/duplicate/export/trash). DATABASE: NotionDatabase (full DB surface w/ tabs + options + per-column menu), NotionProperty (10 property-cell types), 6 built-in views (Table/Board/List/Gallery/Calendar/Feed), ViewTabs, ViewOptions (sort + filter + search popover), ColumnHeaderMenu. SPECIALISED BLOCK RENDERERS: ImageRenderer (URL + caption + preview), EmbedRenderer (YouTube/Vimeo/Loom/Figma/CodePen/Spotify auto-detect + iframe fallback). Pure helpers: applyView, groupBy, bucketByDate. Pure / props-driven — host owns data + change handlers.",
4261
+ "version": "0.23.0",
4262
+ "description": "Portable Notion-style PAGE EDITOR primitives. v0.22 split the tree-nav SIDEBAR out into the standalone `notion-sidebar` slice (so the page editor and the sidebar are independently reusable); embedded DATABASES already live in the `notion-database` peer. notion-shell ships: NotionPage (optional cover image band + header + body), NotionHeader, NotionBlock (live inline-markdown decorator, hover actions menu, optional dragHandle slot, BUILT-IN code (highlight.js) + equation (KaTeX) blocks), SlashMenu (searchable block-type picker w/ keyboard nav), BlockActionsMenu (turn-into / duplicate / delete), InsertBlockButton (`+` trigger w/ SlashMenu), SortableBlockList (@dnd-kit render-prop wrapper for block reorder), PageActionsMenu (header dropdown: cover/favorite/duplicate/export/trash), InlineFormatToolbar + BlockColorPicker (colour) + MentionTypeahead + PageLayoutSection (layout). SPECIALISED BLOCK RENDERERS: ImageRenderer, EmbedRenderer (YouTube/Vimeo/Loom/Figma/CodePen/Spotify auto-detect). Domain types (Database, Property, PropertyValue, DbView, DatabaseViewConfig, DatabaseFilter, DatabaseSort) remain in notion-shell as the single source of truth (Page.rowOfDatabaseId + rowProps reference them). Pure / props-driven — host owns data + change handlers. Compose notion-sidebar + notion-shell + notion-database for the full Notion-clone OS.",
4820
4263
  "source": "notion-page-clone",
4821
4264
  "slicePath": "frontend/slices/notion-shell",
4822
4265
  "convexPaths": [],
4823
4266
  "npm": [
4824
4267
  "@dnd-kit/core",
4825
4268
  "@dnd-kit/sortable",
4826
- "@dnd-kit/utilities"
4269
+ "@dnd-kit/utilities",
4270
+ "katex@^0.16.45",
4271
+ "highlight.js@^11.11.1"
4827
4272
  ],
4828
4273
  "shadcn": [
4829
4274
  "button",
@@ -4840,25 +4285,23 @@
4840
4285
  "notion",
4841
4286
  "shell",
4842
4287
  "wrapper",
4843
- "sidebar",
4844
4288
  "page",
4845
- "database",
4289
+ "block",
4290
+ "editor",
4846
4291
  "primitive",
4847
4292
  "portable",
4848
4293
  "slash-menu",
4849
4294
  "decorator",
4850
4295
  "wysiwyg",
4851
- "views",
4852
- "kanban",
4853
- "calendar",
4854
- "gallery",
4855
4296
  "drag",
4856
4297
  "cover",
4857
4298
  "embed",
4858
4299
  "image",
4300
+ "code",
4301
+ "equation",
4859
4302
  "notion-like"
4860
4303
  ],
4861
- "agentRecipe": "Run `npx rr add notion-shell` for the portable UI wrappers ONLY (no backend). NPM deps: @dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities. Import: `import { NotionPage, NotionSidebar, NotionBlock, NotionDatabase, SortableBlockList, PageActionsMenu, InsertBlockButton, ViewTabs, ImageRenderer, EmbedRenderer } from \"@/features/notion-shell\"`. NotionBlock ships slash menu + decorator + actions menu + dragHandle slot. NotionPage ships optional cover prop. SortableBlockList wraps a render-prop callback `(id, dragProps) => <NotionBlock dragHandle={...} />`. NotionDatabase ships 6 views via VIEW_REGISTRY. Property cells: text/number/checkbox/select/multi-select/status/date/url/email/phone all built in. For rich icon UX wire `renderIcon` + `renderIconPicker` to `@/features/icon-picker`. **PRODUCT POINTER: the full Convex-backed Notion-clone OS (multi-workspace + auth + sharing + comments + snapshots + MCP) lives at https://github.com/rahmanef63/open-silong — clone that repo for the production stack; use this slice when you only need to embed the Notion-style UI in another project.**"
4304
+ "agentRecipe": "Run `npx rr add notion-shell` for the portable PAGE EDITOR wrappers ONLY (no backend; the tree-nav sidebar is the separate `notion-sidebar` slice). NPM deps: @dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities. Import: `import { NotionPage, NotionBlock, SortableBlockList, PageActionsMenu, InsertBlockButton, InlineFormatToolbar, ImageRenderer, EmbedRenderer } from \"@/features/notion-shell\"`. NotionBlock ships slash menu + decorator + actions menu + dragHandle slot. **`createDefaultBlockRenderers()` returns the block-renderer registry — pass it to `<NotionBlock blockRenderers={…}>` so callout (icon+kind picker), table (editable grid), divider, image, embed, code (highlight.js) + equation (KaTeX) all render. code + equation are now BUILT-IN to notion-shell (npm: katex + highlight.js) — no adapter needed. Only `database` + `toc` are injected at the app level (they depend on host data + the sibling notion-database slice).** NotionPage ships optional cover prop. SortableBlockList wraps a render-prop callback `(id, dragProps) => <NotionBlock dragHandle={...} />`. NotionDatabase ships 6 views via VIEW_REGISTRY. Property cells: text/number/checkbox/select/multi-select/status/date/url/email/phone all built in. For rich icon UX wire `renderIcon` + `renderIconPicker` to `@/features/icon-picker`. **v0.17 — Notion-canonical editing keys (`blockKeyHandler.ts`): Enter splits at the caret into a new block (lists continue their type; an empty list item exits to paragraph); Backspace on an empty non-paragraph downgrades it to a plain paragraph (re-triggerable with `/`); a second Backspace on an empty paragraph merges into the previous block; Arrow up/down at a line edge hops blocks. Wire the host callbacks on `<NotionBlock>`: `onInsertAfter(type, init) => newId`, `onMergeBack()`, `onFocusSibling(dir)` — plus `focusBlock(id, offset?)` exported to move the caret after a host state change. The preview `page-demo.tsx` and the notion-clone template `DocView` show full array- and reducer-based wirings.** PRODUCT POINTER: the full Convex-backed Notion-clone OS (multi-workspace + auth + sharing + comments + snapshots + MCP) lives at https://github.com/rahmanef63/open-silong — clone that repo for the production stack; use this slice when you only need to embed the Notion-style UI in another project.**"
4862
4305
  },
4863
4306
  {
4864
4307
  "slug": "workspace-shell",