rmnr
DocsTourSlicesBest PracticeAgentsInstall

Command Palette

Search for a command to run...

New
  • Changelog
Release notes

Changelog

What changed in each rr release — page 10 of 17. Full prose history in CHANGELOG.md.

MAY282026
FixCK-1LMay 28, 2026

Lane A: P0 security patch — 7 fixes across 8 backend slices

Cross-slice security batch from the post-Phase-6 audit. Zero P0 surfaced, but seven P1 findings warranted same-day patches before more slices accreted around the same patterns. Per-slice changes: (1) `payment.markPaid` now verifies `order.userId === requireUser(ctx)` so a logged-in user can no longer flip another user's order to paid by guessing the (string) orderId. (2) `payment.get` and `payment.getOrderByOrderId` are now owner-only — anon callers + non-owner authenticated callers get null instead of full order detail (amount, channel, instructions). (3) `comments.listForTarget` flipped from public `query` to `_listForTarget` `internalQuery` with default-deny semantics — consumers MUST wrap with their own target-visibility gate; ships with doc-comment example. (4) `newsletter.broadcastPublic` admin gate is now enforced (`isAdminUser` internalQuery checks `userProfiles.role==='admin'` or `SUPER_ADMIN_EMAIL`) instead of the TODO comment that any-logged-in could bypass. (5) `newsletter.subscribe` validates email shape (`^[^\s@]+@[^\s@]+\.[^\s@]+$`) + length cap (200 chars) + normalises before insert — partial defense; per-IP rate-limit table deferred to follow-up since it needs schema migration. The canonical `subscribers` slice already has the full hardened pattern (honeypot + windowed rate-limit + unsubscribe token); recommended for production. (6) Unbounded `.collect()` on public/internal queries replaced with explicit caps: `services.listAll` 500, `socials.listAll/listVisible` 200, `testimonials.listAll` 500, `seo.callsInWindow` 1000, `newsletter.activeSubscribers` 10000. Defense-in-depth — these tables would otherwise grow unboundedly on adopted projects with no read-time guard. Eight slice patch bumps: doku-payment 0.1.1, midtrans-payment 0.1.1, resend-newsletter 0.1.1, comments 0.2.1, services 0.1.1, socials 0.1.1, testimonials 0.1.1, seo 0.2.1.

Slices touched

  • doku-payment + midtrans-payment — markPaid owner-check + get/getOrderByOrderId owner-only (0.1.0 → 0.1.1)
  • resend-newsletter — broadcastPublic admin gate + subscribe email validation (0.1.0 → 0.1.1)
  • comments — listForTarget flipped to internalQuery default-deny (0.2.0 → 0.2.1)
  • services — listAll bounded to 500 (0.1.0 → 0.1.1)
  • socials — listAll/listVisible bounded to 200 (0.1.0 → 0.1.1)
  • testimonials — listAll bounded to 500 (0.1.0 → 0.1.1)
  • seo — callsInWindow .collect() bounded to 1000 (0.2.0 → 0.2.1)

Follow-ups (deferred)

  • newsletter/subscribe needs a `newsletterSubscribeAttempts` schema table for per-IP rate-limit on par with subscribers/mutation.ts
  • auth/checkEmail.ts references missing `_shared/clientIp` + `_shared/origin` — restore or delete (file is functional, just unwired)
  • convex/features/admin/query.ts:stats unauthenticated — gate for production-grade deployments
MAY272026
ImprovementCK-1KMay 27, 2026

notion-database 0.13.0 — typed AST formula engine (CK-1D Phase 6)

