rahman-resources 0.4.2 → 0.7.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.
@@ -0,0 +1,161 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://resource.rahmanef.com/slice-schema.json",
4
+ "title": "Rahman Resources slice.json",
5
+ "description": "Contract for a tier-3 portable feature slice. See docs/slice-architecture.md.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": [
9
+ "slug",
10
+ "version",
11
+ "category",
12
+ "title",
13
+ "description",
14
+ "namespace",
15
+ "frontend",
16
+ "deps"
17
+ ],
18
+ "properties": {
19
+ "$schema": { "type": "string" },
20
+ "slug": {
21
+ "type": "string",
22
+ "pattern": "^[a-z0-9][a-z0-9-]*[a-z0-9]$",
23
+ "description": "Globally-unique kebab-case id."
24
+ },
25
+ "version": {
26
+ "type": "string",
27
+ "pattern": "^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?$",
28
+ "description": "Slice semver, independent of kitab version."
29
+ },
30
+ "category": {
31
+ "type": "string",
32
+ "enum": [
33
+ "ai",
34
+ "auth",
35
+ "data",
36
+ "payment",
37
+ "email",
38
+ "realtime",
39
+ "storage",
40
+ "search",
41
+ "content",
42
+ "ui",
43
+ "infra"
44
+ ]
45
+ },
46
+ "title": { "type": "string", "minLength": 3 },
47
+ "description": { "type": "string", "minLength": 10 },
48
+ "namespace": {
49
+ "type": "string",
50
+ "pattern": "^@/features/[a-z0-9][a-z0-9-]*$",
51
+ "description": "Import root for slice-internal references; CLI rewrites if user opts a different namespace."
52
+ },
53
+ "convex": {
54
+ "type": "object",
55
+ "additionalProperties": false,
56
+ "required": ["rootPaths"],
57
+ "properties": {
58
+ "tablesExport": {
59
+ "type": "string",
60
+ "pattern": "^[a-zA-Z][a-zA-Z0-9_]*$",
61
+ "description": "Name of the table-fragment export in schema.ts (e.g., midtransTables)."
62
+ },
63
+ "schemaPath": {
64
+ "type": "string",
65
+ "description": "Convex schema file inside this slice's convex tree."
66
+ },
67
+ "rootPaths": {
68
+ "type": "array",
69
+ "minItems": 1,
70
+ "items": { "type": "string" },
71
+ "description": "Convex folders the lift pulls into the consumer's convex/."
72
+ }
73
+ }
74
+ },
75
+ "frontend": {
76
+ "type": "object",
77
+ "additionalProperties": false,
78
+ "required": ["slicePath", "configExport"],
79
+ "properties": {
80
+ "slicePath": {
81
+ "type": "string",
82
+ "pattern": "^frontend/slices/[a-z0-9_/-]+$"
83
+ },
84
+ "configExport": {
85
+ "type": "string",
86
+ "pattern": "^[a-zA-Z][a-zA-Z0-9_]*$",
87
+ "description": "Name of the defineFeature(...) export the registry generators look for."
88
+ }
89
+ }
90
+ },
91
+ "deps": {
92
+ "type": "object",
93
+ "additionalProperties": false,
94
+ "properties": {
95
+ "npm": {
96
+ "type": "array",
97
+ "items": { "type": "string" },
98
+ "description": "Plain npm install lines."
99
+ },
100
+ "shadcn": {
101
+ "type": "array",
102
+ "items": { "type": "string" },
103
+ "description": "shadcn primitives this slice imports."
104
+ },
105
+ "env": {
106
+ "type": "array",
107
+ "items": {
108
+ "type": "object",
109
+ "additionalProperties": false,
110
+ "required": ["name", "scope"],
111
+ "properties": {
112
+ "name": { "type": "string", "pattern": "^[A-Z][A-Z0-9_]*$" },
113
+ "scope": {
114
+ "type": "string",
115
+ "enum": ["convex", "next-public", "server"]
116
+ },
117
+ "required": { "type": "boolean", "default": true },
118
+ "description": { "type": "string" }
119
+ }
120
+ }
121
+ },
122
+ "peers": {
123
+ "type": "array",
124
+ "items": {
125
+ "type": "object",
126
+ "additionalProperties": false,
127
+ "required": ["slug", "range"],
128
+ "properties": {
129
+ "slug": { "type": "string" },
130
+ "range": { "type": "string" },
131
+ "reason": { "type": "string" }
132
+ }
133
+ }
134
+ }
135
+ }
136
+ },
137
+ "registers": {
138
+ "type": "array",
139
+ "items": {
140
+ "type": "string",
141
+ "enum": ["registry", "preview-registry", "export-registry"]
142
+ },
143
+ "description": "Which registry generators auto-discover this slice."
144
+ },
145
+ "audit": {
146
+ "type": "array",
147
+ "items": { "type": "string", "pattern": "^bp:[a-z0-9-]+$" },
148
+ "description": "Audit-bp rule ids that apply to this slice."
149
+ },
150
+ "license": { "type": "string", "default": "MIT" },
151
+ "tags": {
152
+ "type": "array",
153
+ "items": { "type": "string" }
154
+ },
155
+ "providers": {
156
+ "type": "array",
157
+ "items": { "type": "string" },
158
+ "description": "Optional sub-provider list when a slice routes between alternatives (e.g., payment slice with midtrans + doku siblings)."
159
+ }
160
+ }
161
+ }
@@ -7,6 +7,8 @@ dist
7
7
  .env
