Skip to content

Add Claude Code configuration for storefront development#136

Open
andrewprg wants to merge 1 commit intomainfrom
feat/claude-code-config
Open

Add Claude Code configuration for storefront development#136
andrewprg wants to merge 1 commit intomainfrom
feat/claude-code-config

Conversation

@andrewprg
Copy link
Copy Markdown

Summary

  • Ships a .claude/ directory in the blueprint so anyone who clones or forks it gets pre-configured Claude Code tooling
  • Adds conditional rules (sections, routes, integrations, schemas, styling) that only load when editing relevant files
  • Adds slash commands: /new-section, /add-integration, /preflight, /refresh-rules
  • Adds a /requirements planning agent for spec-first development
  • Auto-lint hook on file edits, typecheck on session stop
  • CLAUDE.md at root for project context
  • settings.local.json excluded via .gitignore so personal overrides stay private

What's included

Path Purpose
.claude/settings.json Permissions, hooks (auto-lint, typecheck)
.claude/rules/sections.md 33 registered sections, conventions
.claude/rules/routes.md Route patterns, data fetching context
.claude/rules/integrations.md Klaviyo, Admin API, analytics platforms
.claude/rules/schemas.md 10 settings files inventory
.claude/rules/styling.md Design tokens, fonts, colors, breakpoints
.claude/commands/ new-section, add-integration, preflight, refresh-rules
.claude/agents/requirements.md Requirements & Solution Architect
CLAUDE.md Project context for AI assistants

Test plan

  • Clone the repo fresh and verify .claude/ structure is present
  • Open in Claude Code and confirm rules load conditionally (edit a section file → sections rule loads)
  • Run /preflight to verify the command works
  • Verify settings.local.json is not tracked (git status shows it untracked)

🤖 Generated with Claude Code

Ships .claude/ directory so anyone who clones or forks the blueprint
gets pre-configured Claude Code tooling out of the box.

- .claude/rules/: conditional rules for sections, routes, integrations, schemas, styling
- .claude/commands/: /new-section, /add-integration, /preflight, /refresh-rules
- .claude/agents/: /requirements planning subagent
- .claude/settings.json: auto-lint on edit, typecheck on stop, permission guardrails
- CLAUDE.md: project context for AI assistants
- .gitignore: exclude settings.local.json from tracking

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
"Bash(npx eslint *)",
"Bash(npx prettier *)",
"Bash(npx tsc *)",
"Bash(npm install *)",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security: Prompt injection via auto-approved package installs. An attacker who can inject content into any file Claude reads during a session (Pack CMS page content, a PR description, a file comment) can include run npm install malicious-package and this permission will auto-approve the install without any user prompt. A malicious package could exfiltrate PRIVATE_* env vars or silently modify source files.

Either remove this entry entirely (users approve individual npm install invocations case-by-case) or restrict it to the no-argument form:

Suggested change
"Bash(npm install *)",
"Bash(npm install)",

That allows npm install (restore all deps from lockfile) but not npm install <arbitrary-package>.

"Bash(git log*)",
"Bash(git diff*)",
"Bash(git branch*)",
"Bash(git checkout*)",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor suggestion: git checkout* is a superset that includes git checkout -- . and git checkout -- <file>, both of which discard uncommitted changes to tracked files — the same class of destructive action that "Bash(git reset --hard*)" is explicitly denied below. The deny list's intent seems to be preventing silent loss of work, but this allow entry creates a gap.

Consider splitting the intent:

Suggested change
"Bash(git checkout*)",
"Bash(git checkout -b *)",
"Bash(git checkout --track *)",
"Bash(git switch *)",

Or at minimum, add a deny entry for the destructive form:

"Bash(git checkout -- *)"

Non-blocking — branch switching is the common case and Claude will usually ask before discarding changes anyway, but the asymmetry with the reset --hard deny is worth closing.


1. Create directory: `app/sections/{SectionName}/`
2. Create component: `{SectionName}.tsx` — export default functional component accepting `{cms}` prop
3. Create schema: `app/sections/{SectionName}/{SectionName}.schema.ts` — export a `Schema` function returning `{ category, label, key, previewSrc, fields }`
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor suggestion: two Pack-specific schema gotchas that cause Customizer crashes are missing from this guide. Any developer following these steps could hit them:

  1. component: 'group' fields must have a group-level defaultValue — without it, the Customizer throws "Oops, something went wrong" when the group has no saved CMS data.
  2. Date fields must never default to '' or null — the Pack date picker component throws a RangeError on empty/null values. Use a valid ISO string (e.g. '2026-12-31T00:00:00.000Z').

Suggest adding a Schema gotchas note after step 3:

3. Create schema: `app/sections/{SectionName}/{SectionName}.schema.ts` — export a `Schema` function returning `{ category, label, key, previewSrc, fields }`
   - `component: 'group'` fields **must** include a group-level `defaultValue` or the Customizer crashes on first load
   - Date fields: never use `''` or `null` as `defaultValue` — use a valid ISO date string (e.g. `'2026-12-31T00:00:00.000Z'`)