Last big CK-1D phase. Replaces the flat single-file regex evaluator (`lib/formula.ts`) with a typed AST engine under `lib/formulaEngine/` ported from notion-page-clone. Eight focused submodules, each ≤200 LOC: `types` (FormulaValue union + AST node shapes + FormulaError), `coerce` (toString/toNumber/toBoolean/toDate/isEmpty), `dateUtils` (UTC addUnit/diffUnit/formatDate), `ParserClass` (Pratt-style recursive-descent w/ source positions), `parser` (top-level dispatch — template / `=math` / bare call), `functions` (29-fn dispatch w/ arity throws), `evaluator` (AST walker w/ circular-ref guard + memoisation cache), `deps` (static `collectDeps` walker). New typed FormulaValue (string/number/boolean/date/null/list) replaces string-only returns — host gets exact runtime types. Circular-reference detection via visited-set throws FormulaError before infinite recursion. Per-call memoisation cache reuses evaluated formula values across an eval tree. New fn surface: `substring`, `dateAdd`, `dateSubtract`, `dateBetween`, `formatDate`, `count`, `sum`, `join` — on top of every existing fn (concat/lower/upper/length/contains/replace/if/and/or/not/empty/round/floor/ceil/abs/min/max/now/today). Relation refs (`{{Tasks}}`) now resolve to a `list` of target-page titles when `pages` is passed through NotionDatabase. FormulaCell upgraded — popover surfaces parse-error message + source position; cell display flips to destructive style + tooltip on invalid expression; preview line updates live as the user types. Legacy `evaluateFormula()` string wrapper preserved (back-compat) but routes through the new engine. New imports: `evalFormula`, `formatFormulaValue`, `collectDeps`, `parseFormula`, plus typed exports `FormulaValue`, `EvalContext`, `EvalResult`, `FormulaError`, `Node`, `ExprNode` from `@/features/notion-database`. Parity tracker: rr ↔ open-silong now ~88% (Phase 6 closes the formula gap; remaining deferred: SubItemsPicker, table-dnd column/row reorder, PropertyFormInput, RowActionsMenu keyboard nav).

MAY272026
FeatureCK-1JMay 27, 2026

activity 0.1.0 — public productivity log + MCP-friendly Convex backend, lifted from rahmanef.com

First 'now-page' / productivity-log slice in the catalog. Public-facing weekly activity log grouped by ISO week with schema.org-friendly markup, designed to maximise SEO so the question 'what is <person> working on this week?' lands here. Convex-backed: schema (`activities` table + `by_visibility_occurredAt` index), queries (`listAll`, `listPublic`, `get`, `statsThisWeek`), unauthenticated mutations (`create`, `update`, `remove`, `seed`) the consumer wraps. MCP-friendly — designed so AI workflows (Claude / GPT / custom agents) can append entries via the consumer's MCP server. ActivityFeed view split from a 225-LOC monolith into 1 view + 2 sub-components (`StatsPanel`, `ActivityItem`) + 4 lib helpers (`grouping`, `format`, `types`, `defaults`) for the 200-LOC cap. All user-facing copy + per-category labels + date/time locale are prop-driven with English defaults — original Indonesian strings + project-specific MCP-integration copy lifted out. Custom `<Section>`/`<Heading>` primitives + brutalist Tailwind utilities (`tracking-brutal-sm`, `border-foreground`) stripped — replaced with raw semantic elements + stock utilities (`tracking-wider`, `border-2`). Project-specific `seedDefaults` mutation (3 hardcoded rahmanef.com seed rows) dropped in favour of generic `seed`. Cross-slice `requireAdmin` import dropped — mutations ship as `internalMutation` and the consumer wraps them.

MAY272026
FeatureCK-1IMay 27, 2026

i18n-translate 0.1.0 — Google Translate widget, lifted from rahmanef.com

