@skyf0xx/hedgehog 0.1.19 → 0.1.21
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/package.json +1 -1
- package/src/agents/front-end-eng.md +16 -1
- package/src/golden-core/.env.example +4 -0
- package/src/golden-core/apps/api/package.json +2 -0
- package/src/golden-core/apps/api/src/main.ts +4 -1
- package/src/golden-core/apps/api-e2e/src/support/global-setup.ts +1 -1
- package/src/golden-core/apps/api-e2e/src/support/test-setup.ts +1 -1
- package/src/golden-core/package.json +3 -0
- package/src/golden-core/pnpm-lock.yaml +42 -0
- package/src/skills/hedgehog-bootstrap/SKILL.md +11 -2
- package/src/skills/hedgehog-bootstrap-core/SKILL.md +28 -6
- package/src/skills/hedgehog-loop/SKILL.md +6 -1
package/package.json
CHANGED
|
@@ -36,7 +36,15 @@ when a new package needs wiring into a consumer's dependencies.
|
|
|
36
36
|
|
|
37
37
|
- **Step 6 (hook)**: build the TanStack Query hook in `packages/hooks`,
|
|
38
38
|
wrapping the ts-rest contract client. One hook per contract operation,
|
|
39
|
-
typed end to end from the Zod contract.
|
|
39
|
+
typed end to end from the Zod contract. The client's base URL comes
|
|
40
|
+
from a `NEXT_PUBLIC_`-prefixed env var (added to
|
|
41
|
+
`packages/config/env.schema.ts` if it isn't there yet) — never a
|
|
42
|
+
hardcoded `http://localhost:<port>` literal, even as a "temporary"
|
|
43
|
+
fallback. `apps/api`'s dev port is `3333` (see `hedgehog-bootstrap-core`
|
|
44
|
+
— chosen specifically to not collide with `apps/web`'s `next dev`
|
|
45
|
+
default of `3000`); a literal fallback drifts out of sync with that the
|
|
46
|
+
moment either port changes and produces a silent 404 that looks like a
|
|
47
|
+
routing bug, not a config bug.
|
|
40
48
|
- **Step 7 (screen)**: build the screen/component in `apps/web` and/or
|
|
41
49
|
`apps/mobile`, consuming the hook and `ux-planner`'s rationale for that
|
|
42
50
|
module (screen inventory, interaction pattern, information hierarchy).
|
|
@@ -77,3 +85,10 @@ when a new package needs wiring into a consumer's dependencies.
|
|
|
77
85
|
- No inline styles, no CSS modules — Tailwind utilities only.
|
|
78
86
|
- If the contract doesn't cover what the screen needs, stop and flag it
|
|
79
87
|
as a Correction Protocol case rather than reaching past the contract.
|
|
88
|
+
- After editing anything under `packages/hooks/src` (or any other
|
|
89
|
+
workspace package a running dev server consumes), run
|
|
90
|
+
`nx run hooks:build` before checking the change in a browser. Next/Expo
|
|
91
|
+
resolve workspace packages through `package.json`'s `main`/`exports`
|
|
92
|
+
fields, which point at `dist/`, not live `src/` — a stale `dist/` means
|
|
93
|
+
the dev server keeps serving the pre-edit code with no error, no
|
|
94
|
+
warning, and no indication the fix didn't take.
|
|
@@ -10,7 +10,10 @@ async function bootstrap() {
|
|
|
10
10
|
app.useLogger(app.get(Logger));
|
|
11
11
|
const globalPrefix = 'api';
|
|
12
12
|
app.setGlobalPrefix(globalPrefix);
|
|
13
|
-
|
|
13
|
+
// Defaults to 3333, not 3000 — `apps/web`'s `next dev` also defaults to
|
|
14
|
+
// 3000, and both apps run side by side in local dev (see root `dev`
|
|
15
|
+
// script), so the api needs a distinct default port to avoid colliding.
|
|
16
|
+
const port = process.env.PORT || 3333;
|
|
14
17
|
await app.listen(port);
|
|
15
18
|
app
|
|
16
19
|
.get(Logger)
|
|
@@ -7,7 +7,7 @@ export default async function setup() {
|
|
|
7
7
|
console.log('\nSetting up...\n');
|
|
8
8
|
|
|
9
9
|
const host = process.env.HOST ?? 'localhost';
|
|
10
|
-
const port = process.env.PORT ? Number(process.env.PORT) :
|
|
10
|
+
const port = process.env.PORT ? Number(process.env.PORT) : 3333;
|
|
11
11
|
await waitForPortOpen(port, { host });
|
|
12
12
|
|
|
13
13
|
return async function teardown() {
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
"private": true,
|
|
4
4
|
"type": "module",
|
|
5
5
|
"packageManager": "pnpm@9.0.0",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "docker compose up -d && nx run-many --target=serve,dev --projects=api,web --parallel"
|
|
8
|
+
},
|
|
6
9
|
"devDependencies": {
|
|
7
10
|
"@commitlint/cli": "^21.2.1",
|
|
8
11
|
"@commitlint/config-conventional": "^21.2.0",
|
|
@@ -212,6 +212,12 @@ importers:
|
|
|
212
212
|
'@nestjs/platform-express':
|
|
213
213
|
specifier: ^11.0.0
|
|
214
214
|
version: 11.1.28(@nestjs/common@11.1.28(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@11.1.28)
|
|
215
|
+
'@ts-rest/core':
|
|
216
|
+
specifier: 3.53.0-rc.1
|
|
217
|
+
version: 3.53.0-rc.1(@types/node@22.20.1)
|
|
218
|
+
'@ts-rest/nest':
|
|
219
|
+
specifier: 3.53.0-rc.1
|
|
220
|
+
version: 3.53.0-rc.1(@nestjs/common@11.1.28(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@11.1.28(@nestjs/common@11.1.28(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@ts-rest/core@3.53.0-rc.1(@types/node@22.20.1))(rxjs@7.8.1)
|
|
215
221
|
config:
|
|
216
222
|
specifier: workspace:*
|
|
217
223
|
version: link:../../packages/config
|
|
@@ -284,6 +290,9 @@ importers:
|
|
|
284
290
|
|
|
285
291
|
packages/config:
|
|
286
292
|
dependencies:
|
|
293
|
+
'@ts-rest/core':
|
|
294
|
+
specifier: 3.53.0-rc.1
|
|
295
|
+
version: 3.53.0-rc.1(@types/node@22.20.1)
|
|
287
296
|
zod:
|
|
288
297
|
specifier: ^4.0.0
|
|
289
298
|
version: 4.4.3
|
|
@@ -4515,6 +4524,28 @@ packages:
|
|
|
4515
4524
|
integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==,
|
|
4516
4525
|
}
|
|
4517
4526
|
|
|
4527
|
+
'@ts-rest/core@3.53.0-rc.1':
|
|
4528
|
+
resolution:
|
|
4529
|
+
{
|
|
4530
|
+
integrity: sha512-hDMXqKHSys6w+kXFW1Q6EvN8QgRvtXKXJ2TpYByKI4TquaPjiTOv99aLD26X4LNRzdna8Ci1PVyzr0jYZv0oNQ==,
|
|
4531
|
+
}
|
|
4532
|
+
peerDependencies:
|
|
4533
|
+
'@types/node': ^18.18.7 || >=20.8.4
|
|
4534
|
+
peerDependenciesMeta:
|
|
4535
|
+
'@types/node':
|
|
4536
|
+
optional: true
|
|
4537
|
+
|
|
4538
|
+
'@ts-rest/nest@3.53.0-rc.1':
|
|
4539
|
+
resolution:
|
|
4540
|
+
{
|
|
4541
|
+
integrity: sha512-tiuxTwXElFrAGFiUpqn78HmGgVY848D5s+uz/wCQwzRgPsfEneeZwOnEtxvXyrAp6tS5VtbVIxrI/kD+yR2zjw==,
|
|
4542
|
+
}
|
|
4543
|
+
peerDependencies:
|
|
4544
|
+
'@nestjs/common': ^9.0.0 || ^10.0.0 || ^11.0.0
|
|
4545
|
+
'@nestjs/core': ^9.0.0 || ^10.0.0 || ^11.0.0
|
|
4546
|
+
'@ts-rest/core': 3.53.0-rc.1
|
|
4547
|
+
rxjs: ^7.1.0
|
|
4548
|
+
|
|
4518
4549
|
'@tybys/wasm-util@0.10.3':
|
|
4519
4550
|
resolution:
|
|
4520
4551
|
{
|
|
@@ -16814,6 +16845,17 @@ snapshots:
|
|
|
16814
16845
|
|
|
16815
16846
|
'@tokenizer/token@0.3.0': {}
|
|
16816
16847
|
|
|
16848
|
+
'@ts-rest/core@3.53.0-rc.1(@types/node@22.20.1)':
|
|
16849
|
+
optionalDependencies:
|
|
16850
|
+
'@types/node': 22.20.1
|
|
16851
|
+
|
|
16852
|
+
'@ts-rest/nest@3.53.0-rc.1(@nestjs/common@11.1.28(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@11.1.28(@nestjs/common@11.1.28(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@ts-rest/core@3.53.0-rc.1(@types/node@22.20.1))(rxjs@7.8.1)':
|
|
16853
|
+
dependencies:
|
|
16854
|
+
'@nestjs/common': 11.1.28(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
|
16855
|
+
'@nestjs/core': 11.1.28(@nestjs/common@11.1.28(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@11.1.28)(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
|
16856
|
+
'@ts-rest/core': 3.53.0-rc.1(@types/node@22.20.1)
|
|
16857
|
+
rxjs: 7.8.1
|
|
16858
|
+
|
|
16817
16859
|
'@tybys/wasm-util@0.10.3':
|
|
16818
16860
|
dependencies:
|
|
16819
16861
|
tslib: 2.8.1
|
|
@@ -168,7 +168,11 @@ pnpm add better-auth @thallesp/nestjs-better-auth
|
|
|
168
168
|
Configure the Drizzle adapter against `packages/db`. Add
|
|
169
169
|
`BETTER_AUTH_SECRET: z.string().min(32)` to `packages/config/env.schema.ts`
|
|
170
170
|
now (it doesn't exist in the core schema `hedgehog-bootstrap-core`
|
|
171
|
-
landed)
|
|
171
|
+
landed), and add a matching `BETTER_AUTH_SECRET=` line with a generated
|
|
172
|
+
value to the root `.env.example` — a schema entry with no `.env.example`
|
|
173
|
+
line reproduces the exact `loadEnv()` crash-on-boot that
|
|
174
|
+
`hedgehog-bootstrap-core`'s `DATABASE_URL` entry exists to prevent, just
|
|
175
|
+
for this var instead. Tag: `scope:auth`, `type:adapter`.
|
|
172
176
|
|
|
173
177
|
Also wire the global auth guard on `apps/api`: `pnpm add
|
|
174
178
|
@thallesp/nestjs-better-auth` there too and register the guard
|
|
@@ -196,7 +200,12 @@ pnpm add bullmq ioredis
|
|
|
196
200
|
Add a `redis` service to the root `docker-compose.yml`
|
|
197
201
|
`hedgehog-bootstrap-core` landed (Postgres-only until now) and
|
|
198
202
|
`REDIS_URL: z.string().url()` to `packages/config/env.schema.ts` (it
|
|
199
|
-
doesn't exist in the core schema)
|
|
203
|
+
doesn't exist in the core schema), plus a matching `REDIS_URL=` line in
|
|
204
|
+
the root `.env.example` pointing at that same `docker-compose.yml`
|
|
205
|
+
service (e.g. `redis://localhost:6379`) — same reasoning as
|
|
206
|
+
`BETTER_AUTH_SECRET` above, a schema entry without a `.env.example` line
|
|
207
|
+
just moves the `loadEnv()` crash-on-boot to this var instead of fixing
|
|
208
|
+
the class of bug:
|
|
200
209
|
|
|
201
210
|
```yaml
|
|
202
211
|
redis:
|
|
@@ -27,12 +27,15 @@ Everything under `src/golden-core/` in the installed Hedgehog package,
|
|
|
27
27
|
copied to the repo root:
|
|
28
28
|
|
|
29
29
|
- Root: `nx.json`, `pnpm-workspace.yaml`, `package.json` (with the
|
|
30
|
-
`pnpm.overrides.esbuild` pin
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
`
|
|
34
|
-
|
|
35
|
-
|
|
30
|
+
`pnpm.overrides.esbuild` pin, `packageManager` field, and a `dev`
|
|
31
|
+
script — `docker compose up -d && nx run-many --target=serve,dev
|
|
32
|
+
--projects=api,web --parallel` — so a fresh clone has one command that
|
|
33
|
+
brings up Postgres and both apps together), `eslint.config.mjs`,
|
|
34
|
+
`docker-compose.yml` (Postgres only — Redis joins later, only if the
|
|
35
|
+
Queue add-on turns on), `.env.example` (`DATABASE_URL`/`NODE_ENV`,
|
|
36
|
+
copied to `.env` in step 4), `lefthook.yml`, `commitlint.config.cjs`,
|
|
37
|
+
`tools/phase-gate.cjs`, `.github/workflows/phase-gate.yml`,
|
|
38
|
+
`tsconfig.base.json`, `pnpm-lock.yaml`.
|
|
36
39
|
- `packages/config/` — `eslint-base.js`, `prettier.js` (no
|
|
37
40
|
`prettier-plugin-tailwindcss` — that's `apps/web`'s own config, already
|
|
38
41
|
wired), `env.schema.ts` (core fields only: `DATABASE_URL`, `NODE_ENV`).
|
|
@@ -96,9 +99,17 @@ lands" above should be on disk.
|
|
|
96
99
|
|
|
97
100
|
```bash
|
|
98
101
|
pnpm install
|
|
102
|
+
cp .env.example .env
|
|
99
103
|
docker compose up -d
|
|
100
104
|
```
|
|
101
105
|
|
|
106
|
+
`.env` is gitignored and never shipped — `.env.example` is the committed
|
|
107
|
+
template (`DATABASE_URL` matching `docker-compose.yml`'s Postgres
|
|
108
|
+
credentials, `NODE_ENV=development`). Skipping the copy means
|
|
109
|
+
`packages/config`'s `loadEnv()` fails its Zod check the moment `apps/api`
|
|
110
|
+
boots (`DATABASE_URL` missing) — a confusing crash to debug live instead
|
|
111
|
+
of one line here.
|
|
112
|
+
|
|
102
113
|
`pnpm install` resolves against the committed `pnpm-lock.yaml` — this
|
|
103
114
|
should be fast and produce no lockfile changes. A lockfile diff here
|
|
104
115
|
means the shipped `pnpm-lock.yaml` doesn't match `package.json` — that's
|
|
@@ -191,6 +202,17 @@ bug by "cleaning up" what looks like an unnecessary pin or directive.
|
|
|
191
202
|
is ESM (`export default`), and without a matching `"type": "module"`
|
|
192
203
|
Node emits a `MODULE_TYPELESS_PACKAGE_JSON` warning on every prettier
|
|
193
204
|
invocation touching that directory.
|
|
205
|
+
- **`apps/api`'s dev port defaults to 3333, not 3000.** `apps/web`'s
|
|
206
|
+
`next dev` also defaults to port 3000, and the root `dev` script runs
|
|
207
|
+
both side by side (`nx run-many --target=serve,dev
|
|
208
|
+
--projects=api,web`). If `apps/api/src/main.ts` ever falls back to
|
|
209
|
+
`process.env.PORT || 3000`, whichever process binds the port second
|
|
210
|
+
either crashes or is silently unreachable, and every API call from the
|
|
211
|
+
web client 404s against Next's own dev server instead (Next has no
|
|
212
|
+
matching route, so it serves its catch-all 404 page rather than a
|
|
213
|
+
connection error — easy to mistake for a routing bug in the api
|
|
214
|
+
itself). Keep `apps/api`'s fallback at `3333` and don't let it drift
|
|
215
|
+
back to matching Next's default.
|
|
194
216
|
- **No `NODE_ENV=production` build-target override needed** (Nx
|
|
195
217
|
23.1.0, Next 16.1.7). Targets are inferred from
|
|
196
218
|
`package.json`/`next.config.js` via the `@nx/next` plugin, with no
|
|
@@ -164,7 +164,12 @@ When a downstream step reveals an upstream step was wrong:
|
|
|
164
164
|
1. Stop.
|
|
165
165
|
2. Patch the upstream step directly, in place.
|
|
166
166
|
3. Fast-forward every dependent step that breaks, each its own small
|
|
167
|
-
commit.
|
|
167
|
+
commit. If the patched step lives in a workspace package (e.g.
|
|
168
|
+
`packages/hooks`, `packages/contracts`) that a running `web`/`mobile`
|
|
169
|
+
dev server consumes, run that package's `nx run <pkg>:build` before
|
|
170
|
+
re-verifying — the dev server resolves the package's built `dist/`,
|
|
171
|
+
not its `src/`, so an unbuilt patch looks unchanged to anything
|
|
172
|
+
downstream even though the source is fixed.
|
|
168
173
|
4. The commit messages are the explanation.
|
|
169
174
|
5. Resume the loop.
|
|
170
175
|
|