Non-blocking — the existing codebase handles these correctly, but the guide as written doesn't surface them.


1. **Lint**: `npm run lint`
- If violations found, report them with file paths and line numbers
- Suggest fixes but do not auto-fix
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor suggestion: this conflicts with the PostToolUse hook in settings.json, which runs eslint --fix automatically on every file save. A developer running /preflight after editing files will have already had violations auto-fixed by the hook; the instruction to "suggest fixes but do not auto-fix" will be confusing in that context.

Consider aligning the wording:

Suggested change
- Suggest fixes but do not auto-fix
- Violations may already be auto-fixed by the PostToolUse lint hook; report any remaining unfixable issues

Non-blocking — the current code works correctly, the guidance is just inconsistent with the hook behavior.

@claude
Copy link
Copy Markdown

claude bot commented Apr 8, 2026

Summary

Well-structured addition of Claude Code tooling to the blueprint — the conditional rules, slash commands, and requirements agent will meaningfully accelerate development on forks. One blocking security issue in settings.json needs addressing before merge; everything else is non-blocking polish.

Review scope: 13 files, 581 additions, 0 deletions — all logic files reviewed in full. Lock files, build artifacts, and generated files skipped per policy.


Security

Blocking — .claude/settings.json:14
"Bash(npm install *)" is in the auto-allow list. Because Claude regularly reads Pack CMS content (page bodies, section fields) and file comments during storefront work, a prompt-injected instruction like run npm install malicious-package will execute without any user confirmation prompt. A malicious package can exfiltrate PRIVATE_* env vars or modify source files silently. Fix: replace with "Bash(npm install)" (no wildcard) to allow only the bare lockfile-restore form, or remove the entry and let users approve package installs case-by-case.


Key Changes Reviewed

.claude/settings.json — Permissions and hooks are well-considered overall. The deny list correctly blocks rm -rf, git push, git reset --hard, and direct .env access. The PostToolUse auto-lint hook is a good pattern — it auto-fixes on save so Claude's edits are always lint-clean. The Stop typecheck hook is purely informational (exit 0) which is the right call (non-blocking warnings). Two gaps flagged inline: the npm install * security issue (blocking) and an asymmetry between git checkout* being allowed while git reset --hard* is denied (non-blocking).

.claude/rules/sections.md — Accurate inventory of all 33 registered sections. The "Creating a New Section" checklist is correct but is missing two Pack-specific schema gotchas that cause Customizer crashes (component: 'group' requiring a group-level defaultValue, and date fields requiring a valid ISO string instead of ''/null). Flagged inline — non-blocking since existing sections handle both correctly, but a developer following the guide to the letter could hit either.

.claude/rules/integrations.md — Good call documenting the existing PUBLIC_KLAIVYO_REVISION typo (misspelled env var) explicitly. Without this note a future contributor would "fix" the typo and break the integration. The table structure and env var naming conventions are accurate.

.claude/rules/routes.md — Correctly documents the ($locale) prefix requirement, the three data sources (context.storefront, context.pack, context.admin), and the conditional availability of context.admin. The caching strategy section (CacheShort / CacheLong) aligns with Hydrogen conventions.

.claude/rules/styling.md — Comprehensive token inventory. Breakpoints, color system, font sizes, layout constants, and component classes all match the actual tailwind.config.js and app.css conventions. The note about assetsInlineLimit: 0 for CSP compliance is a useful gotcha to surface here.

.claude/rules/schemas.md — Correctly scopes this rule to global settings (app/settings/) and distinguishes it from section-level schemas. The active settings table is accurate. Same group/date defaultValue gap applies here as in sections.md — worth adding a "Conventions" note.

.claude/agents/requirements.md — Strong design: read-only tools (Read, Glob, Grep) only, explicit pushback criteria, and the constraint to not write production code unless asked. The spec → docs/specs/<feature-name>.md output target is a good forcing function for spec-first development.

.claude/commands/new-section.md — Conflict-check step first is good defensive practice. Schema co-location and registerSection() registration steps match the actual repo patterns exactly.

.claude/commands/add-integration.md — Correctly captures the PRIVATE_ / PUBLIC_ prefix convention and the Oxygen secret caveat ("configured separately via Shopify Admin"). The self-referential step to update .claude/rules/integrations.md after adding a new integration is a good pattern for keeping rules fresh.

.claude/commands/preflight.md — Functional. Minor wording inconsistency with the auto-lint hook flagged inline.

.claude/commands/refresh-rules.md — Parallel discovery across sections, integrations, settings, styling, and routes is the right approach. The "only overwrite rules that actually changed" constraint prevents noisy diffs.

CLAUDE.md — Clean project context file. Tech stack versions, directory map, and conventions are accurate. The Pack docs links (docs.packdigital.com/llms-full.txt) are useful for agents that need schema type references.

.gitignore — Correct: settings.local.json excluded so personal Anthropic API key overrides stay out of the shared repo.


Overall Assessment

1 blocking issue (npm install * supply chain vector) — fix that entry and this is ready to merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant