rahman-resources 0.12.0 → 1.0.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/bin/cli.js +39 -31
- package/lib/contract.ts +116 -0
- package/lib/manifest.json +615 -34
- package/package.json +5 -3
package/bin/cli.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
//
|
|
2
|
+
// Rahman Resources (rr) — shadcn-style installer for vertical slices.
|
|
3
|
+
// Aliases: `rahman-resources`, `resources`, `rr` (all run this file).
|
|
3
4
|
// Usage:
|
|
4
|
-
// npx
|
|
5
|
-
// npx
|
|
6
|
-
// npx
|
|
7
|
-
// npx
|
|
8
|
-
// npx
|
|
9
|
-
// npx
|
|
10
|
-
// npx
|
|
11
|
-
// npx
|
|
5
|
+
// npx rr init <app-name> [--template <slug>] [--features a,b] [--skills x,y] [--with-shadcn-all]
|
|
6
|
+
// npx rr add <slug> [target-dir] [--at root|preview] [--with-shadcn-all]
|
|
7
|
+
// npx rr add-skill <slug> [target-dir]
|
|
8
|
+
// npx rr scaffold-slice <slug> [--category <cat>] [--target <dir>]
|
|
9
|
+
// npx rr list [layouts|recipes|features|skills|slices]
|
|
10
|
+
// npx rr info <slug>
|
|
11
|
+
// npx rr doctor
|
|
12
|
+
// npx rr mcp # not implemented in CLI; install rahman-resources-mcp
|
|
12
13
|
|
|
13
14
|
import { createRequire } from "node:module";
|
|
14
15
|
import { spawn } from "node:child_process";
|
|
@@ -113,22 +114,25 @@ function printHelp() {
|
|
|
113
114
|
console.log(`
|
|
114
115
|
${kleur.bold("rahman-resources")} — scaffold + install templates, recipes, features, Claude skills
|
|
115
116
|
|
|
117
|
+
${kleur.bold("Rahman Resources (rr)")} — shadcn-style installer for vertical slices.
|
|
118
|
+
${kleur.dim("Bins: rahman-resources / resources / rr (all run this CLI).")}
|
|
119
|
+
|
|
116
120
|
${kleur.bold("Usage:")}
|
|
117
|
-
npx
|
|
118
|
-
|
|
119
|
-
npx
|
|
120
|
-
npx
|
|
121
|
-
npx
|
|
122
|
-
npx
|
|
123
|
-
npx
|
|
124
|
-
npx
|
|
125
|
-
npx
|
|
126
|
-
npx
|
|
127
|
-
npx
|
|
128
|
-
npx
|
|
129
|
-
npx
|
|
130
|
-
npx
|
|
131
|
-
npx
|
|
121
|
+
npx rr init <app-name> [--template <slug>] [--features a,b] [--skills x,y]
|
|
122
|
+
[--no-install] [--with-shadcn-reinit] [--with-shadcn-all]
|
|
123
|
+
npx rr add <slug> [target-dir] [--at root|preview] [--with-shadcn-all]
|
|
124
|
+
npx rr add-skill <slug> [target-dir]
|
|
125
|
+
npx rr scaffold-slice <slug> [--category <cat>] [--target <dir>]
|
|
126
|
+
npx rr lift <source>:<path> [--target <dir>] [--dry-run]
|
|
127
|
+
npx rr publish-slice <local-slice-dir> [--open-pr]
|
|
128
|
+
npx rr list [layouts|recipes|features|skills|slices]
|
|
129
|
+
npx rr info <slug>
|
|
130
|
+
npx rr doctor
|
|
131
|
+
npx rr graph [slug] [--all] [--json]
|
|
132
|
+
npx rr compose <slug>... [--json] [--rr-path <path>] [--no-deps] [--strict]
|
|
133
|
+
npx rr update <slug> [--apply] [--force] [--rr-path P] [--json]
|
|
134
|
+
npx rr migrate <slug> --from <v1> [--to <v2>] [--json] [--write-files] [--force-overwrite]
|
|
135
|
+
npx rr mcp
|
|
132
136
|
|
|
133
137
|
${kleur.bold("Init flags:")}
|
|
134
138
|
--no-install skip 'npm install' step (faster scaffolds; you run it manually)
|
|
@@ -145,13 +149,17 @@ ${kleur.bold("Add flags:")}
|
|
|
145
149
|
--force skip compose pre-flight entirely
|
|
146
150
|
|
|
147
151
|
${kleur.bold("Examples:")}
|
|
148
|
-
npx
|
|
149
|
-
npx
|
|
150
|
-
npx
|
|
151
|
-
npx
|
|
152
|
-
npx
|
|
153
|
-
npx
|
|
154
|
-
npx
|
|
152
|
+
npx rr init my-app
|
|
153
|
+
npx rr init my-app --template personal-brand-os --skills frontend-design,mcp-builder
|
|
154
|
+
npx rr init my-app --no-install
|
|
155
|
+
npx rr add personal-brand-os . --at root
|
|
156
|
+
npx rr add personal-brand-os . --with-shadcn-all
|
|
157
|
+
npx rr add-skill webapp-testing
|
|
158
|
+
npx rr list skills
|
|
159
|
+
|
|
160
|
+
${kleur.dim("Slice install destination (consumer): slices/<slug>/")}
|
|
161
|
+
${kleur.dim("Shared utils destination (cascade): shared/<name>/")}
|
|
162
|
+
${kleur.dim("Consumer's components/ui/ + lib/utils.ts (shadcn) are never touched.")}
|
|
155
163
|
`);
|
|
156
164
|
}
|
|
157
165
|
|
package/lib/contract.ts
CHANGED
|
@@ -92,6 +92,66 @@ export interface SliceContractProvides {
|
|
|
92
92
|
components?: string[];
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
// `bidir` block — Wave N+3 (Bidirectional Sync Detection Layer)
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* How the kitab treats sync between this slice and consumer copies.
|
|
101
|
+
*
|
|
102
|
+
* - `auto-pr`: when `rr scan-consumers` sees an `up-needed` verdict on a
|
|
103
|
+
* consumer's `.kitab.json`, the operator workflow auto-opens a PR against
|
|
104
|
+
* the kitab. Reserved for slices with strict generalisation gates.
|
|
105
|
+
* - `notify`: surface in the scan report; no auto-action.
|
|
106
|
+
* - `manual`: default — operator picks up via `/rr-prep` + `/rr-send`.
|
|
107
|
+
* - `frozen`: kitab refuses both UP and DOWN sync. Lock for retired slices.
|
|
108
|
+
*/
|
|
109
|
+
export type SliceSyncPolicy = "auto-pr" | "notify" | "manual" | "frozen";
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Generalisation level a consumer-side `.kitab.json` MUST claim before
|
|
113
|
+
* `rr-send` accepts the push back into the kitab.
|
|
114
|
+
*
|
|
115
|
+
* - `portable`: no consumer-specific business terms baked in. UP-sync allowed.
|
|
116
|
+
* - `needs-adapter`: requires a thin adapter wired by the consumer; UP-sync
|
|
117
|
+
* blocked until blockers are addressed (or the contract drops the slice
|
|
118
|
+
* to `consumer-locked`).
|
|
119
|
+
* - `consumer-locked`: contains business-specific logic that cannot be
|
|
120
|
+
* generalised. Only DOWN-sync allowed.
|
|
121
|
+
*/
|
|
122
|
+
export type GeneralizationLevel =
|
|
123
|
+
| "portable"
|
|
124
|
+
| "needs-adapter"
|
|
125
|
+
| "consumer-locked";
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Generalisation contract — what the audit-bp `forbiddenTerms` rule scans
|
|
129
|
+
* for, and which props the consumer MUST inject.
|
|
130
|
+
*/
|
|
131
|
+
export interface SliceGeneralization {
|
|
132
|
+
level: GeneralizationLevel;
|
|
133
|
+
/**
|
|
134
|
+
* Identifiers / business terms that MUST NOT appear in the slice source
|
|
135
|
+
* tree. Audit-bp scans .ts/.tsx files. Empty when the slice is generic.
|
|
136
|
+
*/
|
|
137
|
+
forbiddenTerms?: string[];
|
|
138
|
+
/**
|
|
139
|
+
* Props the consumer must inject for the slice to remain portable —
|
|
140
|
+
* e.g. `["basePath", "labels", "permission"]`.
|
|
141
|
+
*/
|
|
142
|
+
requiredProps?: string[];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Bidirectional sync block. Optional, additive — slices without it default to
|
|
147
|
+
* `{ syncPolicy: "manual", generalization: { level: "portable" } }` for
|
|
148
|
+
* legacy compatibility with Wave N+1 contracts.
|
|
149
|
+
*/
|
|
150
|
+
export interface SliceBidirContract {
|
|
151
|
+
syncPolicy: SliceSyncPolicy;
|
|
152
|
+
generalization: SliceGeneralization;
|
|
153
|
+
}
|
|
154
|
+
|
|
95
155
|
// ---------------------------------------------------------------------------
|
|
96
156
|
// Top-level contract
|
|
97
157
|
// ---------------------------------------------------------------------------
|
|
@@ -121,6 +181,8 @@ export interface SliceContract {
|
|
|
121
181
|
conflicts?: string[];
|
|
122
182
|
/** Map of previous-version → migration script id. */
|
|
123
183
|
migrationFrom?: Record<string, string>;
|
|
184
|
+
/** Wave N+3 — bidirectional sync policy + generalisation gate. */
|
|
185
|
+
bidir?: SliceBidirContract;
|
|
124
186
|
}
|
|
125
187
|
|
|
126
188
|
// ---------------------------------------------------------------------------
|
|
@@ -222,6 +284,60 @@ export function defineSliceContract(c: SliceContract): SliceContract {
|
|
|
222
284
|
}
|
|
223
285
|
}
|
|
224
286
|
|
|
287
|
+
// bidir block — Wave N+3
|
|
288
|
+
if (c.bidir !== undefined) {
|
|
289
|
+
if (!c.bidir || typeof c.bidir !== "object") {
|
|
290
|
+
throw new Error(`defineSliceContract(${c.id}): bidir must be an object`);
|
|
291
|
+
}
|
|
292
|
+
const policies = ["auto-pr", "notify", "manual", "frozen"];
|
|
293
|
+
if (!policies.includes(c.bidir.syncPolicy)) {
|
|
294
|
+
throw new Error(
|
|
295
|
+
`defineSliceContract(${c.id}): bidir.syncPolicy "${String(c.bidir.syncPolicy)}" must be one of ${policies.join("|")}`,
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
if (!c.bidir.generalization || typeof c.bidir.generalization !== "object") {
|
|
299
|
+
throw new Error(
|
|
300
|
+
`defineSliceContract(${c.id}): bidir.generalization must be an object`,
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
const levels = ["portable", "needs-adapter", "consumer-locked"];
|
|
304
|
+
if (!levels.includes(c.bidir.generalization.level)) {
|
|
305
|
+
throw new Error(
|
|
306
|
+
`defineSliceContract(${c.id}): bidir.generalization.level "${String(c.bidir.generalization.level)}" must be one of ${levels.join("|")}`,
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
const ft = c.bidir.generalization.forbiddenTerms;
|
|
310
|
+
if (ft !== undefined) {
|
|
311
|
+
if (!Array.isArray(ft)) {
|
|
312
|
+
throw new Error(
|
|
313
|
+
`defineSliceContract(${c.id}): bidir.generalization.forbiddenTerms must be an array`,
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
for (const t of ft) {
|
|
317
|
+
if (typeof t !== "string" || t.length === 0) {
|
|
318
|
+
throw new Error(
|
|
319
|
+
`defineSliceContract(${c.id}): bidir.generalization.forbiddenTerms entries must be non-empty strings`,
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
const rp = c.bidir.generalization.requiredProps;
|
|
325
|
+
if (rp !== undefined) {
|
|
326
|
+
if (!Array.isArray(rp)) {
|
|
327
|
+
throw new Error(
|
|
328
|
+
`defineSliceContract(${c.id}): bidir.generalization.requiredProps must be an array`,
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
for (const p of rp) {
|
|
332
|
+
if (typeof p !== "string" || p.length === 0) {
|
|
333
|
+
throw new Error(
|
|
334
|
+
`defineSliceContract(${c.id}): bidir.generalization.requiredProps entries must be non-empty strings`,
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
225
341
|
// Conflicts
|
|
226
342
|
if (c.conflicts) {
|
|
227
343
|
if (!Array.isArray(c.conflicts)) {
|
package/lib/manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 2,
|
|
3
|
-
"generatedAt": "2026-05-
|
|
3
|
+
"generatedAt": "2026-05-16T08:10:45.510Z",
|
|
4
4
|
"repo": "rahmanef63/resource-site",
|
|
5
5
|
"branch": "main",
|
|
6
6
|
"layouts": [
|
|
@@ -802,6 +802,456 @@
|
|
|
802
802
|
"indonesia"
|
|
803
803
|
],
|
|
804
804
|
"primaryFile": "app/preview/riset-kit/public/page.tsx"
|
|
805
|
+
},
|
|
806
|
+
{
|
|
807
|
+
"slug": "hero-centered",
|
|
808
|
+
"title": "Hero — Centered",
|
|
809
|
+
"category": "marketing",
|
|
810
|
+
"description": "Single-column centered hero with eyebrow pill, headline, sub-copy, and dual CTA. Radial gradient backdrop.",
|
|
811
|
+
"source": "kitab",
|
|
812
|
+
"repoPath": "app/preview/hero-centered",
|
|
813
|
+
"pullPaths": [
|
|
814
|
+
"app/preview/hero-centered"
|
|
815
|
+
],
|
|
816
|
+
"files": [],
|
|
817
|
+
"dependencies": [],
|
|
818
|
+
"shadcnComponents": [],
|
|
819
|
+
"agentRecipe": "Pure layout. Drop into landing pages where the product needs minimum framing. Replace the eyebrow pill with a status badge or release tag. Two CTAs is the sweet spot.",
|
|
820
|
+
"tags": [
|
|
821
|
+
"block",
|
|
822
|
+
"hero",
|
|
823
|
+
"centered",
|
|
824
|
+
"marketing"
|
|
825
|
+
],
|
|
826
|
+
"primaryFile": "app/preview/hero-centered/page.tsx"
|
|
827
|
+
},
|
|
828
|
+
{
|
|
829
|
+
"slug": "hero-split",
|
|
830
|
+
"title": "Hero — Split (Text + Visual)",
|
|
831
|
+
"category": "marketing",
|
|
832
|
+
"description": "Two-column hero: left copy + feature list + CTAs, right visual slot. 9-cell mock grid placeholder for product shot.",
|
|
833
|
+
"source": "kitab",
|
|
834
|
+
"repoPath": "app/preview/hero-split",
|
|
835
|
+
"pullPaths": [
|
|
836
|
+
"app/preview/hero-split"
|
|
837
|
+
],
|
|
838
|
+
"files": [],
|
|
839
|
+
"dependencies": [],
|
|
840
|
+
"shadcnComponents": [],
|
|
841
|
+
"agentRecipe": "Right column accepts any visual — screenshot, product mock, illustration, or live demo iframe. Feature list pairs Lucide icons with one-line value props.",
|
|
842
|
+
"tags": [
|
|
843
|
+
"block",
|
|
844
|
+
"hero",
|
|
845
|
+
"split",
|
|
846
|
+
"marketing",
|
|
847
|
+
"product"
|
|
848
|
+
],
|
|
849
|
+
"primaryFile": "app/preview/hero-split/page.tsx"
|
|
850
|
+
},
|
|
851
|
+
{
|
|
852
|
+
"slug": "hero-bento-bg",
|
|
853
|
+
"title": "Hero — Bento Background",
|
|
854
|
+
"category": "marketing",
|
|
855
|
+
"description": "Bento mini-grid behind a centered headline. Radial mask focuses the eye on the copy while the grid hints at features.",
|
|
856
|
+
"source": "kitab",
|
|
857
|
+
"repoPath": "app/preview/hero-bento-bg",
|
|
858
|
+
"pullPaths": [
|
|
859
|
+
"app/preview/hero-bento-bg"
|
|
860
|
+
],
|
|
861
|
+
"files": [],
|
|
862
|
+
"dependencies": [],
|
|
863
|
+
"shadcnComponents": [],
|
|
864
|
+
"agentRecipe": "Background tiles get a radial mask so the center stays readable. Use 6-8 tiles with asymmetric spans (col-span-2 row-span-2 for one, others 1x1). Lucide icon in each tile.",
|
|
865
|
+
"tags": [
|
|
866
|
+
"block",
|
|
867
|
+
"hero",
|
|
868
|
+
"bento",
|
|
869
|
+
"marketing",
|
|
870
|
+
"decorative"
|
|
871
|
+
],
|
|
872
|
+
"primaryFile": "app/preview/hero-bento-bg/page.tsx"
|
|
873
|
+
},
|
|
874
|
+
{
|
|
875
|
+
"slug": "hero-video-loop",
|
|
876
|
+
"title": "Hero — Video Loop (dark)",
|
|
877
|
+
"category": "marketing",
|
|
878
|
+
"description": "Dark-mode hero with conic-gradient animated backdrop (stand-in for video). Play CTA, headline, dual CTA.",
|
|
879
|
+
"source": "kitab",
|
|
880
|
+
"repoPath": "app/preview/hero-video-loop",
|
|
881
|
+
"pullPaths": [
|
|
882
|
+
"app/preview/hero-video-loop"
|
|
883
|
+
],
|
|
884
|
+
"files": [],
|
|
885
|
+
"dependencies": [],
|
|
886
|
+
"shadcnComponents": [],
|
|
887
|
+
"agentRecipe": "Replace the conic-gradient backdrop with a muted <video autoplay loop>. Keep the dark theme — light text on motion only reads when the contrast is hard.",
|
|
888
|
+
"tags": [
|
|
889
|
+
"block",
|
|
890
|
+
"hero",
|
|
891
|
+
"video",
|
|
892
|
+
"marketing",
|
|
893
|
+
"dark"
|
|
894
|
+
],
|
|
895
|
+
"primaryFile": "app/preview/hero-video-loop/page.tsx"
|
|
896
|
+
},
|
|
897
|
+
{
|
|
898
|
+
"slug": "hero-animated-text",
|
|
899
|
+
"title": "Hero — Animated Text",
|
|
900
|
+
"category": "marketing",
|
|
901
|
+
"description": "Rotating word inside the headline cycles every 2s with gradient text + fade-slide transition. Lightweight, no extra deps.",
|
|
902
|
+
"source": "kitab",
|
|
903
|
+
"repoPath": "app/preview/hero-animated-text",
|
|
904
|
+
"pullPaths": [
|
|
905
|
+
"app/preview/hero-animated-text"
|
|
906
|
+
],
|
|
907
|
+
"files": [],
|
|
908
|
+
"dependencies": [],
|
|
909
|
+
"shadcnComponents": [],
|
|
910
|
+
"agentRecipe": "Use absolute-positioned word slots with translate-y + opacity transitions. The invisible placeholder word keeps the bounding box stable.",
|
|
911
|
+
"tags": [
|
|
912
|
+
"block",
|
|
913
|
+
"hero",
|
|
914
|
+
"motion",
|
|
915
|
+
"marketing",
|
|
916
|
+
"kinetic"
|
|
917
|
+
],
|
|
918
|
+
"primaryFile": "app/preview/hero-animated-text/page.tsx"
|
|
919
|
+
},
|
|
920
|
+
{
|
|
921
|
+
"slug": "pricing-three",
|
|
922
|
+
"title": "Pricing — Three Tier",
|
|
923
|
+
"category": "marketing",
|
|
924
|
+
"description": "Classic 3-tier card layout. Middle tier highlighted with Most Popular badge + soft shadow.",
|
|
925
|
+
"source": "kitab",
|
|
926
|
+
"repoPath": "app/preview/pricing-three",
|
|
927
|
+
"pullPaths": [
|
|
928
|
+
"app/preview/pricing-three"
|
|
929
|
+
],
|
|
930
|
+
"files": [],
|
|
931
|
+
"dependencies": [],
|
|
932
|
+
"shadcnComponents": [],
|
|
933
|
+
"agentRecipe": "Three is the magic number for SaaS pricing — fewer feels limited, more triggers analysis paralysis. Middle tier should be the one you actually want to sell.",
|
|
934
|
+
"tags": [
|
|
935
|
+
"block",
|
|
936
|
+
"pricing",
|
|
937
|
+
"marketing",
|
|
938
|
+
"saas"
|
|
939
|
+
],
|
|
940
|
+
"primaryFile": "app/preview/pricing-three/page.tsx"
|
|
941
|
+
},
|
|
942
|
+
{
|
|
943
|
+
"slug": "pricing-four",
|
|
944
|
+
"title": "Pricing — Four Tier",
|
|
945
|
+
"category": "marketing",
|
|
946
|
+
"description": "Four-tier with Best Value badge on tier 3. Compact card chrome, 4-column grid that collapses gracefully.",
|
|
947
|
+
"source": "kitab",
|
|
948
|
+
"repoPath": "app/preview/pricing-four",
|
|
949
|
+
"pullPaths": [
|
|
950
|
+
"app/preview/pricing-four"
|
|
951
|
+
],
|
|
952
|
+
"files": [],
|
|
953
|
+
"dependencies": [],
|
|
954
|
+
"shadcnComponents": [],
|
|
955
|
+
"agentRecipe": "Use when you genuinely have four distinct tiers (free / solo / team / enterprise). Don't pad to four — use the three-tier variant if the fourth is forced.",
|
|
956
|
+
"tags": [
|
|
957
|
+
"block",
|
|
958
|
+
"pricing",
|
|
959
|
+
"marketing",
|
|
960
|
+
"saas"
|
|
961
|
+
],
|
|
962
|
+
"primaryFile": "app/preview/pricing-four/page.tsx"
|
|
963
|
+
},
|
|
964
|
+
{
|
|
965
|
+
"slug": "pricing-toggle",
|
|
966
|
+
"title": "Pricing — Monthly/Yearly Toggle",
|
|
967
|
+
"category": "marketing",
|
|
968
|
+
"description": "3-tier with a monthly/yearly pill toggle. Yearly price strikethroughs the monthly, -20% savings badge inside the toggle.",
|
|
969
|
+
"source": "kitab",
|
|
970
|
+
"repoPath": "app/preview/pricing-toggle",
|
|
971
|
+
"pullPaths": [
|
|
972
|
+
"app/preview/pricing-toggle"
|
|
973
|
+
],
|
|
974
|
+
"files": [],
|
|
975
|
+
"dependencies": [],
|
|
976
|
+
"shadcnComponents": [],
|
|
977
|
+
"agentRecipe": "Default to yearly — that's the conversion-optimized choice. Show the monthly strikethrough so the savings feel real, not implied.",
|
|
978
|
+
"tags": [
|
|
979
|
+
"block",
|
|
980
|
+
"pricing",
|
|
981
|
+
"marketing",
|
|
982
|
+
"interactive"
|
|
983
|
+
],
|
|
984
|
+
"primaryFile": "app/preview/pricing-toggle/page.tsx"
|
|
985
|
+
},
|
|
986
|
+
{
|
|
987
|
+
"slug": "pricing-compare",
|
|
988
|
+
"title": "Pricing — Feature Comparison",
|
|
989
|
+
"category": "marketing",
|
|
990
|
+
"description": "Single comparison table: feature rows × plan columns. Check/Minus icons, header row with prices, sticky CTA row.",
|
|
991
|
+
"source": "kitab",
|
|
992
|
+
"repoPath": "app/preview/pricing-compare",
|
|
993
|
+
"pullPaths": [
|
|
994
|
+
"app/preview/pricing-compare"
|
|
995
|
+
],
|
|
996
|
+
"files": [],
|
|
997
|
+
"dependencies": [],
|
|
998
|
+
"shadcnComponents": [],
|
|
999
|
+
"agentRecipe": "Use for complex products where buyers actually compare. Mix boolean rows (Check/Minus) with string-value rows (\"1\", \"10\", \"Unlimited\") for clarity.",
|
|
1000
|
+
"tags": [
|
|
1001
|
+
"block",
|
|
1002
|
+
"pricing",
|
|
1003
|
+
"marketing",
|
|
1004
|
+
"comparison",
|
|
1005
|
+
"table"
|
|
1006
|
+
],
|
|
1007
|
+
"primaryFile": "app/preview/pricing-compare/page.tsx"
|
|
1008
|
+
},
|
|
1009
|
+
{
|
|
1010
|
+
"slug": "pricing-slider",
|
|
1011
|
+
"title": "Pricing — Usage Slider",
|
|
1012
|
+
"category": "marketing",
|
|
1013
|
+
"description": "Range slider drives the price. Tier name and per-seat cost update live. Single-card layout, focus on the math.",
|
|
1014
|
+
"source": "kitab",
|
|
1015
|
+
"repoPath": "app/preview/pricing-slider",
|
|
1016
|
+
"pullPaths": [
|
|
1017
|
+
"app/preview/pricing-slider"
|
|
1018
|
+
],
|
|
1019
|
+
"files": [],
|
|
1020
|
+
"dependencies": [],
|
|
1021
|
+
"shadcnComponents": [],
|
|
1022
|
+
"agentRecipe": "Use for usage-based or seat-based products. Make the breakpoints transparent — buyers should be able to predict the next price without surprises.",
|
|
1023
|
+
"tags": [
|
|
1024
|
+
"block",
|
|
1025
|
+
"pricing",
|
|
1026
|
+
"marketing",
|
|
1027
|
+
"interactive",
|
|
1028
|
+
"usage"
|
|
1029
|
+
],
|
|
1030
|
+
"primaryFile": "app/preview/pricing-slider/page.tsx"
|
|
1031
|
+
},
|
|
1032
|
+
{
|
|
1033
|
+
"slug": "accordion-faq",
|
|
1034
|
+
"title": "Accordion — Classic FAQ",
|
|
1035
|
+
"category": "marketing",
|
|
1036
|
+
"description": "Single-open FAQ accordion. ChevronDown rotates, content reveals below. Clean, compact, perfect for support pages.",
|
|
1037
|
+
"source": "kitab",
|
|
1038
|
+
"repoPath": "app/preview/accordion-faq",
|
|
1039
|
+
"pullPaths": [
|
|
1040
|
+
"app/preview/accordion-faq"
|
|
1041
|
+
],
|
|
1042
|
+
"files": [],
|
|
1043
|
+
"dependencies": [],
|
|
1044
|
+
"shadcnComponents": [],
|
|
1045
|
+
"agentRecipe": "Single-open keeps the page short. Use when answers are independent. Switch to multi-open if buyers tend to scan multiple answers at once.",
|
|
1046
|
+
"tags": [
|
|
1047
|
+
"block",
|
|
1048
|
+
"accordion",
|
|
1049
|
+
"faq",
|
|
1050
|
+
"marketing"
|
|
1051
|
+
],
|
|
1052
|
+
"primaryFile": "app/preview/accordion-faq/page.tsx"
|
|
1053
|
+
},
|
|
1054
|
+
{
|
|
1055
|
+
"slug": "accordion-grouped",
|
|
1056
|
+
"title": "Accordion — Grouped Sections",
|
|
1057
|
+
"category": "marketing",
|
|
1058
|
+
"description": "FAQ split into themed groups (Getting Started / Slices / Billing). Each group is its own card. Independent open state per item.",
|
|
1059
|
+
"source": "kitab",
|
|
1060
|
+
"repoPath": "app/preview/accordion-grouped",
|
|
1061
|
+
"pullPaths": [
|
|
1062
|
+
"app/preview/accordion-grouped"
|
|
1063
|
+
],
|
|
1064
|
+
"files": [],
|
|
1065
|
+
"dependencies": [],
|
|
1066
|
+
"shadcnComponents": [],
|
|
1067
|
+
"agentRecipe": "Use when the FAQ is long (>10 items) and questions cluster naturally. Each group's Item owns its open state for predictable UX.",
|
|
1068
|
+
"tags": [
|
|
1069
|
+
"block",
|
|
1070
|
+
"accordion",
|
|
1071
|
+
"faq",
|
|
1072
|
+
"marketing",
|
|
1073
|
+
"grouped"
|
|
1074
|
+
],
|
|
1075
|
+
"primaryFile": "app/preview/accordion-grouped/page.tsx"
|
|
1076
|
+
},
|
|
1077
|
+
{
|
|
1078
|
+
"slug": "accordion-sidebar",
|
|
1079
|
+
"title": "Accordion — Sidebar Navigation",
|
|
1080
|
+
"category": "marketing",
|
|
1081
|
+
"description": "Docs-style: left nav switches sections, right pane shows the section's accordion. Two-axis navigation in one layout.",
|
|
1082
|
+
"source": "kitab",
|
|
1083
|
+
"repoPath": "app/preview/accordion-sidebar",
|
|
1084
|
+
"pullPaths": [
|
|
1085
|
+
"app/preview/accordion-sidebar"
|
|
1086
|
+
],
|
|
1087
|
+
"files": [],
|
|
1088
|
+
"dependencies": [],
|
|
1089
|
+
"shadcnComponents": [],
|
|
1090
|
+
"agentRecipe": "Use for help/docs pages with section breadth. Keep section count ≤ 5 — beyond that, the sidebar gets noisy. Reset accordion state on section change.",
|
|
1091
|
+
"tags": [
|
|
1092
|
+
"block",
|
|
1093
|
+
"accordion",
|
|
1094
|
+
"docs",
|
|
1095
|
+
"sidebar",
|
|
1096
|
+
"navigation"
|
|
1097
|
+
],
|
|
1098
|
+
"primaryFile": "app/preview/accordion-sidebar/page.tsx"
|
|
1099
|
+
},
|
|
1100
|
+
{
|
|
1101
|
+
"slug": "accordion-animated",
|
|
1102
|
+
"title": "Accordion — Smooth Animated",
|
|
1103
|
+
"category": "marketing",
|
|
1104
|
+
"description": "Grid-row transition for true height animation, no janky calc. Each item is a rounded card with rotating plus → primary close icon.",
|
|
1105
|
+
"source": "kitab",
|
|
1106
|
+
"repoPath": "app/preview/accordion-animated",
|
|
1107
|
+
"pullPaths": [
|
|
1108
|
+
"app/preview/accordion-animated"
|
|
1109
|
+
],
|
|
1110
|
+
"files": [],
|
|
1111
|
+
"dependencies": [],
|
|
1112
|
+
"shadcnComponents": [],
|
|
1113
|
+
"agentRecipe": "The grid-template-rows trick lets CSS animate to-auto-height natively. No JS measurement, no jank. Pair with rounded card chrome for premium feel.",
|
|
1114
|
+
"tags": [
|
|
1115
|
+
"block",
|
|
1116
|
+
"accordion",
|
|
1117
|
+
"marketing",
|
|
1118
|
+
"motion"
|
|
1119
|
+
],
|
|
1120
|
+
"primaryFile": "app/preview/accordion-animated/page.tsx"
|
|
1121
|
+
},
|
|
1122
|
+
{
|
|
1123
|
+
"slug": "accordion-multi",
|
|
1124
|
+
"title": "Accordion — Multi-open",
|
|
1125
|
+
"category": "marketing",
|
|
1126
|
+
"description": "All items can be open at once. Expand-all / Collapse-all toggle in header. Best for compare-style reading.",
|
|
1127
|
+
"source": "kitab",
|
|
1128
|
+
"repoPath": "app/preview/accordion-multi",
|
|
1129
|
+
"pullPaths": [
|
|
1130
|
+
"app/preview/accordion-multi"
|
|
1131
|
+
],
|
|
1132
|
+
"files": [],
|
|
1133
|
+
"dependencies": [],
|
|
1134
|
+
"shadcnComponents": [],
|
|
1135
|
+
"agentRecipe": "Use when answers reference each other or buyers want to keep multiple sections visible (changelogs, release notes, feature comparison FAQs).",
|
|
1136
|
+
"tags": [
|
|
1137
|
+
"block",
|
|
1138
|
+
"accordion",
|
|
1139
|
+
"marketing",
|
|
1140
|
+
"multi-open"
|
|
1141
|
+
],
|
|
1142
|
+
"primaryFile": "app/preview/accordion-multi/page.tsx"
|
|
1143
|
+
},
|
|
1144
|
+
{
|
|
1145
|
+
"slug": "blog-grid",
|
|
1146
|
+
"title": "Blog — Card Grid",
|
|
1147
|
+
"category": "cms",
|
|
1148
|
+
"description": "3-column responsive card grid. Cover thumbnail (HSL gradient), title, excerpt, author·date·read meta. Default blog index shape.",
|
|
1149
|
+
"source": "kitab",
|
|
1150
|
+
"repoPath": "app/preview/blog-grid",
|
|
1151
|
+
"pullPaths": [
|
|
1152
|
+
"app/preview/blog-grid"
|
|
1153
|
+
],
|
|
1154
|
+
"files": [],
|
|
1155
|
+
"dependencies": [],
|
|
1156
|
+
"shadcnComponents": [],
|
|
1157
|
+
"agentRecipe": "Default to 3 columns at lg. Use the Thumb helper for cover generation when posts don't ship an image yet — HSL gradient by post.hue keeps each card distinct.",
|
|
1158
|
+
"tags": [
|
|
1159
|
+
"block",
|
|
1160
|
+
"blog",
|
|
1161
|
+
"cms",
|
|
1162
|
+
"grid"
|
|
1163
|
+
],
|
|
1164
|
+
"primaryFile": "app/preview/blog-grid/page.tsx"
|
|
1165
|
+
},
|
|
1166
|
+
{
|
|
1167
|
+
"slug": "blog-list",
|
|
1168
|
+
"title": "Blog — Dense List",
|
|
1169
|
+
"category": "cms",
|
|
1170
|
+
"description": "Single-column scannable list. Thumbnail left, meta + title + excerpt right. High density, low scroll.",
|
|
1171
|
+
"source": "kitab",
|
|
1172
|
+
"repoPath": "app/preview/blog-list",
|
|
1173
|
+
"pullPaths": [
|
|
1174
|
+
"app/preview/blog-list"
|
|
1175
|
+
],
|
|
1176
|
+
"files": [],
|
|
1177
|
+
"dependencies": [],
|
|
1178
|
+
"shadcnComponents": [],
|
|
1179
|
+
"agentRecipe": "Use for archives or category pages where the reader is hunting a specific post. Compact thumbnail keeps the line height tight.",
|
|
1180
|
+
"tags": [
|
|
1181
|
+
"block",
|
|
1182
|
+
"blog",
|
|
1183
|
+
"cms",
|
|
1184
|
+
"list"
|
|
1185
|
+
],
|
|
1186
|
+
"primaryFile": "app/preview/blog-list/page.tsx"
|
|
1187
|
+
},
|
|
1188
|
+
{
|
|
1189
|
+
"slug": "blog-magazine",
|
|
1190
|
+
"title": "Blog — Magazine Layout",
|
|
1191
|
+
"category": "cms",
|
|
1192
|
+
"description": "Editorial spread: large hero post (2/3 width) + secondary featured + tail of headlines. Issue-number header gives quarterly feel.",
|
|
1193
|
+
"source": "kitab",
|
|
1194
|
+
"repoPath": "app/preview/blog-magazine",
|
|
1195
|
+
"pullPaths": [
|
|
1196
|
+
"app/preview/blog-magazine"
|
|
1197
|
+
],
|
|
1198
|
+
"files": [],
|
|
1199
|
+
"dependencies": [],
|
|
1200
|
+
"shadcnComponents": [],
|
|
1201
|
+
"agentRecipe": "Use for content-heavy publications. Hero post earns the visual real estate; the sidebar carries breadth. Mix typography sizes for editorial rhythm.",
|
|
1202
|
+
"tags": [
|
|
1203
|
+
"block",
|
|
1204
|
+
"blog",
|
|
1205
|
+
"cms",
|
|
1206
|
+
"editorial",
|
|
1207
|
+
"magazine"
|
|
1208
|
+
],
|
|
1209
|
+
"primaryFile": "app/preview/blog-magazine/page.tsx"
|
|
1210
|
+
},
|
|
1211
|
+
{
|
|
1212
|
+
"slug": "blog-masonry",
|
|
1213
|
+
"title": "Blog — Masonry",
|
|
1214
|
+
"category": "cms",
|
|
1215
|
+
"description": "CSS columns-based masonry with varying card heights for organic rhythm. break-inside-avoid keeps each card intact.",
|
|
1216
|
+
"source": "kitab",
|
|
1217
|
+
"repoPath": "app/preview/blog-masonry",
|
|
1218
|
+
"pullPaths": [
|
|
1219
|
+
"app/preview/blog-masonry"
|
|
1220
|
+
],
|
|
1221
|
+
"files": [],
|
|
1222
|
+
"dependencies": [],
|
|
1223
|
+
"shadcnComponents": [],
|
|
1224
|
+
"agentRecipe": "CSS columns are the cheap masonry — no JS, no layout shift. Vary the thumbnail height via a HEIGHTS array (h-44 to h-80). DOM order ≠ visual order — design around it.",
|
|
1225
|
+
"tags": [
|
|
1226
|
+
"block",
|
|
1227
|
+
"blog",
|
|
1228
|
+
"cms",
|
|
1229
|
+
"masonry"
|
|
1230
|
+
],
|
|
1231
|
+
"primaryFile": "app/preview/blog-masonry/page.tsx"
|
|
1232
|
+
},
|
|
1233
|
+
{
|
|
1234
|
+
"slug": "blog-featured",
|
|
1235
|
+
"title": "Blog — Featured Hero + Tail",
|
|
1236
|
+
"category": "cms",
|
|
1237
|
+
"description": "Full-bleed cover hero on the first post, then a tight 2-column grid for the rest. Cinematic open, fast scroll for the tail.",
|
|
1238
|
+
"source": "kitab",
|
|
1239
|
+
"repoPath": "app/preview/blog-featured",
|
|
1240
|
+
"pullPaths": [
|
|
1241
|
+
"app/preview/blog-featured"
|
|
1242
|
+
],
|
|
1243
|
+
"files": [],
|
|
1244
|
+
"dependencies": [],
|
|
1245
|
+
"shadcnComponents": [],
|
|
1246
|
+
"agentRecipe": "Use for marketing-driven content sites (newsletter, podcast, brand journal) where the lead story carries the visit. Tail grid keeps the index scrollable without losing the hero impact.",
|
|
1247
|
+
"tags": [
|
|
1248
|
+
"block",
|
|
1249
|
+
"blog",
|
|
1250
|
+
"cms",
|
|
1251
|
+
"featured",
|
|
1252
|
+
"hero"
|
|
1253
|
+
],
|
|
1254
|
+
"primaryFile": "app/preview/blog-featured/page.tsx"
|
|
805
1255
|
}
|
|
806
1256
|
],
|
|
807
1257
|
"recipes": [],
|
|
@@ -937,7 +1387,7 @@
|
|
|
937
1387
|
"slug": "mdx-blog",
|
|
938
1388
|
"title": "MDX Blog",
|
|
939
1389
|
"category": "content",
|
|
940
|
-
"description": "Markdown-with-JSX untuk blog post. File-based
|
|
1390
|
+
"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.",
|
|
941
1391
|
"source": "rahmanef63/resource-site",
|
|
942
1392
|
"docsUrl": "https://github.com/hashicorp/next-mdx-remote",
|
|
943
1393
|
"install": "npm i next-mdx-remote rehype-pretty-code remark-gfm reading-time",
|
|
@@ -997,23 +1447,24 @@
|
|
|
997
1447
|
},
|
|
998
1448
|
{
|
|
999
1449
|
"slug": "command-menu",
|
|
1000
|
-
"title": "Command Menu
|
|
1450
|
+
"title": "Command Menu",
|
|
1001
1451
|
"category": "ui",
|
|
1002
|
-
"description": "
|
|
1003
|
-
"source": "
|
|
1452
|
+
"description": "Renderless ⌘K command palette + generic search modal. Consumer supplies CommandGroup[] + onSelect + label bag; slice owns dialog chrome, ⌘K hotkey, MRU history. Pulled UP from notion-page-clone's command-palette renderless surface (Wave N+3.7) — Nosion adapters dropped at the kitab boundary.",
|
|
1453
|
+
"source": "notion-page-clone (consumerVersion 0.3.0) + earlier superspace facade",
|
|
1004
1454
|
"docsUrl": "https://cmdk.paco.me",
|
|
1005
1455
|
"install": "npm i cmdk",
|
|
1006
1456
|
"npmPackages": [
|
|
1007
1457
|
"cmdk"
|
|
1008
1458
|
],
|
|
1009
1459
|
"exampleCode": "",
|
|
1010
|
-
"agentRecipe": "
|
|
1460
|
+
"agentRecipe": "Wire <CommandPalette groups={...} onHistorySelect={...} labels={...} /> at the dashboard shell. Build groups from your feature registry; each item.onSelect handles navigation. Use <SearchModal bindings={{ pages, databases, recents, isLoading, onQueryChange, onSelectPage, onSelectDatabase }} /> for the search dialog — see slice README.md for adapter shapes.",
|
|
1011
1461
|
"tags": [
|
|
1012
1462
|
"ui",
|
|
1013
1463
|
"palette",
|
|
1014
1464
|
"cmd-k",
|
|
1015
1465
|
"navigation",
|
|
1016
|
-
"keyboard"
|
|
1466
|
+
"keyboard",
|
|
1467
|
+
"search"
|
|
1017
1468
|
]
|
|
1018
1469
|
},
|
|
1019
1470
|
{
|
|
@@ -1208,17 +1659,36 @@
|
|
|
1208
1659
|
"slug": "admin",
|
|
1209
1660
|
"title": "Admin — Generic Shell",
|
|
1210
1661
|
"category": "infra",
|
|
1211
|
-
"description": "
|
|
1662
|
+
"description": "Per-instance admin landing scaffold + portable nav-from-registry factory. Consumer supplies a SliceRegistryAdapter (each slice declares its own admin.activity[]) + queryTable reader; the slice's buildAdminStats(opts) emits the { counts, unreadMessages, activity } shape Convex's admin.stats query returns. Pulled UP from rahmanef.com (Wave N+3.1, commit b542389) — domain literals dropped at the kitab boundary. Gated by requireAdmin on Convex side; superadmin email gate via SUPER_ADMIN_EMAIL env.",
|
|
1212
1663
|
"source": "rahmanef63/resource-site",
|
|
1213
1664
|
"install": "npx rahman-resources add admin",
|
|
1214
1665
|
"npmPackages": [],
|
|
1215
1666
|
"exampleCode": "",
|
|
1216
|
-
"agentRecipe": "Run `rr add admin`. Set SUPER_ADMIN_EMAIL via `npx convex env set` to lock down /admin to one address.",
|
|
1667
|
+
"agentRecipe": "Run `rr add admin`. Wire <AdminPage labels={...} /> at /admin and call buildAdminStats({ sliceRegistry, queryTable }) inside convex/features/admin/queries.ts — sliceRegistry.entries flat-maps each feature's admin.activity[] declarations. Set SUPER_ADMIN_EMAIL via `npx convex env set` to lock down /admin to one address.",
|
|
1217
1668
|
"tags": [
|
|
1218
1669
|
"infra",
|
|
1219
1670
|
"admin",
|
|
1220
1671
|
"shell",
|
|
1221
|
-
"crud"
|
|
1672
|
+
"crud",
|
|
1673
|
+
"nav-from-registry"
|
|
1674
|
+
]
|
|
1675
|
+
},
|
|
1676
|
+
{
|
|
1677
|
+
"slug": "platform-admin",
|
|
1678
|
+
"title": "Platform Admin — Multi-Tenant Control Plane",
|
|
1679
|
+
"category": "infra",
|
|
1680
|
+
"description": "Multi-tenant SaaS control plane. Workspace lifecycle ops (list/delete/cascade), per-tenant tier presets (gates + quota), KPI dashboard grid. Consumer-domain bits injected via adapter props (tenantTablesAdapter / tierPresets / kpiSources). Contract-only scaffold; canonical implementation lands via /rr-send from superspace. See docs/contract-negotiations-2026-05-15.md §4.",
|
|
1681
|
+
"source": "rahmanef63/resource-site",
|
|
1682
|
+
"install": "npx rahman-resources add platform-admin",
|
|
1683
|
+
"npmPackages": [],
|
|
1684
|
+
"exampleCode": "",
|
|
1685
|
+
"agentRecipe": "Contract-only scaffold. Wait for superspace /rr-send platform-admin before adopting. Distinct from per-instance `admin` slug.",
|
|
1686
|
+
"tags": [
|
|
1687
|
+
"infra",
|
|
1688
|
+
"admin",
|
|
1689
|
+
"multi-tenant",
|
|
1690
|
+
"saas",
|
|
1691
|
+
"platform"
|
|
1222
1692
|
]
|
|
1223
1693
|
},
|
|
1224
1694
|
{
|
|
@@ -1242,12 +1712,12 @@
|
|
|
1242
1712
|
"slug": "comments",
|
|
1243
1713
|
"title": "Comments — Threaded",
|
|
1244
1714
|
"category": "content",
|
|
1245
|
-
"description": "
|
|
1715
|
+
"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.",
|
|
1246
1716
|
"source": "rahmanef63/resource-site",
|
|
1247
1717
|
"install": "npx rahman-resources add comments",
|
|
1248
1718
|
"npmPackages": [],
|
|
1249
1719
|
"exampleCode": "",
|
|
1250
|
-
"agentRecipe": "Run `rr add comments`.
|
|
1720
|
+
"agentRecipe": "Run `rr add comments`. Wire Convex bindings ({ list, create, update, resolve, remove }) then use <CommentsThread target={{ kind, id, subId? }} bindings={bindings} forbiddenWords={[...]}>{render-prop}</CommentsThread> OR <CommentsAnchor target=... bindings=... pathMap={(t)=>...}>. v0.2.0 polymorphic — pick `kind` literal per host domain.",
|
|
1251
1721
|
"tags": [
|
|
1252
1722
|
"content",
|
|
1253
1723
|
"social",
|
|
@@ -1260,12 +1730,12 @@
|
|
|
1260
1730
|
"slug": "seo",
|
|
1261
1731
|
"title": "SEO — AI Metadata Generator",
|
|
1262
1732
|
"category": "content",
|
|
1263
|
-
"description": "Service slice for SEO metadata generation — Anthropic-backed action with per-user 24h cost guard. No public route. Backend exposes generate + generateAndApply mutations gated by requireAdmin.",
|
|
1733
|
+
"description": "Service slice for SEO metadata generation — Anthropic-backed action with per-user 24h cost guard + portable persona prop. No public route. Backend exposes generate + generateAndApply mutations gated by requireAdmin; consumers inject brand voice via the personaContext arg (or buildSeoSystemPrompt factory).",
|
|
1264
1734
|
"source": "rahmanef63/resource-site",
|
|
1265
1735
|
"install": "npx rahman-resources add seo",
|
|
1266
1736
|
"npmPackages": [],
|
|
1267
1737
|
"exampleCode": "",
|
|
1268
|
-
"agentRecipe": "Run `rr add seo`. Call seo.generate from server actions or admin mutations. Cost guard rate-limits per-user within 24h via callsInWindow query.",
|
|
1738
|
+
"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.",
|
|
1269
1739
|
"tags": [
|
|
1270
1740
|
"content",
|
|
1271
1741
|
"seo",
|
|
@@ -1273,6 +1743,24 @@
|
|
|
1273
1743
|
"anthropic",
|
|
1274
1744
|
"metadata-generator"
|
|
1275
1745
|
]
|
|
1746
|
+
},
|
|
1747
|
+
{
|
|
1748
|
+
"slug": "document-checklist",
|
|
1749
|
+
"title": "Document Checklist — Job-Search Doc Tracker",
|
|
1750
|
+
"category": "content",
|
|
1751
|
+
"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.",
|
|
1752
|
+
"source": "rahmanef63/CareerPack",
|
|
1753
|
+
"install": "npx rahman-resources add document-checklist",
|
|
1754
|
+
"npmPackages": [],
|
|
1755
|
+
"exampleCode": "",
|
|
1756
|
+
"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.",
|
|
1757
|
+
"tags": [
|
|
1758
|
+
"career",
|
|
1759
|
+
"documents",
|
|
1760
|
+
"checklist",
|
|
1761
|
+
"job-search",
|
|
1762
|
+
"indonesia"
|
|
1763
|
+
]
|
|
1276
1764
|
}
|
|
1277
1765
|
],
|
|
1278
1766
|
"slices": [
|
|
@@ -1571,8 +2059,8 @@
|
|
|
1571
2059
|
"title": "MDX Blog",
|
|
1572
2060
|
"category": "content",
|
|
1573
2061
|
"kind": "ui",
|
|
1574
|
-
"version": "0.
|
|
1575
|
-
"description": "Markdown-with-JSX untuk blog post. File-based
|
|
2062
|
+
"version": "0.2.0",
|
|
2063
|
+
"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.",
|
|
1576
2064
|
"source": "rahmanef63/resource-site",
|
|
1577
2065
|
"slicePath": "frontend/slices/mdx-blog",
|
|
1578
2066
|
"convexPaths": [],
|
|
@@ -1663,13 +2151,13 @@
|
|
|
1663
2151
|
},
|
|
1664
2152
|
{
|
|
1665
2153
|
"slug": "command-menu",
|
|
1666
|
-
"title": "Command Menu
|
|
2154
|
+
"title": "Command Menu",
|
|
1667
2155
|
"category": "ui",
|
|
1668
2156
|
"kind": "ui",
|
|
1669
|
-
"version": "0.
|
|
1670
|
-
"description": "
|
|
1671
|
-
"source": "
|
|
1672
|
-
"slicePath": "
|
|
2157
|
+
"version": "0.2.0",
|
|
2158
|
+
"description": "Renderless ⌘K command palette + generic search modal. Consumer supplies CommandGroup[] + onSelect + label bag; slice owns dialog chrome, ⌘K hotkey, MRU history. Pulled UP from notion-page-clone's command-palette renderless surface (Wave N+3.7) — Nosion adapters dropped at the kitab boundary.",
|
|
2159
|
+
"source": "notion-page-clone (consumerVersion 0.3.0) + earlier superspace facade",
|
|
2160
|
+
"slicePath": "frontend/slices/command-menu",
|
|
1673
2161
|
"convexPaths": [],
|
|
1674
2162
|
"npm": [
|
|
1675
2163
|
"cmdk@^1.0.0"
|
|
@@ -1686,9 +2174,10 @@
|
|
|
1686
2174
|
"palette",
|
|
1687
2175
|
"cmd-k",
|
|
1688
2176
|
"navigation",
|
|
1689
|
-
"keyboard"
|
|
2177
|
+
"keyboard",
|
|
2178
|
+
"search"
|
|
1690
2179
|
],
|
|
1691
|
-
"agentRecipe": "
|
|
2180
|
+
"agentRecipe": "Wire <CommandPalette groups={...} onHistorySelect={...} labels={...} /> at the dashboard shell. Build groups from your feature registry; each item.onSelect handles navigation. Use <SearchModal bindings={{ pages, databases, recents, isLoading, onQueryChange, onSelectPage, onSelectDatabase }} /> for the search dialog — see slice README.md for adapter shapes."
|
|
1692
2181
|
},
|
|
1693
2182
|
{
|
|
1694
2183
|
"slug": "motion-primitives",
|
|
@@ -2013,8 +2502,8 @@
|
|
|
2013
2502
|
"title": "Admin — Generic Shell",
|
|
2014
2503
|
"category": "infra",
|
|
2015
2504
|
"kind": "full",
|
|
2016
|
-
"version": "0.
|
|
2017
|
-
"description": "
|
|
2505
|
+
"version": "0.2.0",
|
|
2506
|
+
"description": "Per-instance admin landing scaffold + portable nav-from-registry factory. Consumer supplies a SliceRegistryAdapter (each slice declares its own admin.activity[]) + queryTable reader; the slice's buildAdminStats(opts) emits the { counts, unreadMessages, activity } shape Convex's admin.stats query returns. Pulled UP from rahmanef.com (Wave N+3.1, commit b542389) — domain literals dropped at the kitab boundary. Gated by requireAdmin on Convex side; superadmin email gate via SUPER_ADMIN_EMAIL env.",
|
|
2018
2507
|
"source": "rahmanef63/resource-site",
|
|
2019
2508
|
"slicePath": "frontend/slices/admin",
|
|
2020
2509
|
"convexPaths": [
|
|
@@ -2044,16 +2533,61 @@
|
|
|
2044
2533
|
"infra",
|
|
2045
2534
|
"admin",
|
|
2046
2535
|
"shell",
|
|
2047
|
-
"crud"
|
|
2536
|
+
"crud",
|
|
2537
|
+
"nav-from-registry"
|
|
2538
|
+
],
|
|
2539
|
+
"agentRecipe": "Run `rr add admin`. Wire <AdminPage labels={...} /> at /admin and call buildAdminStats({ sliceRegistry, queryTable }) inside convex/features/admin/queries.ts — sliceRegistry.entries flat-maps each feature's admin.activity[] declarations. Set SUPER_ADMIN_EMAIL via `npx convex env set` to lock down /admin to one address."
|
|
2540
|
+
},
|
|
2541
|
+
{
|
|
2542
|
+
"slug": "platform-admin",
|
|
2543
|
+
"title": "Platform Admin — Multi-Tenant Control Plane",
|
|
2544
|
+
"category": "infra",
|
|
2545
|
+
"kind": "full",
|
|
2546
|
+
"version": "0.1.0",
|
|
2547
|
+
"description": "Multi-tenant SaaS control plane. Workspace lifecycle ops (list/delete/cascade), per-tenant tier presets (gates + quota), KPI dashboard grid. Consumer-domain bits injected via adapter props (tenantTablesAdapter / tierPresets / kpiSources). Contract-only scaffold; canonical implementation lands via /rr-send from superspace. See docs/contract-negotiations-2026-05-15.md §4.",
|
|
2548
|
+
"source": "rahmanef63/resource-site",
|
|
2549
|
+
"slicePath": "frontend/slices/platform-admin",
|
|
2550
|
+
"convexPaths": [
|
|
2551
|
+
"convex/features/platform-admin"
|
|
2552
|
+
],
|
|
2553
|
+
"npm": [],
|
|
2554
|
+
"shadcn": [],
|
|
2555
|
+
"env": [
|
|
2556
|
+
{
|
|
2557
|
+
"name": "PLATFORM_ADMIN_EMAILS",
|
|
2558
|
+
"scope": "convex",
|
|
2559
|
+
"required": true,
|
|
2560
|
+
"description": "Comma-separated list of platform admin email addresses."
|
|
2561
|
+
}
|
|
2562
|
+
],
|
|
2563
|
+
"peers": [
|
|
2564
|
+
{
|
|
2565
|
+
"slug": "convex-auth",
|
|
2566
|
+
"range": "^0.1",
|
|
2567
|
+
"reason": "Actor identity for audit + tier-set ops."
|
|
2568
|
+
},
|
|
2569
|
+
{
|
|
2570
|
+
"slug": "audit-log",
|
|
2571
|
+
"range": "^0.2",
|
|
2572
|
+
"reason": "padmin_audit table feeds through audit-log TenantAdapter."
|
|
2573
|
+
}
|
|
2574
|
+
],
|
|
2575
|
+
"providers": [],
|
|
2576
|
+
"tags": [
|
|
2577
|
+
"infra",
|
|
2578
|
+
"admin",
|
|
2579
|
+
"multi-tenant",
|
|
2580
|
+
"saas",
|
|
2581
|
+
"platform"
|
|
2048
2582
|
],
|
|
2049
|
-
"agentRecipe": "
|
|
2583
|
+
"agentRecipe": "Contract-only scaffold. Wait for superspace /rr-send platform-admin before adopting. Distinct from per-instance `admin` slug."
|
|
2050
2584
|
},
|
|
2051
2585
|
{
|
|
2052
2586
|
"slug": "audit-log",
|
|
2053
2587
|
"title": "Audit Log — Workspace Events",
|
|
2054
2588
|
"category": "infra",
|
|
2055
2589
|
"kind": "backend",
|
|
2056
|
-
"version": "0.
|
|
2590
|
+
"version": "0.2.0",
|
|
2057
2591
|
"description": "Workspace-scoped audit event recorder. Canonical logAuditEvent helper for mutations + actions; supports entity tracking, before/after diff, IP/user-agent capture.",
|
|
2058
2592
|
"source": "rahmanef63/resource-site",
|
|
2059
2593
|
"slicePath": "frontend/slices/audit-log",
|
|
@@ -2084,8 +2618,8 @@
|
|
|
2084
2618
|
"title": "Comments — Threaded",
|
|
2085
2619
|
"category": "content",
|
|
2086
2620
|
"kind": "full",
|
|
2087
|
-
"version": "0.
|
|
2088
|
-
"description": "
|
|
2621
|
+
"version": "0.2.0",
|
|
2622
|
+
"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.",
|
|
2089
2623
|
"source": "rahmanef63/resource-site",
|
|
2090
2624
|
"slicePath": "frontend/slices/comments",
|
|
2091
2625
|
"convexPaths": [
|
|
@@ -2113,15 +2647,15 @@
|
|
|
2113
2647
|
"threaded",
|
|
2114
2648
|
"annotations"
|
|
2115
2649
|
],
|
|
2116
|
-
"agentRecipe": "Run `rr add comments`.
|
|
2650
|
+
"agentRecipe": "Run `rr add comments`. Wire Convex bindings ({ list, create, update, resolve, remove }) then use <CommentsThread target={{ kind, id, subId? }} bindings={bindings} forbiddenWords={[...]}>{render-prop}</CommentsThread> OR <CommentsAnchor target=... bindings=... pathMap={(t)=>...}>. v0.2.0 polymorphic — pick `kind` literal per host domain."
|
|
2117
2651
|
},
|
|
2118
2652
|
{
|
|
2119
2653
|
"slug": "seo",
|
|
2120
2654
|
"title": "SEO — AI Metadata Generator",
|
|
2121
2655
|
"category": "content",
|
|
2122
2656
|
"kind": "full",
|
|
2123
|
-
"version": "0.
|
|
2124
|
-
"description": "Service slice for SEO metadata generation — Anthropic-backed action with per-user 24h cost guard. No public route. Backend exposes generate + generateAndApply mutations gated by requireAdmin.",
|
|
2657
|
+
"version": "0.2.0",
|
|
2658
|
+
"description": "Service slice for SEO metadata generation — Anthropic-backed action with per-user 24h cost guard + portable persona prop. No public route. Backend exposes generate + generateAndApply mutations gated by requireAdmin; consumers inject brand voice via the personaContext arg (or buildSeoSystemPrompt factory).",
|
|
2125
2659
|
"source": "rahmanef63/resource-site",
|
|
2126
2660
|
"slicePath": "frontend/slices/seo",
|
|
2127
2661
|
"convexPaths": [
|
|
@@ -2151,7 +2685,54 @@
|
|
|
2151
2685
|
"anthropic",
|
|
2152
2686
|
"metadata-generator"
|
|
2153
2687
|
],
|
|
2154
|
-
"agentRecipe": "Run `rr add seo`. Call seo.generate from server actions or admin mutations. Cost guard rate-limits per-user within 24h via callsInWindow query."
|
|
2688
|
+
"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."
|
|
2689
|
+
},
|
|
2690
|
+
{
|
|
2691
|
+
"slug": "document-checklist",
|
|
2692
|
+
"title": "Document Checklist — Job-Search Doc Tracker",
|
|
2693
|
+
"category": "content",
|
|
2694
|
+
"kind": "full",
|
|
2695
|
+
"version": "0.1.0",
|
|
2696
|
+
"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.",
|
|
2697
|
+
"source": "rahmanef63/CareerPack",
|
|
2698
|
+
"slicePath": "frontend/slices/document-checklist",
|
|
2699
|
+
"convexPaths": [
|
|
2700
|
+
"convex/features/document-checklist"
|
|
2701
|
+
],
|
|
2702
|
+
"npm": [
|
|
2703
|
+
"lucide-react"
|
|
2704
|
+
],
|
|
2705
|
+
"shadcn": [
|
|
2706
|
+
"badge",
|
|
2707
|
+
"button",
|
|
2708
|
+
"card",
|
|
2709
|
+
"dialog",
|
|
2710
|
+
"label",
|
|
2711
|
+
"popover",
|
|
2712
|
+
"calendar",
|
|
2713
|
+
"progress",
|
|
2714
|
+
"scroll-area",
|
|
2715
|
+
"skeleton",
|
|
2716
|
+
"tabs",
|
|
2717
|
+
"textarea"
|
|
2718
|
+
],
|
|
2719
|
+
"env": [],
|
|
2720
|
+
"peers": [
|
|
2721
|
+
{
|
|
2722
|
+
"slug": "convex-auth",
|
|
2723
|
+
"range": "^0.1",
|
|
2724
|
+
"reason": "Auth identity for user-scoped checklist state."
|
|
2725
|
+
}
|
|
2726
|
+
],
|
|
2727
|
+
"providers": [],
|
|
2728
|
+
"tags": [
|
|
2729
|
+
"career",
|
|
2730
|
+
"documents",
|
|
2731
|
+
"checklist",
|
|
2732
|
+
"job-search",
|
|
2733
|
+
"indonesia"
|
|
2734
|
+
],
|
|
2735
|
+
"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
2736
|
}
|
|
2156
2737
|
]
|
|
2157
2738
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rahman-resources",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Rahman Resources (rr) — shadcn-style installer for vertical slices. `npx resources add <slug>` copies slice into your project's `slices/<slug>/`. You own the files.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Rahman <casadezian@gmail.com>",
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
"directory": "packages/cli"
|
|
13
13
|
},
|
|
14
14
|
"bin": {
|
|
15
|
-
"rahman-resources": "bin/cli.js"
|
|
15
|
+
"rahman-resources": "bin/cli.js",
|
|
16
|
+
"resources": "bin/cli.js",
|
|
17
|
+
"rr": "bin/cli.js"
|
|
16
18
|
},
|
|
17
19
|
"files": [
|
|
18
20
|
"bin",
|