@skyf0xx/hedgehog-core-full-stack-app 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/CLAUDE.core.md +147 -0
- package/LICENSE +21 -0
- package/README.md +41 -0
- package/agents/backend-eng.md +189 -0
- package/agents/front-end-eng.md +176 -0
- package/agents/ux-planner.md +174 -0
- package/hedgehog-core.yaml +20 -0
- package/package.json +41 -0
- package/skills/hedgehog-bootstrap/SKILL.md +324 -0
- package/skills/hedgehog-bootstrap-full-stack-app-core/SKILL.md +411 -0
- package/skills/hedgehog-loop/SKILL.md +643 -0
- package/skills/link-workspace-packages/SKILL.md +41 -0
- package/skills/nx-generate/SKILL.md +165 -0
- package/skills/nx-run-tasks/SKILL.md +52 -0
- package/skills/nx-workspace/SKILL.md +261 -0
- package/skills/nx-workspace/references/AFFECTED.md +27 -0
- package/vendor-skills/GSAP/ATTRIBUTION.md +30 -0
- package/vendor-skills/GSAP/LICENSE +21 -0
- package/vendor-skills/GSAP/gsap-core/SKILL.md +254 -0
- package/vendor-skills/GSAP/gsap-frameworks/SKILL.md +266 -0
- package/vendor-skills/GSAP/gsap-performance/SKILL.md +79 -0
- package/vendor-skills/GSAP/gsap-plugins/SKILL.md +433 -0
- package/vendor-skills/GSAP/gsap-react/SKILL.md +136 -0
- package/vendor-skills/GSAP/gsap-scrolltrigger/SKILL.md +296 -0
- package/vendor-skills/GSAP/gsap-timeline/SKILL.md +107 -0
- package/vendor-skills/GSAP/gsap-utils/SKILL.md +284 -0
- package/vendor-skills/GSAP/llms.txt +39 -0
- package/workspace/.env.example +5 -0
- package/workspace/.github/workflows/phase-gate.yml +17 -0
- package/workspace/.prettierignore +5 -0
- package/workspace/.prettierrc +3 -0
- package/workspace/.vscode/extensions.json +3 -0
- package/workspace/apps/api/eslint.config.mjs +3 -0
- package/workspace/apps/api/package.json +117 -0
- package/workspace/apps/api/src/app/app.module.spec.ts +15 -0
- package/workspace/apps/api/src/app/app.module.ts +15 -0
- package/workspace/apps/api/src/app/feature-modules.ts +8 -0
- package/workspace/apps/api/src/app/health.controller.ts +9 -0
- package/workspace/apps/api/src/assets/.gitkeep +0 -0
- package/workspace/apps/api/src/main.ts +32 -0
- package/workspace/apps/api/tsconfig.app.json +22 -0
- package/workspace/apps/api/tsconfig.json +13 -0
- package/workspace/apps/api/tsconfig.spec.json +36 -0
- package/workspace/apps/api/vitest.config.mts +18 -0
- package/workspace/apps/api/webpack.config.cjs +25 -0
- package/workspace/apps/api-e2e/eslint.config.mjs +3 -0
- package/workspace/apps/api-e2e/package.json +28 -0
- package/workspace/apps/api-e2e/src/api/api.spec.ts +11 -0
- package/workspace/apps/api-e2e/src/support/global-setup.ts +17 -0
- package/workspace/apps/api-e2e/src/support/test-setup.ts +6 -0
- package/workspace/apps/api-e2e/tsconfig.json +10 -0
- package/workspace/apps/api-e2e/tsconfig.spec.json +28 -0
- package/workspace/apps/api-e2e/vitest.config.mts +20 -0
- package/workspace/apps/web/.env.example +12 -0
- package/workspace/apps/web/.prettierrc.js +10 -0
- package/workspace/apps/web/.swcrc +30 -0
- package/workspace/apps/web/components.json +21 -0
- package/workspace/apps/web/eslint.config.mjs +12 -0
- package/workspace/apps/web/index.d.ts +7 -0
- package/workspace/apps/web/next-env.d.ts +7 -0
- package/workspace/apps/web/next.config.js +9 -0
- package/workspace/apps/web/package.json +38 -0
- package/workspace/apps/web/postcss.config.mjs +7 -0
- package/workspace/apps/web/public/.gitkeep +0 -0
- package/workspace/apps/web/public/favicon.ico +0 -0
- package/workspace/apps/web/src/app/global.css +83 -0
- package/workspace/apps/web/src/app/layout.tsx +34 -0
- package/workspace/apps/web/src/app/module-routes.ts +13 -0
- package/workspace/apps/web/src/app/page.tsx +34 -0
- package/workspace/apps/web/src/app/providers.tsx +12 -0
- package/workspace/apps/web/src/components/theme-toggle.spec.tsx +20 -0
- package/workspace/apps/web/src/components/theme-toggle.tsx +32 -0
- package/workspace/apps/web/src/components/ui/button.tsx +60 -0
- package/workspace/apps/web/src/lib/utils.ts +6 -0
- package/workspace/apps/web/src/test-setup.ts +1 -0
- package/workspace/apps/web/tsconfig.json +62 -0
- package/workspace/apps/web/tsconfig.spec.json +37 -0
- package/workspace/apps/web/vitest.config.mts +27 -0
- package/workspace/apps/web-e2e/eslint.config.mjs +12 -0
- package/workspace/apps/web-e2e/package.json +10 -0
- package/workspace/apps/web-e2e/playwright.config.mts +75 -0
- package/workspace/apps/web-e2e/src/example.spec.ts +7 -0
- package/workspace/apps/web-e2e/tsconfig.json +26 -0
- package/workspace/commitlint.config.cjs +3 -0
- package/workspace/core.yaml +68 -0
- package/workspace/docker-compose.yml +14 -0
- package/workspace/eslint.config.mjs +15 -0
- package/workspace/gitignore.template +24 -0
- package/workspace/lefthook.yml +52 -0
- package/workspace/nx.json +90 -0
- package/workspace/package.json +99 -0
- package/workspace/packages/config/eslint-base.js +205 -0
- package/workspace/packages/config/package.json +28 -0
- package/workspace/packages/config/prettier.js +13 -0
- package/workspace/packages/config/src/env.schema.spec.ts +38 -0
- package/workspace/packages/config/src/env.schema.ts +18 -0
- package/workspace/packages/config/src/index.ts +1 -0
- package/workspace/packages/config/tsconfig.json +13 -0
- package/workspace/packages/config/tsconfig.lib.json +27 -0
- package/workspace/packages/config/tsconfig.spec.json +34 -0
- package/workspace/packages/config/vitest.config.mts +18 -0
- package/workspace/packages/db/package.json +27 -0
- package/workspace/packages/db/src/index.ts +2 -0
- package/workspace/packages/db/src/lib/db.spec.ts +48 -0
- package/workspace/packages/db/src/lib/db.ts +54 -0
- package/workspace/packages/db/src/schema/index.ts +4 -0
- package/workspace/packages/db/tsconfig.json +13 -0
- package/workspace/packages/db/tsconfig.lib.json +27 -0
- package/workspace/packages/db/tsconfig.spec.json +34 -0
- package/workspace/packages/db/vitest.config.mts +18 -0
- package/workspace/pnpm-lock.yaml +23719 -0
- package/workspace/pnpm-workspace.yaml +7 -0
- package/workspace/tools/generate-feature-modules.cjs +104 -0
- package/workspace/tools/generate-module-routes.cjs +89 -0
- package/workspace/tools/generators/contract/generator.ts +336 -0
- package/workspace/tools/generators/contract/schema.json +24 -0
- package/workspace/tools/generators/controller/generator.ts +390 -0
- package/workspace/tools/generators/controller/schema.json +24 -0
- package/workspace/tools/generators/fields.ts +160 -0
- package/workspace/tools/generators/generators.json +42 -0
- package/workspace/tools/generators/hook/generator.ts +291 -0
- package/workspace/tools/generators/hook/schema.json +19 -0
- package/workspace/tools/generators/lib-shell.ts +124 -0
- package/workspace/tools/generators/naming.ts +84 -0
- package/workspace/tools/generators/package.json +6 -0
- package/workspace/tools/generators/repository/generator.ts +298 -0
- package/workspace/tools/generators/repository/schema.json +15 -0
- package/workspace/tools/generators/schema/generator.ts +169 -0
- package/workspace/tools/generators/schema/schema.json +20 -0
- package/workspace/tools/generators/screen/generator.ts +218 -0
- package/workspace/tools/generators/screen/schema.json +15 -0
- package/workspace/tools/generators/service/generator.ts +270 -0
- package/workspace/tools/generators/service/schema.json +19 -0
- package/workspace/tools/phase-gate.cjs +77 -0
- package/workspace/tsconfig.base.json +21 -0
- package/workspace/tsconfig.json +25 -0
- package/workspace/vitest.workspace.ts +4 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ux-planner
|
|
3
|
+
description: Use once per module at the start of Phase B, after the hook step is committed and before the screen step starts. Produces a short interaction/layout rationale for the module's screen(s), grounded in established usability heuristics, and writes it to docs/design/<module>.md. Not a visual designer and not a per-component reviewer.
|
|
4
|
+
model: sonnet
|
|
5
|
+
color: green
|
|
6
|
+
tools: Read, Glob, Grep, Write
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are the ux-planner role in the Hedgehog discipline. Planning intake
|
|
10
|
+
(`planner` agent) deliberately defers "screens, flows, and how it should
|
|
11
|
+
feel" to Phase B rather than deciding it up front, alongside the domain
|
|
12
|
+
model. You are where that deferral resolves: the judgment call that
|
|
13
|
+
happens after a module's contract and hook exist, and before
|
|
14
|
+
`front-end-eng` writes a single component. `front-end-eng` implements — it
|
|
15
|
+
doesn't decide information hierarchy, interaction pattern, or which
|
|
16
|
+
usability tradeoffs apply. You decide those, once, per module, so
|
|
17
|
+
`front-end-eng` builds against a rationale instead of improvising one
|
|
18
|
+
mid-implementation.
|
|
19
|
+
|
|
20
|
+
## When you run
|
|
21
|
+
|
|
22
|
+
- Once per module, after `feat(<module>): hooks` is committed and before
|
|
23
|
+
the screen step starts. Not per-component, not per-commit — the Loop's
|
|
24
|
+
gate already covers implementation correctness.
|
|
25
|
+
- When the user says "plan the screen," "how should this flow," or asks
|
|
26
|
+
for UX/usability input before or during Phase B.
|
|
27
|
+
- Re-run only when a screen step reveals the plan was wrong — patch
|
|
28
|
+
`docs/design/<module>.md` in place and flag the dependent screen work
|
|
29
|
+
to fast-forward, per the Correction Protocol (`hedgehog-loop` skill).
|
|
30
|
+
Not on every screen edit.
|
|
31
|
+
|
|
32
|
+
Your first run for a module signals to the user that Phase B has started
|
|
33
|
+
for it. Check for `docs/design/<module>-notes.md` first — raw screen/flow
|
|
34
|
+
material `planner` files per module at planning intake, for you to act on here.
|
|
35
|
+
If it's thin, or a specific detail you need (information architecture, a
|
|
36
|
+
named flow, visual identity) isn't in it, read the full source directly:
|
|
37
|
+
`.hedgehog/BMAD/05-ux-spec/DESIGN.md` and `EXPERIENCE.md`, the un-mined
|
|
38
|
+
UX spec `planner`'s notes were drawn from. Read whichever of the two the
|
|
39
|
+
archive holds — a project planned through compressed intake
|
|
40
|
+
(`hedgehog-planning-intake`'s Phase 0) has `EXPERIENCE.md` only, and one
|
|
41
|
+
whose brief stated no flows may have neither. **An absent file is your
|
|
42
|
+
cue to ask, not to invent.** Visual identity is the first thing a
|
|
43
|
+
compressed brief omits, so where the archive is silent, say so and
|
|
44
|
+
propose from the contract and hook rather than inferring a direction the
|
|
45
|
+
user never gave — that inference is the improvisation this step exists to
|
|
46
|
+
replace.
|
|
47
|
+
|
|
48
|
+
Read the notes file if present, then say so plainly and ask for anything
|
|
49
|
+
further before producing the rationale: "Phase A is closed for
|
|
50
|
+
`<module>` — this is the UX planning step before the screen gets built.
|
|
51
|
+
[If notes exist: "I've got what was noted at planning intake for this
|
|
52
|
+
module — here's a quick recap: (one-line summary)."] [If the archive
|
|
53
|
+
holds no UX spec: "This project was planned through compressed intake, so
|
|
54
|
+
there's no visual direction on file."] If you have a mockup, screenshot,
|
|
55
|
+
an export from a tool like Google Stitch or Figma, or an existing screen
|
|
56
|
+
you want this to resemble, hand it over now; otherwise I'll propose the
|
|
57
|
+
layout from the contract, hook, and any notes on file." Treat whatever's
|
|
58
|
+
supplied or on file the same way — a source of screen inventory and
|
|
59
|
+
hierarchy, not something to transcribe pixel-for-pixel. No visual tool or
|
|
60
|
+
prior note is required; the rationale stands on its own when nothing is
|
|
61
|
+
supplied.
|
|
62
|
+
|
|
63
|
+
## What you produce
|
|
64
|
+
|
|
65
|
+
`docs/design/<module>.md` — a short, module-scoped UX rationale, not a
|
|
66
|
+
mockup, not a design system, not code:
|
|
67
|
+
|
|
68
|
+
1. **Screen inventory**: what screen(s) or views this module's data
|
|
69
|
+
requires (list view, detail view, form, confirmation step) — derived
|
|
70
|
+
from the contract's operations, not invented.
|
|
71
|
+
2. **Interaction pattern per screen**: the shape of the interaction
|
|
72
|
+
(inline edit vs. modal vs. dedicated page; optimistic update vs.
|
|
73
|
+
confirm-then-wait), each tied to a specific heuristic below.
|
|
74
|
+
3. **Information hierarchy**: what's primary vs. secondary on each
|
|
75
|
+
screen, given the module's actual fields — not every column in the
|
|
76
|
+
schema deserves equal visual weight.
|
|
77
|
+
4. **Named risks**: places a naive implementation would violate a
|
|
78
|
+
heuristic (e.g. a destructive action with no confirmation, a target
|
|
79
|
+
too small to hit reliably, a state change with no visible feedback).
|
|
80
|
+
5. **Source material**, if any was supplied or found on file: what it
|
|
81
|
+
was (a screenshot, a Stitch/Figma export, a named reference app,
|
|
82
|
+
planning-intake notes from `docs/design/<module>-notes.md`, or the
|
|
83
|
+
raw UX spec at `.hedgehog/BMAD/05-ux-spec/`) and what was drawn from
|
|
84
|
+
it versus decided independently. Where there was none — a compressed
|
|
85
|
+
archive with no UX spec and nothing supplied — say that plainly here,
|
|
86
|
+
so `front-end-eng` and `reviewer` read the rationale as reasoned from
|
|
87
|
+
the contract and hook rather than from a direction on file.
|
|
88
|
+
|
|
89
|
+
Keep it short — a few bullets per screen, not a document. This is a
|
|
90
|
+
rationale `front-end-eng` reads once before starting, and `reviewer` can
|
|
91
|
+
check against later — not a spec either cross-checks line by line.
|
|
92
|
+
|
|
93
|
+
## Heuristics you draw on
|
|
94
|
+
|
|
95
|
+
Grounded in established usability principles (Laws of UX and equivalent
|
|
96
|
+
sources — Fitts's Law, Hick's Law, Jakob's Law, the Von Restorff effect,
|
|
97
|
+
recognition over recall, Miller's Law, the proximity/similarity Gestalt
|
|
98
|
+
principles, and feedback/visibility of system status). Apply them as
|
|
99
|
+
reasoning tools, not a checklist to recite:
|
|
100
|
+
|
|
101
|
+
- **Fitts's Law** — interactive targets sized and placed for how often
|
|
102
|
+
and how urgently they're used (a destructive action isn't the biggest,
|
|
103
|
+
easiest-to-hit button on the screen).
|
|
104
|
+
- **Hick's Law** — fewer, clearer choices at any one decision point;
|
|
105
|
+
don't surface every contract operation as an equally-weighted action.
|
|
106
|
+
- **Jakob's Law** — match patterns users already know from other tools
|
|
107
|
+
(standard form/table/modal conventions) unless the module's workflow
|
|
108
|
+
genuinely needs to diverge, and name why if it does.
|
|
109
|
+
- **Recognition over recall** — show options and current state rather
|
|
110
|
+
than requiring the user to remember what's possible or what they set
|
|
111
|
+
earlier.
|
|
112
|
+
- **Miller's Law / chunking** — group related fields; don't present a
|
|
113
|
+
flat list of every schema column.
|
|
114
|
+
- **Visibility of system status** — every mutation (the hook layer's
|
|
115
|
+
operations) has a corresponding loading/success/error state named
|
|
116
|
+
here, not left for `front-end-eng` to decide ad hoc.
|
|
117
|
+
|
|
118
|
+
Cite the specific heuristic behind each nontrivial recommendation so
|
|
119
|
+
`front-end-eng` and `reviewer` can trace the reasoning, not just the
|
|
120
|
+
conclusion.
|
|
121
|
+
|
|
122
|
+
## Workflow
|
|
123
|
+
|
|
124
|
+
1. Confirm the module's hook step is committed (`feat(<module>): hooks`)
|
|
125
|
+
— if not, stop, this is being asked for too early.
|
|
126
|
+
2. Check for `docs/design/<module>-notes.md` and read it if present. If
|
|
127
|
+
it's thin or missing a detail you need, read whichever of
|
|
128
|
+
`.hedgehog/BMAD/05-ux-spec/DESIGN.md` and `EXPERIENCE.md` the archive
|
|
129
|
+
holds, for the full material it was drawn from. Where neither the
|
|
130
|
+
notes nor the spec covers what you need, that gap goes into step 3's
|
|
131
|
+
ask — it is not something to fill in yourself.
|
|
132
|
+
3. Announce the Phase B transition and ask for visual input, per "When
|
|
133
|
+
you run," above.
|
|
134
|
+
4. Read the contract (`packages/contracts`) for the module: what
|
|
135
|
+
operations exist, what each returns, what's required vs. optional.
|
|
136
|
+
5. Read the hook (`packages/hooks`) to confirm what's actually exposed
|
|
137
|
+
to the screen layer (loading/error states, mutation shape).
|
|
138
|
+
6. Check for existing screens in `apps/web` / `apps/mobile`, and existing
|
|
139
|
+
files under `docs/design/`, for other modules — reuse established
|
|
140
|
+
patterns (Jakob's Law applies to this codebase's own prior screens
|
|
141
|
+
first, external conventions second).
|
|
142
|
+
7. Write `docs/design/<module>.md` per "What you produce," above.
|
|
143
|
+
8. Hand off to `front-end-eng` for the screen step. The file isn't a step in
|
|
144
|
+
the Domain Module Pattern and isn't committed on its own — it lands in
|
|
145
|
+
the same commit as the screen step it informs
|
|
146
|
+
(`feat(<module>): screen-web`), same as any other file
|
|
147
|
+
`front-end-eng` touches while building that step.
|
|
148
|
+
|
|
149
|
+
## Constraints
|
|
150
|
+
|
|
151
|
+
- Write only `docs/design/<module>.md` — never application code. Same
|
|
152
|
+
read-only-against-the-codebase posture as `planner`, scoped to this one
|
|
153
|
+
file type. Read-only against `.hedgehog/BMAD/` too — archival record,
|
|
154
|
+
never edited.
|
|
155
|
+
- Never design visual style, color, typography, or branding — that's
|
|
156
|
+
`front-end-eng`'s call against the project's ShadCN/Tailwind setup, or a
|
|
157
|
+
design tool's output if one is wired into the project.
|
|
158
|
+
- Don't block the Loop. If the contract doesn't give enough to reason
|
|
159
|
+
about (e.g. no way to tell which fields matter most), ask one targeted
|
|
160
|
+
question rather than guessing — same bar as `planner`'s planning intake.
|
|
161
|
+
- Don't relitigate scope or the domain model — that's `planner`'s job,
|
|
162
|
+
already closed by the time Phase B starts.
|
|
163
|
+
- Don't produce a rationale longer than the screen it's for would
|
|
164
|
+
justify — a single form doesn't need five heuristics cited if two
|
|
165
|
+
actually apply.
|
|
166
|
+
|
|
167
|
+
## Weaknesses
|
|
168
|
+
|
|
169
|
+
- You reason from the contract and hook, not from a live user — this is
|
|
170
|
+
a heuristic pass, not usability testing. Flag assumptions that would
|
|
171
|
+
benefit from real validation rather than presenting them as settled.
|
|
172
|
+
- You may over-apply heuristics to a trivial screen. When a screen is a
|
|
173
|
+
single field and a submit button, say so plainly instead of forcing a
|
|
174
|
+
rationale onto it.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
name: full-stack-app
|
|
2
|
+
flag: --ts-full-stack-app
|
|
3
|
+
language: typescript
|
|
4
|
+
engine: "^5.0.0"
|
|
5
|
+
selects_when: >
|
|
6
|
+
The description names persistent domain data with its own lifecycle:
|
|
7
|
+
something that gets created, changes state, gets queried back later, or
|
|
8
|
+
needs accounts/auth, background jobs, or a real app beyond a single
|
|
9
|
+
page. Data that gets stored is this core at any size — a todo list, a
|
|
10
|
+
notes app, a tracker of any kind — never talked down to browser-local
|
|
11
|
+
storage or a single-file page for sounding small. If the project has
|
|
12
|
+
both a marketing page and a real app behind it, this is still
|
|
13
|
+
full-stack-app: the page becomes routes inside apps/web, not a
|
|
14
|
+
separate project.
|
|
15
|
+
workspace: workspace/
|
|
16
|
+
template: CLAUDE.core.md
|
|
17
|
+
agents: [backend-eng, ux-planner, front-end-eng]
|
|
18
|
+
skills: [hedgehog-loop, hedgehog-bootstrap, hedgehog-bootstrap-full-stack-app-core,
|
|
19
|
+
nx-generate, nx-run-tasks, nx-workspace, link-workspace-packages]
|
|
20
|
+
vendor_skills: [GSAP]
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@skyf0xx/hedgehog-core-full-stack-app",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Hedgehog's full-stack-app core: an Nx/pnpm/NestJS/Next.js workspace, backend-first domain module build discipline, and the agents and skills that drive it.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/skyf0xx/hedgehog-core-full-stack-app.git"
|
|
9
|
+
},
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"workspace",
|
|
15
|
+
"agents",
|
|
16
|
+
"skills",
|
|
17
|
+
"vendor-skills",
|
|
18
|
+
"CLAUDE.core.md",
|
|
19
|
+
"hedgehog-core.yaml",
|
|
20
|
+
"!workspace/node_modules/**",
|
|
21
|
+
"!workspace/.nx/**",
|
|
22
|
+
"!workspace/apps/*/node_modules/**",
|
|
23
|
+
"!workspace/apps/*/dist/**",
|
|
24
|
+
"!workspace/apps/*/.next/**",
|
|
25
|
+
"!workspace/apps/*/out-tsc/**",
|
|
26
|
+
"!workspace/packages/*/node_modules/**",
|
|
27
|
+
"!workspace/packages/*/dist/**"
|
|
28
|
+
],
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=22.5.0"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"hedgehog-core",
|
|
34
|
+
"hedgehog",
|
|
35
|
+
"claude-code",
|
|
36
|
+
"nx",
|
|
37
|
+
"nestjs",
|
|
38
|
+
"nextjs"
|
|
39
|
+
],
|
|
40
|
+
"license": "MIT"
|
|
41
|
+
}
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hedgehog-bootstrap
|
|
3
|
+
description: Use once, at the start of a new Hedgehog project, to land the core workspace and scaffold whichever add-ons (Auth, Queue, Mobile) planning intake turned on (`.hedgehog/addons.yaml`). Runs when the `bootstrap` agent runs, which `planner` invokes automatically after Confirm & Lock. Scoped to project scaffolding; per-module work runs through the `hedgehog-loop` skill, one step at a time.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Hedgehog Bootstrap
|
|
7
|
+
|
|
8
|
+
Scaffolds a Hedgehog project's Bootstrap phase: the always-on core, plus
|
|
9
|
+
whichever named add-ons (Auth, Queue, Mobile) planning intake's scope
|
|
10
|
+
boundary (`planner`, running BMAD-METHOD's planning shelf then mining it
|
|
11
|
+
— see that agent) actually calls for. This is Phase 2 (Scaffold) of the
|
|
12
|
+
overall bootstrap sequence — Phase 0 (BMAD elicitation) and Phase 1
|
|
13
|
+
(mining into the build graph and `.hedgehog/addons.yaml`) already closed
|
|
14
|
+
by the time this skill runs. After this closes, `hedgehog-loop` takes
|
|
15
|
+
over per module, one step at a time.
|
|
16
|
+
This skill touches no domain modules — no schema, no contract, nothing
|
|
17
|
+
under `libs/<module>/`. That's Phase A, started fresh after Bootstrap
|
|
18
|
+
closes.
|
|
19
|
+
|
|
20
|
+
**Core lands via `hedgehog-bootstrap-full-stack-app-core`, run first, unconditionally.**
|
|
21
|
+
That skill copies a pre-built, pre-verified workspace (Nx, enforcement
|
|
22
|
+
config, `packages/db`, `apps/api`, `apps/web`) rather than generating it
|
|
23
|
+
live — core is identical on every project, so it's built once upstream
|
|
24
|
+
and copied, not re-derived per project. This skill covers only what's
|
|
25
|
+
still genuinely project-specific: whether Auth, Queue, and Mobile are on,
|
|
26
|
+
and — if so — scaffolding them.
|
|
27
|
+
|
|
28
|
+
Run the `nx g` commands below via nrwl's [nx-generate](https://github.com/nrwl/nx-ai-agents-config/tree/main/skills/nx-generate) skill — it dry-runs
|
|
29
|
+
and verifies generator flags against the installed Nx version. Run the
|
|
30
|
+
`nx run` / `nx affected` commands via
|
|
31
|
+
[nx-run-tasks](https://github.com/nrwl/nx-ai-agents-config/tree/main/skills/nx-run-tasks) the same way. The commands below are the spec; those
|
|
32
|
+
skills execute it correctly.
|
|
33
|
+
|
|
34
|
+
## The Stack: core + add-ons
|
|
35
|
+
|
|
36
|
+
Hedgehog has one non-negotiable **core** — applied to every project that
|
|
37
|
+
uses Hedgehog at all, regardless of size — plus a small set of named
|
|
38
|
+
**add-ons**, each scaffolded only when planning intake's scope boundary
|
|
39
|
+
(`planner`) actually calls for it. The core is not "the small version of
|
|
40
|
+
the stack"; it's the fixed floor, landed by `hedgehog-bootstrap-full-stack-app-core`.
|
|
41
|
+
Add-ons are not "extra polish"; each is standing infra with a real
|
|
42
|
+
ongoing cost (a service to run, a secret to manage, a seam to keep
|
|
43
|
+
idempotent) that a project without the matching need shouldn't carry.
|
|
44
|
+
|
|
45
|
+
### Core (every project, no exceptions — see `hedgehog-bootstrap-full-stack-app-core`)
|
|
46
|
+
|
|
47
|
+
| Layer | Choice |
|
|
48
|
+
|---|---|
|
|
49
|
+
| Monorepo | Nx |
|
|
50
|
+
| Package manager | pnpm |
|
|
51
|
+
| Backend framework | NestJS |
|
|
52
|
+
| ORM | Drizzle (+ `drizzle-zod`) |
|
|
53
|
+
| Database | PostgreSQL |
|
|
54
|
+
| Local infra | Docker Compose (Postgres) |
|
|
55
|
+
| Platform | Railway |
|
|
56
|
+
| API contract | ts-rest |
|
|
57
|
+
| Validation | Zod |
|
|
58
|
+
| Data fetching / hooks | TanStack Query |
|
|
59
|
+
| Web UI | Next.js (frontend only) + ShadCN + Tailwind |
|
|
60
|
+
| Logging | Pino (`nestjs-pino`) |
|
|
61
|
+
| Lint / format | ESLint (flat config) + Prettier (+ `prettier-plugin-tailwindcss`, scoped to `apps/web`) |
|
|
62
|
+
| Testing | Vitest (unit/integration) + Playwright (web e2e) |
|
|
63
|
+
| Commits | Conventional Commits + commitlint + lefthook |
|
|
64
|
+
| Observability | Sentry |
|
|
65
|
+
|
|
66
|
+
Constraint-contingent substitutions: Prisma for Drizzle when the team
|
|
67
|
+
isn't SQL-comfortable; cloud + Pulumi/SST for Railway when full
|
|
68
|
+
declarative IaC is a hard requirement; tRPC for ts-rest when the client is
|
|
69
|
+
committed TypeScript-only. A substitution here means this core's own
|
|
70
|
+
`workspace/` itself needs regenerating against the substitute before
|
|
71
|
+
this project's Bootstrap runs — not a per-project hand-edit after
|
|
72
|
+
landing core.
|
|
73
|
+
|
|
74
|
+
### Add-ons (scaffolded only when planning intake calls for them)
|
|
75
|
+
|
|
76
|
+
Each row is independent — on or off per project, decided at planning
|
|
77
|
+
intake's Confirm & Lock (`planner`) and recorded in
|
|
78
|
+
`.hedgehog/addons.yaml`. Turning one on inserts its Bootstrap step(s)
|
|
79
|
+
into the sequence below; turning it off means that step is skipped
|
|
80
|
+
entirely, not stubbed or partially wired.
|
|
81
|
+
|
|
82
|
+
| Add-on | Trigger (from planning intake scope) | Adds |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| **Auth** | The product has accounts, logins, or per-user data | Better Auth (+ `@thallesp/nestjs-better-auth`, Drizzle adapter), `packages/auth`, a global auth guard on `apps/api`, `BETTER_AUTH_SECRET` in the env schema |
|
|
85
|
+
| **Queue** | At least one operation is genuinely long-running, retried, or fanned out | BullMQ + Redis, `apps/worker`, a `Queue` port/adapter seam, `REDIS_URL` in the env schema, Redis in `docker-compose.yml` |
|
|
86
|
+
| **Mobile** | Mobile is explicitly in scope | Expo + React Native Reusables + NativeWind, `apps/mobile` |
|
|
87
|
+
|
|
88
|
+
A project with none of these on is still a full Hedgehog project — Nx,
|
|
89
|
+
NestJS, Postgres, Docker, ts-rest, the phase discipline, and every gate
|
|
90
|
+
still apply (all landed by `hedgehog-bootstrap-full-stack-app-core`). What's cut is
|
|
91
|
+
infra with no consumer, not the discipline itself.
|
|
92
|
+
|
|
93
|
+
If a project's whole description has no persistent domain data and no
|
|
94
|
+
real lifecycle to model at all (a static marketing page, a one-off
|
|
95
|
+
script, a slide deck) — not "small," but literally no state to carry
|
|
96
|
+
across a schema/contract/service — Hedgehog doesn't apply. `planner`
|
|
97
|
+
checks for this before running BMAD's planning shelf (see that agent's
|
|
98
|
+
opening check) and says so rather than forcing the discipline onto
|
|
99
|
+
something with no domain module in it.
|
|
100
|
+
|
|
101
|
+
### Monorepo layout
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
apps/
|
|
105
|
+
web (Next.js — UI only) core, landed by hedgehog-bootstrap-full-stack-app-core
|
|
106
|
+
mobile (Expo — only if the Mobile add-on is on)
|
|
107
|
+
api (NestJS — owns all domain logic + DB access) core, landed by hedgehog-bootstrap-full-stack-app-core
|
|
108
|
+
worker (BullMQ consumers — only if the Queue add-on is on)
|
|
109
|
+
|
|
110
|
+
packages/
|
|
111
|
+
db (Drizzle schema + client) core, landed by hedgehog-bootstrap-full-stack-app-core
|
|
112
|
+
contracts (ts-rest + Zod contracts)
|
|
113
|
+
hooks (TanStack Query — shared web + mobile)
|
|
114
|
+
jobs (typed job registry / queue definitions — only if Queue is on)
|
|
115
|
+
auth (Better Auth config — only if Auth is on)
|
|
116
|
+
config (locked ESLint/Prettier/tsconfig/env schema) core, landed by hedgehog-bootstrap-full-stack-app-core
|
|
117
|
+
shared (cross-cutting types + utils)
|
|
118
|
+
|
|
119
|
+
docs/
|
|
120
|
+
design (<module>.md per module — `ux-planner` agent output)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`packages/auth` and `packages/jobs` are infra, built once, here (when
|
|
124
|
+
their add-on is on) — not touched again per module. `docs/design` fills in
|
|
125
|
+
per module during Phase B; nothing to scaffold here beyond the empty
|
|
126
|
+
directory.
|
|
127
|
+
|
|
128
|
+
### Queue add-on: seam in, usage deferred
|
|
129
|
+
|
|
130
|
+
When the Queue add-on is on, it goes in as a day-one standing default:
|
|
131
|
+
Redis provisioned on Railway, a `worker` app in the monorepo, a `Queue`
|
|
132
|
+
port with a BullMQ adapter (same pattern as repositories) — but usage
|
|
133
|
+
stays last-responsible-moment even then: an operation goes async only
|
|
134
|
+
when it genuinely needs to (long-running work, retries, fan-out).
|
|
135
|
+
Services don't know how their results are returned — the enqueue-vs-await
|
|
136
|
+
decision lives at the application/controller layer. Workers are
|
|
137
|
+
idempotent (at-least-once delivery). A project where nothing meets that
|
|
138
|
+
bar doesn't get the seam at all — see the Add-ons table above.
|
|
139
|
+
|
|
140
|
+
## Before running
|
|
141
|
+
|
|
142
|
+
Confirm planning intake already happened — intent records should exist in
|
|
143
|
+
the build graph (`hedgehog status`) and `.hedgehog/addons.yaml` should
|
|
144
|
+
exist, recording which add-ons (Auth, Queue, Mobile) are on for this
|
|
145
|
+
project. No intents yet, or no `.hedgehog/addons.yaml`: stop and point to
|
|
146
|
+
`planner` rather than guessing which add-ons apply.
|
|
147
|
+
|
|
148
|
+
Run `hedgehog-bootstrap-full-stack-app-core` first, unconditionally, if it hasn't
|
|
149
|
+
already landed core (check the commit log, or `nx.json` at the repo
|
|
150
|
+
root). That skill has its own re-run guard and Docker check — don't
|
|
151
|
+
duplicate those here.
|
|
152
|
+
|
|
153
|
+
## Steps (run in sequence, one commit per step that actually runs)
|
|
154
|
+
|
|
155
|
+
### 1. `packages/auth` — Better Auth config *(Auth add-on only)*
|
|
156
|
+
|
|
157
|
+
Skip this step entirely if Auth isn't on for this project (check
|
|
158
|
+
`.hedgehog/addons.yaml`) — don't scaffold a credential store with no
|
|
159
|
+
login anywhere in scope. If skipped, say so plainly (per the `bootstrap`
|
|
160
|
+
agent's handling of conditional steps) and move on — `.hedgehog/addons.yaml`'s
|
|
161
|
+
`auth.on: false` entry is already the durable record, nothing further to
|
|
162
|
+
write — same treatment as an out-of-scope `apps/mobile`.
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
npx nx g @nx/js:lib packages/auth --bundler=none --unitTestRunner=vitest
|
|
166
|
+
pnpm add better-auth @thallesp/nestjs-better-auth
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Configure the Drizzle adapter against `packages/db`. Add
|
|
170
|
+
`BETTER_AUTH_SECRET: z.string().min(32)` to `packages/config/env.schema.ts`
|
|
171
|
+
now (it doesn't exist in the core schema `hedgehog-bootstrap-full-stack-app-core`
|
|
172
|
+
landed), and add a matching `BETTER_AUTH_SECRET=` line with a generated
|
|
173
|
+
value to the root `.env.example` — a schema entry with no `.env.example`
|
|
174
|
+
line reproduces the exact `loadEnv()` crash-on-boot that
|
|
175
|
+
`hedgehog-bootstrap-full-stack-app-core`'s `DATABASE_URL` entry exists to prevent, just
|
|
176
|
+
for this var instead. Tag: `scope:auth`, `type:adapter`.
|
|
177
|
+
|
|
178
|
+
Also wire the global auth guard on `apps/api`: `pnpm add
|
|
179
|
+
@thallesp/nestjs-better-auth` there too and register the guard
|
|
180
|
+
(secure-by-default) against `packages/auth`. `apps/api`'s
|
|
181
|
+
`depConstraints` entry needs `scope:auth` added to its allowed
|
|
182
|
+
dependencies now — the one deliberate exception to "api reaches things
|
|
183
|
+
only through ports," since auth is cross-cutting infra, not a domain
|
|
184
|
+
module.
|
|
185
|
+
|
|
186
|
+
Commit: `feat(auth): better auth config + global guard`
|
|
187
|
+
|
|
188
|
+
### 2. `apps/worker` — BullMQ seam (Redis, no consumers yet) *(Queue add-on only)*
|
|
189
|
+
|
|
190
|
+
Skip this step entirely if Queue isn't on for this project (check
|
|
191
|
+
`.hedgehog/addons.yaml`) — no operation in scope is long-running,
|
|
192
|
+
retried, or fanned out, so there's nothing for a queue to seam in for. If
|
|
193
|
+
skipped, say so plainly and move on — same treatment as an out-of-scope
|
|
194
|
+
`apps/mobile`.
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
npx nx g @nx/node:app apps/worker
|
|
198
|
+
pnpm add bullmq ioredis
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Add a `redis` service to the root `docker-compose.yml` that
|
|
202
|
+
`hedgehog-bootstrap-full-stack-app-core` landed (Postgres-only) and
|
|
203
|
+
`REDIS_URL: z.string().url()` to `packages/config/env.schema.ts` (it
|
|
204
|
+
doesn't exist in the core schema), plus a matching `REDIS_URL=` line in
|
|
205
|
+
`.env.example` (`redis://localhost:6379`) — same `loadEnv()`
|
|
206
|
+
crash-on-boot risk as `BETTER_AUTH_SECRET` above:
|
|
207
|
+
|
|
208
|
+
```yaml
|
|
209
|
+
redis:
|
|
210
|
+
image: redis:7-alpine
|
|
211
|
+
ports:
|
|
212
|
+
- '6379:6379'
|
|
213
|
+
volumes:
|
|
214
|
+
- redis-data:/data
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
(and add `redis-data:` under the top-level `volumes:` key.)
|
|
218
|
+
|
|
219
|
+
Provision the Redis connection and a `Queue` port shape (port + BullMQ
|
|
220
|
+
adapter, same pattern repositories use later) with no consumers — usage
|
|
221
|
+
is deferred (see Queue add-on, above). Call `loadEnv()` at the top of
|
|
222
|
+
`apps/worker/src/main.ts`. Tag: `scope:worker`.
|
|
223
|
+
|
|
224
|
+
`packages/config/eslint-base.js` already ships the `scope:worker`
|
|
225
|
+
`depConstraints` entry — nothing to add here. The BullMQ adapter's file
|
|
226
|
+
name ends in `.adapter.ts`, same convention repositories use, so
|
|
227
|
+
`eslint-base.js`'s port-discipline rules apply to it unchanged.
|
|
228
|
+
|
|
229
|
+
Commit: `feat(worker): bullmq seam, no consumers`
|
|
230
|
+
|
|
231
|
+
### 3. `apps/mobile` — Expo shell *(Mobile add-on only)*
|
|
232
|
+
|
|
233
|
+
Skip this step entirely if Mobile isn't on for this project (check
|
|
234
|
+
`.hedgehog/addons.yaml`) — don't scaffold speculative infra. If skipped,
|
|
235
|
+
say so plainly and move on — same pattern as Auth (step 1) and Queue
|
|
236
|
+
(step 2) when their add-on is off.
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
npx nx g @nx/expo:app apps/mobile
|
|
240
|
+
pnpm add react-native-reusables nativewind
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Configure NativeWind's theme (`tailwind.config.js` colors, light/dark) to
|
|
244
|
+
match `apps/web`'s base theme (landed by `hedgehog-bootstrap-full-stack-app-core`) — one
|
|
245
|
+
visual identity across platforms, set once here rather than drifting
|
|
246
|
+
per-screen. Tag: `scope:mobile`.
|
|
247
|
+
|
|
248
|
+
`packages/config/eslint-base.js` already ships the `scope:mobile`
|
|
249
|
+
`depConstraints` entry — nothing to add there.
|
|
250
|
+
|
|
251
|
+
**Extend the `screen` layer in root `core.yaml` to cover mobile.** The
|
|
252
|
+
shipped layer is web-only, because `apps/mobile` exists only on a project
|
|
253
|
+
that ran this step — which is now. This step is the one place that knows
|
|
254
|
+
both that the Nx `mobile` project exists and that its test target is real:
|
|
255
|
+
|
|
256
|
+
```yaml
|
|
257
|
+
- id: screen
|
|
258
|
+
depends_on: hook
|
|
259
|
+
scope: ["apps/web/src/app/{module}/**", "apps/mobile/src/{module}/**"]
|
|
260
|
+
verify: "pnpm nx test web -- src/app/{module}/ && pnpm nx test mobile -- src/{module}/"
|
|
261
|
+
commit: "feat({module}): screen-web"
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Then run `hedgehog plan --recompile`. `planner` already compiled every
|
|
265
|
+
module's tasks before handing over, so the edit reaches the not-yet-started
|
|
266
|
+
`screen` tasks only through a recompile — `hedgehog status`'s DRIFT section
|
|
267
|
+
names them until it runs. Show the recompile output: it should list one
|
|
268
|
+
updated `*-SCREEN` task per module and skip nothing.
|
|
269
|
+
|
|
270
|
+
Commit: `feat(mobile): expo shell + base theme`
|
|
271
|
+
|
|
272
|
+
## Step order
|
|
273
|
+
|
|
274
|
+
A project with every add-on off runs zero steps from this file; a
|
|
275
|
+
project with all three on runs three, in this order (Auth before Queue
|
|
276
|
+
before Mobile, since Auth's guard should exist before other infra
|
|
277
|
+
touches `apps/api`, and Queue/Mobile have no ordering dependency on each
|
|
278
|
+
other).
|
|
279
|
+
|
|
280
|
+
## Locked format/lint config
|
|
281
|
+
|
|
282
|
+
One shared config, extended everywhere — landed by
|
|
283
|
+
`hedgehog-bootstrap-full-stack-app-core`, referenced (not re-created) by every add-on
|
|
284
|
+
step above:
|
|
285
|
+
|
|
286
|
+
- `packages/config/eslint-base.js` — flat config, extended by every
|
|
287
|
+
app/lib.
|
|
288
|
+
- `packages/config/prettier.js` — the shared base, *without*
|
|
289
|
+
`prettier-plugin-tailwindcss` (that's `apps/web`'s own config, already
|
|
290
|
+
wired by `hedgehog-bootstrap-full-stack-app-core`).
|
|
291
|
+
|
|
292
|
+
A per-app override request signals to fix the base config at the source.
|
|
293
|
+
|
|
294
|
+
## After Bootstrap
|
|
295
|
+
|
|
296
|
+
Once every `on` add-on in `.hedgehog/addons.yaml` has its commit landed
|
|
297
|
+
(core's commit already landed via
|
|
298
|
+
`hedgehog-bootstrap-full-stack-app-core`), hand off to `hedgehog-loop` —
|
|
299
|
+
from here, every domain module goes through Phase A layers one at a
|
|
300
|
+
time via `hedgehog next`/`hedgehog verify`, each its own commit.
|
|
301
|
+
|
|
302
|
+
## Constraints
|
|
303
|
+
|
|
304
|
+
- Run `hedgehog-bootstrap-full-stack-app-core` first, unconditionally, before any step
|
|
305
|
+
in this file — never scaffold an add-on against a core that hasn't
|
|
306
|
+
landed and verified clean.
|
|
307
|
+
- Add-on steps (Auth, Queue, Mobile) run only if `.hedgehog/addons.yaml`
|
|
308
|
+
(written by `planner` at planning intake) turns that add-on on — say so
|
|
309
|
+
plainly and skip otherwise, don't leave it ambiguous whether the step
|
|
310
|
+
was considered.
|
|
311
|
+
- Don't add domain schema, contracts, or any `libs/<module>/*` content —
|
|
312
|
+
that's Phase A, started after Bootstrap, one module at a time.
|
|
313
|
+
- Don't deviate from the package/library choices above, for whichever
|
|
314
|
+
steps actually run. If a generator or package name changed upstream
|
|
315
|
+
since this was written, verify against current docs before running the
|
|
316
|
+
command — don't substitute a different library. Skipping an add-on
|
|
317
|
+
step whose trigger genuinely isn't in scope is not a deviation; adding
|
|
318
|
+
a library the stack doesn't call for, or dropping one it does, is.
|
|
319
|
+
- Each step that runs is its own commit, in order — same unit-of-work
|
|
320
|
+
discipline as every other step in the discipline, even though this is
|
|
321
|
+
infra rather than a domain module.
|
|
322
|
+
- Never substitute a natively-installed Postgres or Redis, even to match
|
|
323
|
+
a contributor's existing local setup — see `hedgehog-bootstrap-full-stack-app-core`'s
|
|
324
|
+
**Local infra: Docker, always**.
|