@react-vault/create-app 0.1.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.
Files changed (117) hide show
  1. package/LICENSE +12 -0
  2. package/README.md +16 -0
  3. package/bin/create-app.js +8 -0
  4. package/claude-toolkit/README.md +131 -0
  5. package/claude-toolkit/agents/bfsi-accessibility-auditor.md +132 -0
  6. package/claude-toolkit/agents/bfsi-architect.md +156 -0
  7. package/claude-toolkit/agents/bfsi-code-reviewer.md +137 -0
  8. package/claude-toolkit/agents/bfsi-compliance-auditor.md +161 -0
  9. package/claude-toolkit/agents/bfsi-pii-scanner.md +142 -0
  10. package/claude-toolkit/agents/bfsi-pr-reviewer.md +114 -0
  11. package/claude-toolkit/agents/bfsi-security-reviewer.md +136 -0
  12. package/claude-toolkit/commands/bfsi-audit.md +46 -0
  13. package/claude-toolkit/commands/bfsi-doctor.md +97 -0
  14. package/claude-toolkit/commands/bfsi-review.md +46 -0
  15. package/claude-toolkit/commands/bfsi-scaffold.md +47 -0
  16. package/claude-toolkit/hooks/hooks.json +181 -0
  17. package/claude-toolkit/hooks/scripts/a11y-check.sh +63 -0
  18. package/claude-toolkit/hooks/scripts/audit-prompt.sh +36 -0
  19. package/claude-toolkit/hooks/scripts/block-destructive.sh +41 -0
  20. package/claude-toolkit/hooks/scripts/block-force-push.sh +30 -0
  21. package/claude-toolkit/hooks/scripts/format.sh +42 -0
  22. package/claude-toolkit/hooks/scripts/inject-context.sh +44 -0
  23. package/claude-toolkit/hooks/scripts/lint.sh +45 -0
  24. package/claude-toolkit/hooks/scripts/protect-files.sh +53 -0
  25. package/claude-toolkit/hooks/scripts/save-compliance-context.sh +35 -0
  26. package/claude-toolkit/hooks/scripts/scan-pii.sh +87 -0
  27. package/claude-toolkit/hooks/scripts/scan-secrets.sh +67 -0
  28. package/claude-toolkit/hooks/scripts/verify-clean.sh +50 -0
  29. package/claude-toolkit/package.json +22 -0
  30. package/claude-toolkit/plugin.json +31 -0
  31. package/claude-toolkit/skills/bfsi-api-endpoint/SKILL.md +105 -0
  32. package/claude-toolkit/skills/bfsi-commit/SKILL.md +102 -0
  33. package/claude-toolkit/skills/bfsi-compliance-check/SKILL.md +107 -0
  34. package/claude-toolkit/skills/bfsi-encrypt-helper/SKILL.md +127 -0
  35. package/claude-toolkit/skills/bfsi-error-message/SKILL.md +162 -0
  36. package/claude-toolkit/skills/bfsi-feature/SKILL.md +120 -0
  37. package/claude-toolkit/skills/bfsi-feature/references/architecture.md +69 -0
  38. package/claude-toolkit/skills/bfsi-feature/references/audit-events.md +70 -0
  39. package/claude-toolkit/skills/bfsi-feature/scripts/scaffold.mjs +136 -0
  40. package/claude-toolkit/skills/bfsi-form/SKILL.md +73 -0
  41. package/claude-toolkit/skills/bfsi-form/references/validation-regex.md +50 -0
  42. package/claude-toolkit/skills/bfsi-onboarding/SKILL.md +110 -0
  43. package/claude-toolkit/skills/bfsi-pii-field/SKILL.md +90 -0
  44. package/claude-toolkit/skills/bfsi-test-pattern/SKILL.md +179 -0
  45. package/dist/index.d.ts +2 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +339 -0
  48. package/dist/index.js.map +1 -0
  49. package/package.json +69 -0
  50. package/templates/_shared/.claude/settings.json +31 -0
  51. package/templates/_shared/.env.local.sample +25 -0
  52. package/templates/_shared/.github/workflows/ci.yml +49 -0
  53. package/templates/_shared/CLAUDE.md +89 -0
  54. package/templates/_shared/README.md +50 -0
  55. package/templates/_shared/index.html +16 -0
  56. package/templates/_shared/package.json +73 -0
  57. package/templates/_shared/postcss.config.cjs +6 -0
  58. package/templates/_shared/src/app/App.tsx +13 -0
  59. package/templates/_shared/src/app/globals.css +64 -0
  60. package/templates/_shared/src/env.ts +33 -0
  61. package/templates/_shared/src/i18n/i18n.ts +18 -0
  62. package/templates/_shared/src/i18n/translations/en.json +54 -0
  63. package/templates/_shared/src/i18n/translations/hi.json +30 -0
  64. package/templates/_shared/src/main.tsx +16 -0
  65. package/templates/_shared/src/routes/ProtectedRoute.tsx +28 -0
  66. package/templates/_shared/src/routes/index.tsx +67 -0
  67. package/templates/_shared/src/shared/ErrorBoundary.tsx +60 -0
  68. package/templates/_shared/tailwind.config.ts +68 -0
  69. package/templates/_shared/tests/setup.ts +7 -0
  70. package/templates/_shared/tsconfig.json +33 -0
  71. package/templates/_shared/tsconfig.node.json +13 -0
  72. package/templates/_shared/vite.config.ts +47 -0
  73. package/templates/rtk-query/.claude/skills/axios-auth/SKILL.md +103 -0
  74. package/templates/rtk-query/.claude/skills/axios-auth/references/error-shape.md +84 -0
  75. package/templates/rtk-query/.claude/skills/axios-auth/references/full-code-walkthrough.md +146 -0
  76. package/templates/rtk-query/.claude/skills/axios-auth/references/notification-wiring.md +141 -0
  77. package/templates/rtk-query/.claude/skills/constants-organization/SKILL.md +112 -0
  78. package/templates/rtk-query/.claude/skills/constants-organization/references/example-files.md +134 -0
  79. package/templates/rtk-query/.claude/skills/constants-organization/references/tag-types-catalog.md +53 -0
  80. package/templates/rtk-query/.claude/skills/redux-store-integration/SKILL.md +159 -0
  81. package/templates/rtk-query/.claude/skills/redux-store-integration/references/localStorage-persistence.md +70 -0
  82. package/templates/rtk-query/.claude/skills/redux-store-integration/references/middleware-patterns.md +82 -0
  83. package/templates/rtk-query/.claude/skills/rtk-query-api/SKILL.md +148 -0
  84. package/templates/rtk-query/.claude/skills/rtk-query-api/references/cache-strategies.md +96 -0
  85. package/templates/rtk-query/.claude/skills/rtk-query-api/references/endpoint-cookbook.md +145 -0
  86. package/templates/rtk-query/.claude/skills/rtk-query-api/references/optimistic-update.md +53 -0
  87. package/templates/rtk-query/README.md +84 -0
  88. package/templates/rtk-query/package.partial.json +7 -0
  89. package/templates/rtk-query/src/app/App.tsx +23 -0
  90. package/templates/rtk-query/src/axiosconfig/axiosInstance.ts +26 -0
  91. package/templates/rtk-query/src/axiosconfig/baseQuery.ts +72 -0
  92. package/templates/rtk-query/src/axiosconfig/interceptor.ts +42 -0
  93. package/templates/rtk-query/src/redux/invalidateCacheMiddleware.ts +20 -0
  94. package/templates/rtk-query/src/redux/reduxHooks.ts +10 -0
  95. package/templates/rtk-query/src/redux/rootReducer.ts +18 -0
  96. package/templates/rtk-query/src/redux/store.ts +36 -0
  97. package/templates/tanstack-query/.claude/skills/axios-auth/SKILL.md +109 -0
  98. package/templates/tanstack-query/.claude/skills/axios-auth/references/error-shape.md +89 -0
  99. package/templates/tanstack-query/.claude/skills/axios-auth/references/full-code-walkthrough.md +121 -0
  100. package/templates/tanstack-query/.claude/skills/axios-auth/references/notification-pattern.md +109 -0
  101. package/templates/tanstack-query/.claude/skills/constants-organization/SKILL.md +144 -0
  102. package/templates/tanstack-query/.claude/skills/constants-organization/references/example-files.md +111 -0
  103. package/templates/tanstack-query/.claude/skills/constants-organization/references/query-key-factories.md +129 -0
  104. package/templates/tanstack-query/.claude/skills/query-client-setup/SKILL.md +165 -0
  105. package/templates/tanstack-query/.claude/skills/query-client-setup/references/devtools.md +67 -0
  106. package/templates/tanstack-query/.claude/skills/query-client-setup/references/global-handlers.md +94 -0
  107. package/templates/tanstack-query/.claude/skills/tanstack-services/SKILL.md +142 -0
  108. package/templates/tanstack-query/.claude/skills/tanstack-services/references/audited-mutation.md +144 -0
  109. package/templates/tanstack-query/.claude/skills/tanstack-services/references/optimistic-update.md +102 -0
  110. package/templates/tanstack-query/.claude/skills/tanstack-services/references/service-cookbook.md +151 -0
  111. package/templates/tanstack-query/README.md +63 -0
  112. package/templates/tanstack-query/package.partial.json +8 -0
  113. package/templates/tanstack-query/src/api/axiosInstance.ts +20 -0
  114. package/templates/tanstack-query/src/api/http.ts +62 -0
  115. package/templates/tanstack-query/src/api/queryClient.ts +28 -0
  116. package/templates/tanstack-query/src/app/App.tsx +20 -0
  117. package/templates/tanstack-query/src/services/example.ts +32 -0