8
8
  *.tsbuildinfo
9
9
  next-env.d.ts
10
- convex/_generated
10
+ # convex/_generated is COMMITTED in self-hosted setups (Dokploy etc) so the
11
+ # Docker build can typecheck without running codegen inside the container.
12
+ # If you deploy via Convex Cloud, you can re-add the ignore line.
11
13
  .vercel
12
14
  .DS_Store
@@ -13,6 +13,7 @@
13
13
  "convex:codegen": "convex dev --once"
14
14
  },
15
15
  "dependencies": {
16
+ "@auth/core": "^0.37.0",
16
17
  "@convex-dev/auth": "^0.0.84",
17
18
  "@radix-ui/react-label": "^2.1.0",
18
19
  "@radix-ui/react-slot": "^1.1.0",
@@ -1,4 +1,5 @@
1
1
  import type { Metadata } from "next";
2
+ import { Suspense } from "react";
2
3
  import { Inter } from "next/font/google";
3
4
  import { ConvexClientProvider } from "@/components/convex-provider";
4
5
  import { Toaster } from "sonner";
@@ -15,7 +16,9 @@ export default function RootLayout({ children }: { children: React.ReactNode })
15
16
  return (
16
17
  <html lang="en" suppressHydrationWarning>
17
18
  <body className={`${inter.variable} font-sans antialiased`}>
18
- <ConvexClientProvider>{children}</ConvexClientProvider>
19
+ <Suspense fallback={null}>
20
+ <ConvexClientProvider>{children}</ConvexClientProvider>
21
+ </Suspense>
19
22
  <Toaster position="bottom-right" />
20
23
  </body>
21
24
  </html>
@@ -1,13 +1,37 @@
1
1
  "use client";
2
2
 
3
- import { ConvexAuthNextjsProvider } from "@convex-dev/auth/nextjs";
4
- import { ConvexReactClient } from "convex/react";
5
- import type { ReactNode } from "react";
3
+ // SSG-safe Convex auth provider for Next 16 + cacheComponents:true.
4
+ //
5
+ // Why not ConvexAuthNextjsProvider? Postmortem 5.2: it crashes during static
6
+ // prerender (calls useConvexAuth() with undefined context). This client-only
7
+ // mount + Suspense wrap pattern matches what the si-coder skill ships.
8
+ //
9
+ // Auth actions are routed through HTTP (not WebSocket) so signIn / signOut
10
+ // work even when the client hasn't established its WS yet.
6
11
 
7
- const url = process.env.NEXT_PUBLIC_CONVEX_URL;
8
- const convex = url ? new ConvexReactClient(url) : null;
12
+ import { ConvexAuthProvider } from "@convex-dev/auth/react";
13
+ import { ConvexReactClient } from "convex/react";
14
+ import { ConvexHttpClient } from "convex/browser";
15
+ import { useEffect, useState, type ReactNode } from "react";
9
16
 
10
17
  export function ConvexClientProvider({ children }: { children: ReactNode }) {
11
- if (!convex) return <>{children}</>;
12
- return <ConvexAuthNextjsProvider client={convex}>{children}</ConvexAuthNextjsProvider>;
18
+ const [mounted, setMounted] = useState(false);
19
+ const [convex] = useState(() => {
20
+ const url = process.env.NEXT_PUBLIC_CONVEX_URL;
21
+ if (!url) return null;
22
+ const client = new ConvexReactClient(url);
23
+ const http = new ConvexHttpClient(url);
24
+ const orig = client.action.bind(client);
25
+ (client as unknown as { action: typeof client.action }).action = ((ref, args) => {
26
+ const name = (ref as unknown as { _name?: string })?._name ?? String(ref);
27
+ return typeof name === "string" && name.startsWith("auth:")
28
+ ? http.action(ref, args)
29
+ : orig(ref, args);
30
+ }) as typeof client.action;
31
+ return client;
32
+ });
33
+
34
+ useEffect(() => setMounted(true), []);
35
+ if (!mounted || !convex) return <>{children}</>;
36
+ return <ConvexAuthProvider client={convex}>{children}</ConvexAuthProvider>;
13
37
  }
@@ -15,9 +15,12 @@
15
15
  "incremental": true,
16
16
  "plugins": [{ "name": "next" }],
17
17
  "paths": {
18
- "@/*": ["./*"]
18
+ "@/*": ["./*"],
19
+ "@/shared/*": ["./components/shared/*", "./lib/shared/*"],
20
+ "@/features/*": ["./frontend/slices/*"],
21
+ "@convex/*": ["./convex/*"]
19
22
  }
20
23
  },
21
24
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
22
- "exclude": ["node_modules", "convex/_generated"]
25
+ "exclude": ["node_modules", "convex-templates"]
23
26
  }