First on-the-fly localization slice in the catalog. Drop `<GoogleTranslate />` anywhere — no API key, no Google Cloud billing, no hand-maintained dictionaries. Auto-detect browser language on first visit (cookie set BEFORE Google's script loads so first paint is already translated), persist user choice via localStorage, click-to-reload language switching with router-refresh + best-effort-in-place fallback strategies. Source was a 510-LOC monolith at rahmanef.com `slices/i18n-translate/components/GoogleTranslate.tsx`; split during lift into 8 sub-files (`components/GoogleTranslate.tsx`, `hooks/useGoogleTranslate.ts`, `lib/{widget,cookie,storage,styles,defaults,types}.ts`) for the 200-LOC cap. Project-specific Tailwind utilities (`tracking-brutal-sm`, `border-[length:var(--border-width,2px)]`) stripped from defaults — replaced with stock `tracking-wider` + `border-2` so the slice renders cleanly without a brutalism preset. Consumer must add the CSP allowlist in README.md to their middleware/proxy for Google's script to load.

Slices touched

  • i18n-translate — first release, lifted from rahmanef.com (0.0.0 → 0.1.0)
MAY252026
FeatureCK-1HMay 25, 2026

icon-picker 0.3.0 — Phosphor fill variant + smart positioning + dialog fallback

Lifted from open-silong. The picker gains a second icon variant (Phosphor fill, color-aware) parallel to Lucide outline, surfaced via a two-tab layout (Emoji | Icon) with sub-variant pills (Native | Twemoji / Lucide | Phosphor). Storage adds a new `phosphor:Name?c=hex` form parallel to `lucide:Name?c=hex` — back-compat with every existing emoji + lucide value. Smart positioning: PopoverContent now caps height to Radix's `--radix-popover-content-available-height` CSS var and falls back to a centered Dialog when neither side fits ≥340px usable vertical (or viewport <360px wide) — fixes off-screen clipping on tight viewports + small mobile screens. Inline picker restructured to flex column with `min-h-0` so it adapts to either container. `style-pref.ts` renamed its localStorage key `nosion:iconStyle` → `icon-picker:style` with one-shot legacy migration so existing consumers keep their Twemoji/native preference.

Slices touched

  • icon-picker — phosphor variant, smart popover positioning, flex-resizable inline body (0.2.0 → 0.3.0)
MAY232026
FeatureCK-1GMay 23, 2026

AI prompts everywhere — per-slice agent.md, /agents/<slug> route, llms.txt expansion, copyable detail block

Surfaces the existing agentRecipe metadata (already on all 56 slices + 56 features + 36 layouts) in four new places so AI coding agents have a one-stop install surface. (1) Per-slice detail page now renders the recipe inside a copyable CodeBlock + Install-with-AI-agent dialog + link to the dedicated prompt page, replacing the prior plain-text paragraph. (2) /llms.txt expanded so each slice entry now includes `agent recipe:` + `prompt:` link. (3) gen-slice-agent-md.mjs writes `agent.md` inside every slice dir (53 files written); the file ships with the slice when consumers run `npx rr add <slug>`, so the install prompt is available offline + in-tree alongside the code. Generation wired into slices:check pre-push gate. (4) New /agents/<slug> dedicated route resolves against slices OR layouts; renders full prompt + copy + install button + source link. /agents/ index now lists all 44 slices + 36 layouts (was only first 4 layouts).

New

  • lib/slice-agent-prompt.ts — buildSliceAgentPrompt + buildLayoutAgentPrompt formatters
  • scripts/features/gen-slice-agent-md.mjs — generator (run + --check modes)
MAY232026
FeatureCK-1FMay 23, 2026

theme-presets v0.2 — one unified switcher; registry bundled inside slice

Consolidates the theme-preset surface in three directions. (1) Two switcher components → one: TweakcnSwitcher + ThemePicker merged into a single ThemePresetSwitcher (Palette-icon Popover with sticky light/dark/system mode tabs + sticky preset-count row with Default reset + scrollable grouped color list with hover-preview + click-commit). Pattern lifted from CareerPack production switcher. (2) ThemePresetProvider context added — wraps state so deeply-nested consumers read `useThemePreset()` instead of mounting the switcher directly. Bootstrap on first client mount, single registry load, exposes setPreset/preview/restore/isReady. (3) Catalog cleanup — dropped phantom `theme-preset-switcher` entry (pointed at template-base/frontend/shared/theme which doesn't exist on disk; was a legacy stub from rahmanef.com source map). User-requested extra: the ~240KB tweakcn registry now ships INSIDE the slice as registry-data.json and loads lazily via dynamic import — code-splits into its own chunk, no consumer public/ setup, no network roundtrip. HIDDEN_PRESETS filter drops gimmicky themes (Doom 64, Cyberpunk, Neo Brutalism, Bubblegum, Candyland, Pastel Dreams). Indonesian group labels (Profesional / Bold / Hangat / Artistik / Gelap / Lainnya). Slice count: 45 → 44 (net -1 after dropping phantom).

New files

MAY222026
FeatureCK-1EMay 22, 2026

database-io merged slice — CSV + JSON + dynamic template in one dropdown; catalog gains family sub-grouping

Two consolidations. (1) database-csv + database-json hard-merged into a single `database-io` slice. One DatabaseIOActions dropdown ships six items: Export CSV / Export JSON / Import CSV / Import JSON / Download CSV template / Download JSON template. Templates are generated dynamically from the live db.properties — header row (CSV) or wire-format v1 schema (JSON) reflects the current column set, with one placeholder row hinting at the expected format per property type (date → `2026-01-01`, multi_select → `Option1; Option2`, computed → `(computed — ignored on import)`). Single onImport callback still serves both formats because result shape stayed identical. Both legacy slugs hard-removed; consumers wanting CSV-only or JSON-only now install database-io and ignore the items they don't need (zero overhead — same shadcn deps). Slice count: 46 → 45. (2) /slices catalog UI gains second-level family sub-grouping. Within each category tab (or the All tab's category sections), slices that share a family slug-prefix (notion-*, ai-*, database-*, theme-*) or a manual override (payment, landing, admin, content) cluster under a labeled sub-header. Singletons fall back to the flat row — no `family of 1` labels.

New slice files

MAY212026
FeatureCK-JMay 21, 2026

database-json standalone slice — JSON import + export, twin of database-csv

Lifted JSON wire format companion from upstream notion-page-clone. Mirrors database-csv API surface so a single host onImport handler can serve both formats — same {newProperties, rows} result shape. Wire format v1 carries database schema (name + icon + properties + views) + rows (title + icon + rowProps). On import: parses + diffs incoming property list against existing db.properties (case-insensitive name + exact type match); matched props keep existing ids, mismatched listed as `newProperties`; row values remapped through the id table. NEW slice frontend/slices/database-json/ at version 0.1.0, peer of notion-database ^0.4. Dropped vs upstream: lib/ai.ts + AIAssistDialog (needs AI router separately), cover + blocks + sub-items + templates wire fields (not in rr Page/Database minimal shape), DataMenu (consumer composes CsvActions + JsonActions themselves). Slice count 45 → 46. Preview /preview/slices/database-json: 3-row demo + working Export downloads .json + Import file picker + collapsible wire-format JSON viewer at bottom.

New slice files

  • frontend/slices/database-json/{slice.json, slice.manifest.json, slice.contract.ts, index.ts, types.ts}
MAY212026
FeatureCK-1CMay 21, 2026

notion-database completes 11/11 views — FormView lifted

Final view (FormView) lifted from upstream. Was deferred from CK-1B because of PropertyFormInput + FormSettings + addRow-with-values complexity. Resolved by REUSING the existing renderPropertyCell helper (already covers all 16 property types) instead of lifting a separate input widget — form-context just adds a label wrapper. PropertyFormInput is NOT lifted as a peer; renderPropertyCell is the single source. New files: FormView.tsx (155 LOC — title input + per-property labels + Submit button + success state), form-settings.tsx (102 LOC — show / required checkboxes per formable property + form title + description + success message editor), form-helpers.ts (32 LOC — isFormableProperty / emptyDraft / isEmptyValue / READ_ONLY_PROPERTY_TYPES). ViewProps extended with onRowCreate?: (draft: {title, rowProps}) => Promise<void>|void. NotionDatabase forwards it through. DatabaseViewConfig extended with formTitle? + formDescription? (existing formRequiredProps / formShownProps / formSuccessMessage already added in CK-1A). VIEW_REGISTRY now has all 11 entries — db.views.type === 'form' resolves to FormView. Coverage: views 10/11 → 11/11 (100%). Adaptation ~76% → ~80%. notion-database 0.3.0 → 0.4.0. Preview /preview/slices/notion-database: 8 view tabs (added Form view), preview now uses React state so Form submit actually appends a row to the table — round-trip demonstrable.

New files

NewerPage 10 / 17Older

Slices touched

  • notion-database — typed AST formula engine + 8 new fns + circular-ref guard (0.12.0 → 0.13.0)

New files

  • frontend/slices/notion-database/lib/formulaEngine/{types,coerce,dateUtils,ParserClass,parser,functions,evaluator,deps,index}.ts — 9-file typed AST engine

Touched files

  • lib/formula.ts — slimmed to barrel + legacy evaluateFormula() wrapper
  • components/cells/FormulaCell.tsx — inline parse-error + live preview + relation-pages prop
  • components/property-cells.tsx — passes `pages` through to FormulaCell

Slices touched

  • activity — first release, lifted from rahmanef.com (0.0.0 → 0.1.0)

New files

  • convex/features/activity/{_schema,queries,mutations,index}.ts — Convex backend
  • frontend/slices/activity/views/ActivityFeed.tsx — top-level view (~90 LOC)
  • frontend/slices/activity/components/{StatsPanel,ActivityItem}.tsx — view sub-components
  • frontend/slices/activity/lib/{types,defaults,grouping,format}.ts — helpers + prop types + English copy defaults
  • frontend/slices/activity/{slice.json,slice.contract.ts,slice.manifest.json,README.md,config.ts,index.ts}

Dependencies

  • convex ^1.17 (schema + queries + mutations)
  • lucide-react ^0.400.0 (ArrowUpRight, Clock, Tag icons in ActivityItem)
  • next ^15 (next/link in ActivityItem)
  • react ^18

New files

  • frontend/slices/i18n-translate/components/GoogleTranslate.tsx — dropdown UI (110 LOC)
  • frontend/slices/i18n-translate/hooks/useGoogleTranslate.ts — stateful hook (87 LOC)
  • frontend/slices/i18n-translate/lib/widget.ts — Google widget plumbing (script + combo dispatch) (102 LOC)
  • frontend/slices/i18n-translate/lib/{cookie,storage,styles,defaults,types}.ts — sub-module split for 200-LOC cap
  • frontend/slices/i18n-translate/{slice.json,slice.contract.ts,slice.manifest.json,README.md,config.ts,index.ts}

Dependencies

  • lucide-react ^0.400.0 (ChevronDown icon in trigger button)
  • next ^15 (useRouter for the "router" refresh strategy)
  • react ^18

New files

  • frontend/slices/icon-picker/lib/phosphor-catalog.ts — 190 phosphor names grouped by category
  • frontend/slices/icon-picker/lib/phosphor-icons.ts — curated named-import surface for @phosphor-icons/react (tree-shake-safe)
  • frontend/slices/icon-picker/components/picker-parts/IconTab.tsx — combined Lucide+Phosphor tab (replaces LucideTab.tsx)

Dependencies

  • @phosphor-icons/react@^2.1.10 added to dependencies
  • deps.shadcn += dialog (smart fallback uses it)
  • package.json scripts: gen:agent-md, gen:agent-md:check
  • slices:check chain now includes gen:agent-md:check (drift gate)
  • app/(docs)/agents/[slug]/page.tsx — dedicated prompt page per slice/layout
  • frontend/slices/<slug>/agent.md × 53 — auto-generated, ships with `npx rr add`
  • Updated

    • app/(docs)/slices/[slug]/details-tab.tsx — agentRecipe block becomes CodeBlock + InstallWithAgent + dedicated-page link
    • app/llms.txt/route.ts — each slice gets `agent recipe:` + `prompt:` lines
    • app/(docs)/agents/page.tsx — full index of all slices + layouts (was only first 4)
    • components/ThemePresetSwitcher.tsx — single unified switcher (~190 LOC)
    • components/ThemePresetProvider.tsx — context + useThemePreset() hook + DEFAULT_PRESET_NAME
    • lib/tweakcn/registry-data.json — bundled tweakcn registry (~240KB, lazy-loaded)
    • slice.json + slice.contract.ts — slice now has full metadata trio

    Removed

    • components/ThemePicker.tsx (4-grid picker, replaced)
    • components/TweakcnSwitcher.tsx (replaced by ThemePresetSwitcher)
    • components/tweakcn/{ModeRow,PresetList}.tsx (inlined into switcher)
    • useThemePreset.ts (old hook, replaced by context-backed one in Provider)
    • presets.ts + presets/ (old THEME_PRESETS path, never used externally)
    • app/preview/slices/theme-preset-switcher/* (phantom slice preview)

    Updated

    • lib/tweakcn/registry.ts — dynamic import of registry-data.json (was fetch /r/registry.json)
    • lib/tweakcn/groups.ts — added HIDDEN_PRESETS + Indonesian group labels
    • lib/tweakcn/types.ts — dropped REGISTRY_URL constant (no longer needed)
    • index.ts barrel — new exports (drop ThemePicker, TweakcnSwitcher)
    • app/preview/slices/theme-presets/page.tsx — uses new ThemePresetSwitcher

    Catalog

    • theme-presets v0.1.0 → v0.2.0
    • DROPPED theme-preset-switcher (phantom, never on disk)
    • Slice count: 45 → 44
  • frontend/slices/database-io/{slice.json, slice.manifest.json, slice.contract.ts, index.ts, types.ts}
  • components/DatabaseIOActions.tsx — single combined dropdown (6 items + 2 dialogs)
  • components/CsvImportDialog.tsx + csv-mapping.tsx — column mapper (lifted from database-csv)
  • components/JsonImportDialog.tsx — file picker + preview (lifted from database-json)
  • lib/csv.ts — exportDatabaseToCsv + parseCsv + downloadCsv + valueFromString (lifted)
  • lib/serialize.ts — exportDatabase + parseExport + diffSchema + buildImportResult + downloadJson (lifted)
  • lib/template.ts — NEW buildCsvTemplate + buildJsonTemplate (per-type placeholder hints)
  • Removed (hard delete)

    • frontend/slices/database-csv/* (replaced by database-io)
    • frontend/slices/database-json/* (replaced by database-io)
    • app/preview/slices/database-csv/page.tsx (replaced by /preview/slices/database-io)
    • app/preview/slices/database-json/page.tsx (replaced by /preview/slices/database-io)

    Catalog UI — family sub-grouping

    • components/site/catalog/catalog-tabs-parts.tsx — new CatalogGroupedGrid + FamilyOf type
    • components/site/catalog/catalog-tabs.tsx — accepts optional familyOf + familyLabel props
    • app/(docs)/slices/family-map.ts — FAMILY_OVERRIDES + FAMILY_LABEL + familyOfSlug()
    • app/(docs)/slices/page.tsx — passes familyOf to CatalogTabs
    • Singleton families fall back to flat row (no `family of 1` headers)

    Catalog

    • NEW database-io 0.1.0 — peer of notion-database ^0.3
    • REMOVED database-csv 0.1.0
    • REMOVED database-json 0.1.0
    • Slice count: 46 → 45 (net -1 after merge)
  • components/JsonActions.tsx — Export + Import dropdown trigger
  • components/JsonImportDialog.tsx — file picker + preview + submit
  • lib/serialize.ts — exportDatabase + parseExport + diffSchema + buildImportResult + downloadJson
  • API

    • JsonActions: { db, rows, onImport, className? }
    • JsonImportDialog: { db, open, onOpenChange, onImport }
    • onImport: ({ newProperties, rows, importedDb }) => Promise<void> | void
    • Result shape MIRRORS CsvImportResult — single host handler works for both
    • Lower-level: exportDatabase / parseExport / diffSchema / buildImportResult exported standalone

    Catalog

    • NEW database-json 0.1.0 — peer of notion-database ^0.4
    • Slice count: 45 → 46. JSON import/export 0% → 100%.
    • Database adaptation: ~80% → ~82%

    Deferred (post upstream mega-bundle)

    • AI-assisted row generation (AIAssistDialog + lib/ai.ts — separate AI router peer)
    • Cover + blocks + sub-items + templates wire fields (need cross-block + cross-DB context)
    • components/views/FormView.tsx — main form (155 LOC)
    • components/views/form-settings.tsx — settings panel (102 LOC)
    • components/views/form-helpers.ts — predicates + draft factory (32 LOC)

    API

    • ViewProps.onRowCreate — new optional callback
    • NotionDatabaseProps.onRowCreate — forwarded to view
    • DatabaseViewConfig.formTitle + formDescription — new optional fields
    • FormView reuses renderPropertyCell for per-property inputs — no separate widget

    Coverage

    • Views: 10/11 → 11/11 (100%)
    • Property types: 16/17 (94%, unchanged)
    • Filter/Sort UI: 100% (unchanged)
    • CSV import/export: 100% (database-csv slice, CK-4)
    • notion-database 0.3.0 → 0.4.0
    • Database adaptation: ~76% → ~80%

    Deferred (post upstream mega-bundle)

    • relation + rollup property types — need cross-DB context
    • JSON import — same pattern as CSV but lower demand