package/dist/index.js ADDED
@@ -0,0 +1,339 @@
1
+ /**
2
+ * `create-app` entry point.
3
+ *
4
+ * Scaffolds a new BFSI React project from `templates/_shared/` + a variant overlay
5
+ * (RTK Query or TanStack Query), inlines the Claude toolkit into the project's
6
+ * `.claude/` directory, and optionally rewrites `@react-vault/*` deps to local `link:`
7
+ * paths so the project installs without the packages being published yet.
8
+ */
9
+ import { intro, outro, text, select, confirm, isCancel, cancel, spinner, note, } from '@clack/prompts';
10
+ import pc from 'picocolors';
11
+ import fs from 'fs-extra';
12
+ import path from 'node:path';
13
+ import { fileURLToPath } from 'node:url';
14
+ import { execa } from 'execa';
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ const __dirname = path.dirname(__filename);
17
+ // The CLI runs in two modes:
18
+ // - Dev: inside the monorepo at <starter>/packages/cli/dist/index.js.
19
+ // Templates are at <starter>/templates/ and the toolkit lives at
20
+ // <starter>/packages/claude-toolkit/.
21
+ // - Published: installed at <somewhere>/node_modules/@react-vault/create-app/.
22
+ // The prepublishOnly script bundles templates/ and claude-toolkit/ INTO
23
+ // the package itself, so they sit alongside dist/.
24
+ const PACKAGE_ROOT = path.resolve(__dirname, '..');
25
+ const BUNDLED_TEMPLATES = path.join(PACKAGE_ROOT, 'templates');
26
+ const IS_PUBLISHED_MODE = fs.existsSync(BUNDLED_TEMPLATES);
27
+ const TEMPLATES_ROOT = IS_PUBLISHED_MODE
28
+ ? BUNDLED_TEMPLATES
29
+ : path.resolve(PACKAGE_ROOT, '..', '..', 'templates');
30
+ const TOOLKIT_ROOT = IS_PUBLISHED_MODE
31
+ ? path.join(PACKAGE_ROOT, 'claude-toolkit')
32
+ : path.resolve(PACKAGE_ROOT, '..', 'claude-toolkit');
33
+ // The npm scope used in templates' package.json references. The CLI's `link:`
34
+ // rewrite swaps these to absolute paths for local-dev mode.
35
+ const PACKAGE_SCOPE = '@react-vault';
36
+ export async function main() {
37
+ console.log();
38
+ intro(pc.bold(pc.bgCyan(pc.black(' @react-vault/create-app '))));
39
+ const projectName = await text({
40
+ message: 'Project name?',
41
+ placeholder: 'my-bank-app',
42
+ validate(value) {
43
+ if (!value) {
44
+ return 'Project name is required';
45
+ }
46
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(value)) {
47
+ return 'Lowercase letters, digits, and hyphens only';
48
+ }
49
+ const target = path.resolve(process.cwd(), value);
50
+ if (fs.existsSync(target)) {
51
+ return `Directory ${value} already exists`;
52
+ }
53
+ return undefined;
54
+ },
55
+ });
56
+ if (isCancel(projectName)) {
57
+ return cancelled();
58
+ }
59
+ const variant = (await select({
60
+ message: 'State management?',
61
+ options: [
62
+ {
63
+ value: 'rtk',
64
+ label: 'RTK Query (Redux Toolkit)',
65
+ hint: 'Recommended for complex client state',
66
+ },
67
+ {
68
+ value: 'tanstack',
69
+ label: 'TanStack Query + Zustand',
70
+ hint: 'Lighter; great for server-state-heavy apps',
71
+ },
72
+ ],
73
+ }));
74
+ if (isCancel(variant)) {
75
+ return cancelled();
76
+ }
77
+ const inlineToolkit = (await confirm({
78
+ message: 'Inline the Claude toolkit (skills/agents/hooks/commands) into .claude/?',
79
+ initialValue: true,
80
+ }));
81
+ if (isCancel(inlineToolkit)) {
82
+ return cancelled();
83
+ }
84
+ // In published mode (npx-installed CLI), `link:` paths to a local workspace
85
+ // don't exist on the user's machine — skip the prompt. In dev mode (running
86
+ // from the monorepo), offer to point at the local workspace.
87
+ let localLink = false;
88
+ if (!IS_PUBLISHED_MODE) {
89
+ const answer = (await confirm({
90
+ message: 'Use link: refs for @react-vault/core and @react-vault/ui? (points the project at this local workspace instead of fetching from npm)',
91
+ initialValue: true,
92
+ }));
93
+ if (isCancel(answer)) {
94
+ return cancelled();
95
+ }
96
+ localLink = answer;
97
+ }
98
+ const installDeps = (await confirm({
99
+ message: 'Install dependencies after scaffolding (pnpm install)?',
100
+ initialValue: true,
101
+ }));
102
+ if (isCancel(installDeps)) {
103
+ return cancelled();
104
+ }
105
+ const initGit = (await confirm({
106
+ message: 'Initialise git repository?',
107
+ initialValue: true,
108
+ }));
109
+ if (isCancel(initGit)) {
110
+ return cancelled();
111
+ }
112
+ const opts = {
113
+ projectName: projectName,
114
+ variant,
115
+ inlineToolkit,
116
+ localLink,
117
+ installDeps,
118
+ initGit,
119
+ };
120
+ await scaffold(opts);
121
+ const lines = [
122
+ `${pc.bold('cd ' + opts.projectName)}`,
123
+ '',
124
+ ` ${pc.cyan('pnpm dev')} — start dev server`,
125
+ ` ${pc.cyan('claude')} — Claude Code (BFSI toolkit auto-available)`,
126
+ ` ${pc.cyan('/bfsi-doctor')} — verify wiring inside Claude`,
127
+ ` ${pc.cyan('/bfsi-onboarding')} — orient yourself to the project`,
128
+ ];
129
+ note(lines.join('\n'), 'Next steps');
130
+ outro(pc.green('Done.'));
131
+ }
132
+ async function scaffold(opts) {
133
+ const s = spinner();
134
+ const target = path.resolve(process.cwd(), opts.projectName);
135
+ const sharedDir = path.join(TEMPLATES_ROOT, '_shared');
136
+ const variantDir = path.join(TEMPLATES_ROOT, opts.variant === 'rtk' ? 'rtk-query' : 'tanstack-query');
137
+ // 1. Copy shared template
138
+ s.start('Copying template files');
139
+ await fs.copy(sharedDir, target, {
140
+ filter: (src) => !/(\bnode_modules\b|\.turbo\b|\bdist\b)/.test(src),
141
+ });
142
+ // 2. Apply variant overlay
143
+ if (await fs.pathExists(variantDir)) {
144
+ await fs.copy(variantDir, target, { overwrite: true });
145
+ }
146
+ s.stop('Template files copied');
147
+ // 3. Merge package.partial.json from variant into package.json, then delete it
148
+ await mergeVariantPackage(target);
149
+ // 4. Substitute {{projectName}} in package.json, README.md, index.html, i18n
150
+ await substituteVars(target, opts.projectName);
151
+ // 5. In dev mode, optionally swap @react-vault/{core,ui} dep versions to
152
+ // `link:` paths pointing at the workspace. No-op in published mode.
153
+ await maybeRewriteToLinkDeps(target, opts.localLink);
154
+ // 6. Inline the toolkit (skills, agents, commands, hooks) into .claude/.
155
+ // Variant-specific RTK skills are shipped in templates/rtk-query/.claude/
156
+ // so they're already in place from step 2 — nothing extra to copy here.
157
+ if (opts.inlineToolkit) {
158
+ s.start('Inlining Claude toolkit into .claude/');
159
+ await inlineToolkitInto(target);
160
+ s.stop('Claude toolkit inlined into .claude/');
161
+ }
162
+ // 7. pnpm install
163
+ if (opts.installDeps) {
164
+ s.start('Installing dependencies (pnpm install)');
165
+ try {
166
+ await execa('pnpm', ['install'], { cwd: target, stdio: 'pipe' });
167
+ s.stop('Dependencies installed');
168
+ }
169
+ catch (err) {
170
+ s.stop(pc.yellow('pnpm install failed — see error above. Re-run manually with: pnpm install'));
171
+ console.warn(pc.dim(err.message));
172
+ }
173
+ }
174
+ // 8. git init + rename to main + first commit
175
+ if (opts.initGit) {
176
+ s.start('Initialising git');
177
+ try {
178
+ await execa('git', ['init', '-q'], { cwd: target });
179
+ await execa('git', ['branch', '-m', 'main'], { cwd: target }).catch(() => {
180
+ // Older git versions: master is created by init; rename may fail if no commits yet
181
+ });
182
+ await execa('git', ['add', '.'], { cwd: target });
183
+ await execa('git', ['commit', '-q', '-m', `chore: scaffold ${opts.projectName} from create-app`], {
184
+ cwd: target,
185
+ });
186
+ // Ensure final branch is main even if rename pre-commit failed
187
+ await execa('git', ['branch', '-M', 'main'], { cwd: target }).catch(() => {
188
+ /* ignore */
189
+ });
190
+ s.stop('Git repo initialised (branch: main)');
191
+ }
192
+ catch (err) {
193
+ s.stop(pc.yellow('git init failed (continuing anyway)'));
194
+ console.warn(pc.dim(err.message));
195
+ }
196
+ }
197
+ }
198
+ async function mergeVariantPackage(target) {
199
+ const partialPath = path.join(target, 'package.partial.json');
200
+ const pkgPath = path.join(target, 'package.json');
201
+ if (!(await fs.pathExists(partialPath)) || !(await fs.pathExists(pkgPath))) {
202
+ return;
203
+ }
204
+ const partial = (await fs.readJSON(partialPath));
205
+ const pkg = (await fs.readJSON(pkgPath));
206
+ if (partial.dependencies) {
207
+ pkg.dependencies = { ...(pkg.dependencies ?? {}), ...partial.dependencies };
208
+ }
209
+ if (partial.devDependencies) {
210
+ pkg.devDependencies = { ...(pkg.devDependencies ?? {}), ...partial.devDependencies };
211
+ }
212
+ await fs.writeJSON(pkgPath, pkg, { spaces: 2 });
213
+ await fs.remove(partialPath);
214
+ }
215
+ async function substituteVars(target, projectName) {
216
+ const filesToTouch = [
217
+ path.join(target, 'package.json'),
218
+ path.join(target, 'README.md'),
219
+ path.join(target, 'CLAUDE.md'),
220
+ path.join(target, 'index.html'),
221
+ path.join(target, 'src', 'i18n', 'translations', 'en.json'),
222
+ path.join(target, 'src', 'i18n', 'translations', 'hi.json'),
223
+ ];
224
+ for (const f of filesToTouch) {
225
+ if (!(await fs.pathExists(f))) {
226
+ continue;
227
+ }
228
+ const content = await fs.readFile(f, 'utf8');
229
+ const replaced = content.replaceAll('{{projectName}}', projectName);
230
+ if (replaced !== content) {
231
+ await fs.writeFile(f, replaced, 'utf8');
232
+ }
233
+ }
234
+ }
235
+ /**
236
+ * In local-dev (running from the monorepo) the user can opt-in to rewriting
237
+ * @react-vault/core and @react-vault/ui dependency versions to `link:` paths
238
+ * that point at the workspace packages. Lets you `pnpm install` before the
239
+ * packages are published to npm.
240
+ *
241
+ * In published mode (npx-installed CLI), `link:` paths would dangle, so this
242
+ * step is a no-op — the templates' versions stay as published npm versions.
243
+ */
244
+ async function maybeRewriteToLinkDeps(target, localLink) {
245
+ if (!localLink || IS_PUBLISHED_MODE) {
246
+ return;
247
+ }
248
+ const pkgPath = path.join(target, 'package.json');
249
+ if (!(await fs.pathExists(pkgPath))) {
250
+ return;
251
+ }
252
+ const pkg = (await fs.readJSON(pkgPath));
253
+ // Resolve workspace paths relative to the monorepo root (only valid in dev mode)
254
+ const starterRoot = path.resolve(PACKAGE_ROOT, '..', '..');
255
+ const linkTargets = {
256
+ [`${PACKAGE_SCOPE}/core`]: `link:${path.join(starterRoot, 'packages', 'core')}`,
257
+ [`${PACKAGE_SCOPE}/ui`]: `link:${path.join(starterRoot, 'packages', 'ui')}`,
258
+ };
259
+ for (const key of ['dependencies', 'devDependencies']) {
260
+ const block = pkg[key];
261
+ if (!block) {
262
+ continue;
263
+ }
264
+ for (const depName of Object.keys(block)) {
265
+ const target = linkTargets[depName];
266
+ if (target) {
267
+ block[depName] = target;
268
+ }
269
+ }
270
+ }
271
+ await fs.writeJSON(pkgPath, pkg, { spaces: 2 });
272
+ }
273
+ /**
274
+ * Inline the Claude toolkit into <project>/.claude/.
275
+ *
276
+ * - Copies the toolkit's skills/, agents/, commands/ into the project (these
277
+ * are the shared bfsi-* skills that ship in every project)
278
+ * - Copies hooks/scripts/ and rewrites paths in hooks.json from `${CLAUDE_PLUGIN_ROOT}/...`
279
+ * to `${CLAUDE_PROJECT_DIR}/.claude/...` since we're now project-local, not a plugin
280
+ * - Merges hooks into existing `.claude/settings.json` (which already has permissions)
281
+ * - Removes `enabledPlugins` from settings since the plugin is now inlined
282
+ *
283
+ * Variant-specific skills (e.g. RTK pattern skills under templates/rtk-query/
284
+ * .claude/skills/) are NOT handled here — they ship inside their variant
285
+ * overlay and land in the project as part of the standard overlay copy.
286
+ */
287
+ async function inlineToolkitInto(target) {
288
+ const claudeDir = path.join(target, '.claude');
289
+ await fs.ensureDir(claudeDir);
290
+ // Copy the toolkit's skills, agents, commands. Existing files at the same
291
+ // path (e.g. variant-shipped RTK skills already placed by the overlay) are
292
+ // preserved because we don't write over names we don't have.
293
+ for (const sub of ['skills', 'agents', 'commands']) {
294
+ const src = path.join(TOOLKIT_ROOT, sub);
295
+ const dst = path.join(claudeDir, sub);
296
+ if (await fs.pathExists(src)) {
297
+ await fs.copy(src, dst, { overwrite: true });
298
+ }
299
+ }
300
+ // Copy hook scripts + chmod +x
301
+ const scriptsSrc = path.join(TOOLKIT_ROOT, 'hooks', 'scripts');
302
+ const scriptsDst = path.join(claudeDir, 'hooks', 'scripts');
303
+ if (await fs.pathExists(scriptsSrc)) {
304
+ await fs.copy(scriptsSrc, scriptsDst, { overwrite: true });
305
+ const entries = await fs.readdir(scriptsDst);
306
+ for (const e of entries) {
307
+ const p = path.join(scriptsDst, e);
308
+ if ((await fs.stat(p)).isFile()) {
309
+ await fs.chmod(p, 0o755);
310
+ }
311
+ }
312
+ }
313
+ // Read toolkit hooks.json, rewrite ${CLAUDE_PLUGIN_ROOT} → ${CLAUDE_PROJECT_DIR}/.claude
314
+ const toolkitHooksPath = path.join(TOOLKIT_ROOT, 'hooks', 'hooks.json');
315
+ let toolkitHooks = {};
316
+ if (await fs.pathExists(toolkitHooksPath)) {
317
+ const raw = await fs.readFile(toolkitHooksPath, 'utf8');
318
+ const rewritten = raw.replaceAll('${CLAUDE_PLUGIN_ROOT}', '${CLAUDE_PROJECT_DIR}/.claude');
319
+ toolkitHooks = JSON.parse(rewritten);
320
+ }
321
+ // Merge into existing settings.json
322
+ const settingsPath = path.join(claudeDir, 'settings.json');
323
+ const existing = (await fs.pathExists(settingsPath))
324
+ ? (await fs.readJSON(settingsPath))
325
+ : {};
326
+ // Remove plugin reference — the toolkit is now project-local
327
+ delete existing.enabledPlugins;
328
+ // Set hooks from the rewritten toolkit
329
+ const hookSection = toolkitHooks.hooks;
330
+ if (hookSection !== undefined) {
331
+ existing.hooks = hookSection;
332
+ }
333
+ await fs.writeJSON(settingsPath, existing, { spaces: 2 });
334
+ }
335
+ function cancelled() {
336
+ cancel('Cancelled. No files written.');
337
+ process.exit(0);
338
+ }
339
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@react-vault/create-app",
3
+ "version": "0.1.0",
4
+ "description": "Scaffold a new BFSI React project with security, audit, encryption, Tailwind, shadcn/ui, and a Claude Code companion baked in. Pick RTK Query or TanStack Query at scaffold time.",
5
+ "license": "UNLICENSED",
6
+ "type": "module",
7
+ "bin": {
8
+ "create-app": "./bin/create-app.js"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "files": [
12
+ "bin",
13
+ "dist",
14
+ "templates",
15
+ "claude-toolkit",
16
+ "README.md"
17
+ ],
18
+ "dependencies": {
19
+ "@clack/prompts": "0.7.0",
20
+ "picocolors": "1.0.0",
21
+ "fs-extra": "11.2.0",
22
+ "execa": "9.0.2"
23
+ },
24
+ "devDependencies": {
25
+ "@types/node": "20.11.30",
26
+ "@types/fs-extra": "11.0.4",
27
+ "typescript": "5.4.5",
28
+ "vitest": "1.6.0"
29
+ },
30
+ "engines": {
31
+ "node": ">=20.11.0"
32
+ },
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/amar-josh/react-vault.git",
36
+ "directory": "packages/cli"
37
+ },
38
+ "homepage": "https://github.com/amar-josh/react-vault#readme",
39
+ "bugs": {
40
+ "url": "https://github.com/amar-josh/react-vault/issues"
41
+ },
42
+ "keywords": [
43
+ "create-app",
44
+ "react",
45
+ "vite",
46
+ "bfsi",
47
+ "fintech",
48
+ "tailwind",
49
+ "shadcn",
50
+ "rtk-query",
51
+ "tanstack-query",
52
+ "claude-code",
53
+ "scaffolder",
54
+ "starter"
55
+ ],
56
+ "publishConfig": {
57
+ "access": "public"
58
+ },
59
+ "scripts": {
60
+ "build": "tsc -p tsconfig.json",
61
+ "dev": "tsc -p tsconfig.json --watch",
62
+ "lint": "eslint src --ext .ts",
63
+ "lint:fix": "eslint src --ext .ts --fix",
64
+ "test": "vitest run",
65
+ "typecheck": "tsc -p tsconfig.json --noEmit",
66
+ "clean": "rm -rf dist .tsbuildinfo templates claude-toolkit",
67
+ "bundle": "node ./scripts/bundle-for-publish.mjs"
68
+ }
69
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/claude-code-settings.json",
3
+ "enabledPlugins": [
4
+ "toolkit@react-vault"
5
+ ],
6
+ "permissions": {
7
+ "deny": [
8
+ "Bash(rm -rf /*)",
9
+ "Bash(git push --force *main*)",
10
+ "Bash(git push --force *master*)",
11
+ "Bash(git push --force *production*)",
12
+ "Bash(git push --force *staging*)"
13
+ ],
14
+ "allow": [
15
+ "Bash(pnpm:*)",
16
+ "Bash(npx:*)",
17
+ "Bash(node:*)",
18
+ "Bash(git status:*)",
19
+ "Bash(git diff:*)",
20
+ "Bash(git log:*)",
21
+ "Bash(git branch:*)",
22
+ "Bash(git show:*)",
23
+ "Bash(git add:*)",
24
+ "Bash(git commit:*)",
25
+ "Bash(git pull:*)",
26
+ "Bash(git fetch:*)",
27
+ "Bash(gh pr:*)",
28
+ "Bash(gh repo:*)"
29
+ ]
30
+ }
31
+ }
@@ -0,0 +1,25 @@
1
+ # Copy this file to .env.local and fill in real values for your environment.
2
+ # .env.local is gitignored — never commit real secrets.
3
+
4
+ # --- API ---
5
+ VITE_API_BASE_URL=https://api.example.com
6
+ VITE_API_TIMEOUT_MS=30000
7
+
8
+ # --- Auth ---
9
+ VITE_AUTH_HEADER_NAME=Authorization
10
+
11
+ # --- Audit ---
12
+ VITE_AUDIT_ENDPOINT=/api/audit
13
+ VITE_AUDIT_BATCH_SIZE=20
14
+ VITE_AUDIT_FLUSH_INTERVAL_MS=5000
15
+
16
+ # --- Observability (optional) ---
17
+ # Sentry DSN — leave empty to disable
18
+ VITE_SENTRY_DSN=
19
+
20
+ # --- Session ---
21
+ VITE_IDLE_TIMEOUT_MS=900000 # 15 minutes
22
+ VITE_SENSITIVE_IDLE_TIMEOUT_MS=300000 # 5 minutes for transaction routes
23
+
24
+ # --- Feature flags ---
25
+ VITE_FEATURE_FLAGS_PROVIDER=local
@@ -0,0 +1,49 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, staging]
6
+ pull_request:
7
+ branches: [main, staging]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ build:
14
+ runs-on: ubuntu-latest
15
+ timeout-minutes: 15
16
+ strategy:
17
+ matrix:
18
+ node: [20]
19
+ steps:
20
+ - name: Checkout
21
+ uses: actions/checkout@v4
22
+ with:
23
+ fetch-depth: 0
24
+ - name: Setup pnpm
25
+ uses: pnpm/action-setup@v3
26
+ with:
27
+ version: 9
28
+ - name: Setup Node
29
+ uses: actions/setup-node@v4
30
+ with:
31
+ node-version: ${{ matrix.node }}
32
+ cache: pnpm
33
+ - name: Install
34
+ run: pnpm install --frozen-lockfile
35
+ - name: Typecheck
36
+ run: pnpm typecheck
37
+ - name: Lint
38
+ run: pnpm lint
39
+ - name: Test
40
+ run: pnpm test
41
+ - name: Build
42
+ run: pnpm build
43
+ - name: npm audit (high+)
44
+ run: pnpm audit --audit-level=high
45
+ continue-on-error: true
46
+ - name: Gitleaks
47
+ uses: gitleaks/gitleaks-action@v2
48
+ env:
49
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,89 @@
1
+ # CLAUDE.md — `{{projectName}}`
2
+
3
+ BFSI React project scaffolded from `create-app`. This file is what Claude reads at session start, per the [Claude Code spec](https://code.claude.com/docs/best-practices).
4
+
5
+ ## Stack (so you don't have to read configs)
6
+
7
+ - **React 18** + **Vite 5** + **TypeScript strict**
8
+ - **Tailwind CSS** + **shadcn/ui** (components owned in `src/components/ui/`)
9
+ - **React Hook Form** + **Zod** for forms
10
+ - **react-router-dom v6** with `<ProtectedRoute permission="...">` guards
11
+ - **react-i18next** (`en`, `hi` defaults)
12
+ - Data layer: **RTK Query** OR **TanStack Query** — check `package.json` to confirm which
13
+ - Tests: **Vitest** + **Testing Library**; E2E **Playwright**
14
+
15
+ ## Bash commands
16
+
17
+ ```bash
18
+ pnpm dev # vite dev server on :5173
19
+ pnpm build # tsc -b && vite build
20
+ pnpm test # vitest run
21
+ pnpm test:watch # vitest watch
22
+ pnpm test:e2e # playwright
23
+ pnpm typecheck # tsc -b --noEmit
24
+ pnpm lint # eslint, --max-warnings 0
25
+ pnpm format # prettier write
26
+ ```
27
+
28
+ ## Critical conventions (DO NOT violate)
29
+
30
+ 1. **Tokens never in `localStorage`.** Use `setAuthToken(axios, token)` from `@<scope>/core/http` at login — it lives in memory.
31
+ 2. **All API responses go through Zod `.parse()`.** No raw types. See the `rtk-query-api` or `tanstack-services` skill.
32
+ 3. **PII fields display via `<PIIMaskedDisplay>`.** Never render PAN/Aadhaar/account-number directly.
33
+ 4. **No card data in HTML inputs.** Use `<PCITokenizedCardInput>` (v0.2 — for now, flag any plain card input).
34
+ 5. **All routes are `<ProtectedRoute permission="...">`** with explicit permission strings (route to feature-permission mapping in `src/routes/`).
35
+ 6. **No `dangerouslySetInnerHTML`** unless explicitly sanitised. Pre-write hook will block it.
36
+ 7. **No `console.log` of PII variables** (PAN, Aadhaar, account, password, OTP). Post-write hook scans for this.
37
+ 8. **Conventional Commits with BFSI types**: `feat`, `fix`, `security`, `compliance`, `audit`, `perf`, `refactor`, `docs`, `style`, `test`, `build`, `ci`, `chore`. NO `Co-Authored-By` trailer.
38
+
39
+ ## Where things live
40
+
41
+ ```
42
+ src/
43
+ ├── app/ App.tsx, providers, globals.css
44
+ ├── routes/ ProtectedRoute, route config
45
+ ├── features/<Feature>/ ALL feature code: api/schema/types/containers/components/tests
46
+ ├── shared/ Cross-feature components (ErrorBoundary, NotFound)
47
+ ├── i18n/ react-i18next setup + translations/en.json + hi.json
48
+ ├── utils/constants/ urls / routes / regex / tag-types / app constants
49
+ ├── env.ts Zod-validated env (throws at boot on bad config)
50
+ └── main.tsx Entry point
51
+ ```
52
+
53
+ Variant-specific:
54
+
55
+ - **RTK Query**: `src/axiosconfig/` (instance + interceptor + baseQuery), `src/redux/` (store + rootReducer + reduxHooks + invalidateCacheMiddleware)
56
+ - **TanStack Query**: `src/api/` (axiosInstance + http + queryClient), `src/services/` (typed service methods)
57
+
58
+ ## Claude skills available
59
+
60
+ Run `/skills` or open `.claude/skills/<name>/SKILL.md` directly. Reference skills auto-load when relevant; action skills are invoked with `/<name>`.
61
+
62
+ **Always available** (from the toolkit): `/bfsi-feature`, `/bfsi-form`, `/bfsi-pii-field`, `/bfsi-api-endpoint`, `/bfsi-compliance-check`, `/bfsi-commit`, `/bfsi-doctor`, `/bfsi-onboarding`, `/bfsi-review`, `/bfsi-audit`.
63
+
64
+ **Variant-specific** (in `.claude/skills/`):
65
+ - RTK: `axios-auth`, `constants-organization`, `redux-store-integration`, `rtk-query-api`
66
+ - TanStack: `axios-auth`, `constants-organization`, `tanstack-services`, `query-client-setup`
67
+
68
+ ## Auto-review on Stop
69
+
70
+ A Stop hook runs a review sub-agent after every coding turn. If it finds P0 (security/PII/secrets) or P1 (convention violations) issues in the uncommitted diff, it'll show you the list and ask:
71
+
72
+ 1. **Fix all now** — Claude resolves every P0/P1 finding before stopping
73
+ 2. **Fix selected ones** — checkbox list, you pick which
74
+ 3. **Skip** — Claude stops; the findings list is yours to act on
75
+
76
+ No prompt fires when the diff is clean, doc-only, or contains only P2 (style/naming) findings. To turn it off entirely, delete the second entry under `Stop` in `.claude/settings.json`.
77
+
78
+ ## Gotchas
79
+
80
+ - `.env.local` is gitignored. If app fails at boot with a Zod error, copy `.env.local.sample` → `.env.local` and fill in real values.
81
+ - `src/components/ui/` is shadcn-managed. Add components via `pnpm dlx shadcn-ui@latest add <component>` — don't hand-author there.
82
+ - The dev server enforces tight security headers (X-Frame-Options: DENY, etc.). If iframe embedding fails in dev, that's why.
83
+ - ESLint runs with `--max-warnings 0`. Warnings fail CI; fix them as they appear.
84
+
85
+ ## When something fails
86
+
87
+ - Type error after `pnpm install` → `pnpm typecheck` to see all errors; the `@<scope>/core` and `@<scope>/ui` paths resolve via `link:` to the local workspace.
88
+ - 401 in dev → check `setAuthToken(axiosInstance, token)` is called in the login mutation's `onQueryStarted` (RTK) or `onSuccess` (TanStack).
89
+ - `/bfsi-doctor` fails on `.claude/settings.json $schema` → the correct URL is `https://json.schemastore.org/claude-code-settings.json`.