@@ -0,0 +1,50 @@
1
+ # Workflow — Features (CRUD)
2
+
3
+ Features are backend / integration drop-ins (auth, midtrans, resend, vector-search, ai-router, …).
4
+ Source of truth: `lib/content/features.ts`.
5
+
6
+ ## Create
7
+
8
+ 1. Build the feature surface — backend code in `convex/features/<slug>/`, frontend code in
9
+ `frontend/slices/<slug>/` (vertical-slice convention per CLAUDE.md).
10
+ 2. Per-feature schema: `convex/features/<slug>/schema.ts` exporting `<slug>Tables`. Compose into root.
11
+ 3. Frontend: `frontend/slices/<slug>/{config.ts, init.ts, page.tsx, ...}`. The `config.ts` calls
12
+ `defineFeature({...})` and gets picked up automatically by
13
+ `npx tsx scripts/features/generate-registry.ts`.
14
+ 4. Register entry in `lib/content/features.ts`: slug, title, description, category, tags,
15
+ pullPaths, files, dependencies, agentRecipe.
16
+ 5. Regenerate registries:
17
+ ```bash
18
+ npx tsx scripts/features/generate-registry.ts
19
+ npx tsx scripts/features/generate-preview-registry.ts
20
+ npx tsx scripts/features/generate-export-registry.ts
21
+ cd packages/cli && node scripts/gen-manifest.mjs
22
+ ```
23
+ 6. Verify `npx tsc --noEmit` clean.
24
+ 7. Commit + push.
25
+ 8. Publish CLI minor — feature is now installable via `npx rahman-resources add <slug>`.
26
+
27
+ ## Read
28
+
29
+ - Browse: `https://resource.rahmanef.com/features` then `/features/<slug>`.
30
+ - CLI: `npx rahman-resources list features` / `info <slug>`.
31
+ - MCP tool: `rr_list_features` / `rr_get`.
32
+ - MCP resource: `rr://features/<slug>`.
33
+
34
+ ## Update
35
+
36
+ 1. Edit `lib/content/features.ts` entry.
37
+ 2. Update slice/convex code if shape changed.
38
+ 3. Regenerate registries (same as Create step 5).
39
+ 4. Commit + push.
40
+ 5. Publish CLI patch (content-only) or minor (file-list change).
41
+
42
+ ## Delete
43
+
44
+ 1. Remove entry from `lib/content/features.ts`.
45
+ 2. `git rm -r convex/features/<slug>/` + `frontend/slices/<slug>/`.
46
+ 3. Regenerate registries.
47
+ 4. Search repo for `<slug>` references — most likely no other feature depends on it,
48
+ but check `site/lib/build/compat.ts` for template×feature compat hints.
49
+ 5. Commit + push.
50
+ 6. Publish CLI **major** if widely depended on, else minor.
@@ -0,0 +1,42 @@
1
+ # Workflow — Recipes (CRUD)
2
+
3
+ Recipes are UI patterns to **copy manually** (block-editor, command-palette, asymmetric-masonry, …).
4
+ Lower-friction than features — recipes don't always have backend pieces.
5
+ Source of truth: `lib/content/recipes.ts`.
6
+
7
+ ## Create
8
+
9
+ 1. Build the UI under any of these (pick what fits the recipe shape):
10
+ - `frontend/slices/<slug>/` for full slice patterns
11
+ - `components/<area>/<Component>.tsx` for single-component recipes
12
+ - Existing `cookbook/` or `recipes/` dirs at repo root for ready-to-paste snippets
13
+ 2. Register entry in `lib/content/recipes.ts`: slug, title, description, source, repoPath, tags,
14
+ exampleCode (the snippet user pastes), agentRecipe (instructions for AI to install).
15
+ 3. Regenerate manifest: `cd packages/cli && node scripts/gen-manifest.mjs`.
16
+ 4. Verify build (recipes show on `/recipes` index + `/recipes/<slug>` detail).
17
+ 5. Commit + push.
18
+ 6. Publish CLI patch — recipes don't ship as installable artifacts via `add`; they're
19
+ reference patterns reachable via the docs site + MCP.
20
+
21
+ ## Read
22
+
23
+ - Browse: `https://resource.rahmanef.com/recipes` then `/recipes/<slug>`.
24
+ - CLI: `npx rahman-resources list` (no recipe-only filter; full mixed list) / `info <slug>`.
25
+ - MCP tool: `rr_list_recipes` / `rr_get`.
26
+ - MCP resource: `rr://recipes/<slug>`.
27
+
28
+ ## Update
29
+
30
+ 1. Edit `lib/content/recipes.ts` entry.
31
+ 2. Update the underlying snippet/file if it lives in the repo.
32
+ 3. Regenerate manifest.
33
+ 4. Commit + push.
34
+ 5. Publish CLI patch.
35
+
36
+ ## Delete
37
+
38
+ 1. Remove entry from `lib/content/recipes.ts`.
39
+ 2. Remove the underlying file(s) if exclusive to this recipe.
40
+ 3. Regenerate manifest.
41
+ 4. Commit + push.
42
+ 5. Publish CLI patch (recipes don't have installer call-sites — safe to remove).
@@ -0,0 +1,48 @@
1
+ # Workflow — Claude Skills (CRUD)
2
+
3
+ Claude Skills are reusable agent skills (anthropics + rahman-authored) shipped via the kitab.
4
+ Source of truth: `site/lib/content/claude-skills.ts` — sync feeds `packages/cli/lib/skills.json`.
5
+
6
+ ## Create
7
+
8
+ 1. Author the skill at `~/.agents/skills/<slug>/SKILL.md` (or the project-local skill path).
9
+ Follow the SKILL.md frontmatter contract (name, description, type, tools).
10
+ 2. If it should ship via the kitab, add an entry to `site/lib/content/claude-skills.ts`:
11
+ slug, title, description, scope ("anthropics" | "rahman"), tags, sourceUrl.
12
+ 3. Sync to CLI bundle:
13
+ ```bash
14
+ node packages/cli/scripts/sync-skills.mjs
15
+ ```
16
+ This writes `packages/cli/lib/skills.json` from the TypeScript source. The
17
+ `--check` variant runs in CI to prevent drift.
18
+ 4. Regenerate manifest: `cd packages/cli && node scripts/gen-manifest.mjs`.
19
+ 5. Verify the skill shows in `npx rahman-resources list skills`.
20
+ 6. Commit + push (both `site/lib/content/claude-skills.ts` and `packages/cli/lib/skills.json`).
21
+ 7. Publish CLI minor — consumers can now `npx rahman-resources add-skill <slug>`.
22
+
23
+ ## Read
24
+
25
+ - Browse: `https://resource.rahmanef.com/agents` (and on the site Skills are listed alongside
26
+ templates/features in the Bundle Builder at `/build`).
27
+ - CLI: `npx rahman-resources list skills` / `info <slug>`.
28
+ - MCP tool: `rr_list_skills` / `rr_get`.
29
+ - MCP resource: `rr://skills/<slug>`.
30
+
31
+ ## Update
32
+
33
+ 1. Edit `site/lib/content/claude-skills.ts` entry.
34
+ 2. Edit `~/.agents/skills/<slug>/SKILL.md` if the actual skill changed.
35
+ 3. Run `node packages/cli/scripts/sync-skills.mjs`.
36
+ 4. Regenerate manifest.
37
+ 5. Commit + push.
38
+ 6. Publish CLI patch (description-only) or minor (slug rename / new tools).
39
+
40
+ ## Delete
41
+
42
+ 1. Remove entry from `site/lib/content/claude-skills.ts`.
43
+ 2. Delete the SKILL.md folder if no longer used.
44
+ 3. Re-sync (`sync-skills.mjs`).
45
+ 4. Regenerate manifest.
46
+ 5. Commit + push.
47
+ 6. Publish CLI **major** if widely used (consumers' `add-skill <slug>` will 404),
48
+ else minor.
@@ -0,0 +1,51 @@
1
+ # Workflow — Templates (CRUD)
2
+
3
+ Templates are full-app website templates registered with `category: "website-template"`.
4
+ Source of truth: `lib/content/layouts.ts` in the kitab repo.
5
+
6
+ ## Create
7
+
8
+ 1. Build the UI scaffold under `app/preview/<slug>/{public,admin}/` following the
9
+ `personal-brand-os` gold reference (read `template-base/CONSUMER-SETUP.md` first).
10
+ 2. Build per-template shared at
11
+ `components/templates/<base>/shared/{site-config.ts, types.ts, seed.ts, nav-config.ts, store.tsx}`.
12
+ 3. Build slice components at `components/templates/<base>/slices/<route>/<RouteName>Page.tsx` for public
13
+ and `components/templates/<base>/slices/admin/<route>/<RouteName>View.tsx` for admin.
14
+ 4. Reuse chrome from `components/templates/_shared/ui/*` — never create new chrome.
15
+ 5. Reuse shadcn primitives from `@/components/ui/*` + lucide-react. No new UI lib deps.
16
+ 6. Register an entry in `lib/content/layouts.ts` with: slug, title, category="website-template",
17
+ description, source, repoPath, primaryFile, tags, previewPath, adminPreviewPath, defaultSurface,
18
+ pullPaths, files (full list), dependencies, exampleCode, agentRecipe.
19
+ 7. Regenerate manifest: `cd packages/cli && node scripts/gen-manifest.mjs`.
20
+ 8. Verify: `npx tsc --noEmit` (root + template-base both 0) and `npm run build` (route appears
21
+ in the prerendered list).
22
+ 9. Commit + push.
23
+ 10. Publish CLI minor (`packages/cli/package.json` version bump → `npm publish`) so the new
24
+ template lands in the npm tarball consumers fetch via `npx rahman-resources init`.
25
+
26
+ ## Read
27
+
28
+ - Browse: `https://resource.rahmanef.com/templates` (gallery) or `/layouts/<slug>` (detail).
29
+ - CLI: `npx rahman-resources list templates` then `npx rahman-resources info <slug>`.
30
+ - MCP tool: `rr_list_templates` / `rr_get`.
31
+ - MCP resource: `rr://templates/<slug>`.
32
+ - Knowledge base for AI agents: `https://resource.rahmanef.com/llms.txt`.
33
+
34
+ ## Update
35
+
36
+ 1. Edit the entry in `lib/content/layouts.ts` (description, files, agentRecipe — anything).
37
+ 2. Update the underlying component files if shape changed.
38
+ 3. Regenerate manifest (same step as Create).
39
+ 4. Verify build green.
40
+ 5. Commit + push.
41
+ 6. Publish CLI patch (content-only) or minor (new field/file in the entry).
42
+
43
+ ## Delete
44
+
45
+ 1. Remove the entry from `lib/content/layouts.ts`.
46
+ 2. `git rm -r app/preview/<slug>/` and `components/templates/<base>/`.
47
+ 3. Regenerate manifest.
48
+ 4. Audit: `grep -r "<slug>"` repo-wide — purge stale references.
49
+ 5. Commit + push.
50
+ 6. Publish CLI **major** if the template was widely used (consumers' `init` calls referencing
51
+ the slug will fail), else minor.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rahman-resources",
3
- "version": "0.4.2",
4
- "description": "Scaffolder + installer for Rahman Resources kitab — npx rahman-resources init <app>; add <template>; list; info",
3
+ "version": "0.7.0",
4
+ "description": "Scaffolder + installer for Rahman Resources kitab — npx rahman-resources init/add/lift/scaffold-slice/publish-slice. Tier-3 portable feature slices + manifest + skills + CRUD workflows.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": "Rahman <casadezian@gmail.com>",
@@ -25,14 +25,18 @@
25
25
  "scripts": {
26
26
  "gen": "node scripts/gen-manifest.mjs",
27
27
  "validate": "node scripts/validate.mjs",
28
+ "validate:slices": "node scripts/validate-slice.mjs",
28
29
  "sync:skills": "node scripts/sync-skills.mjs",
29
30
  "sync:skills:check": "node scripts/sync-skills.mjs --check",
30
- "prepublishOnly": "node scripts/sync-skills.mjs --check && node scripts/validate.mjs"
31
+ "prepublishOnly": "node scripts/sync-skills.mjs --check && node scripts/validate.mjs && node scripts/validate-slice.mjs --check"
31
32
  },
32
33
  "dependencies": {
33
34
  "kleur": "^4.1.5",
34
35
  "tiged": "^2.12.7"
35
36
  },
37
+ "overrides": {
38
+ "tar": "^7.5.0"
39
+ },
36
40
  "keywords": [
37
41
  "rahman",
38
42
  "kitab",