diff --git a/.claude/hooks/session-start.sh b/.claude/hooks/session-start.sh index 2802e02..4a17e89 100755 --- a/.claude/hooks/session-start.sh +++ b/.claude/hooks/session-start.sh @@ -18,7 +18,7 @@ cd "${CLAUDE_PROJECT_DIR:-$(dirname "$0")/../..}" # script only runs where .tool-versions isn't guaranteed to be self-enforcing # (see the CLAUDE_CODE_REMOTE guard above). On Node 18, pnpm silently skips # the platform-specific @oxc-parser native bindings; the install still exits -# 0 and the failure only appears later as an unrelated-looking `astro check` +# 0 and the failure only appears later as an unrelated-looking `astro sync` # crash. REQUIRED_NODE_MAJOR="$(awk '$1 == "nodejs" { split($2, v, "."); print v[1] }' .tool-versions 2>/dev/null)" REQUIRED_NODE_MAJOR="${REQUIRED_NODE_MAJOR:-22}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2e40705..d584c84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,7 +48,7 @@ jobs: - name: Install dependencies run: pnpm install --frozen-lockfile - # `pnpm run build` is `astro check && astro build`, which never invokes + # `pnpm run build` is type-check + `astro build`, which never invokes # ESLint or Prettier. Without these two steps a change that breaks # linting outright — an ESLint major that orphans the config file, say — # still reports a green build. diff --git a/CLAUDE.md b/CLAUDE.md index 3fcaba7..d6c1dca 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -39,7 +39,7 @@ Cannot find module '@oxc-parser/binding-linux-x64-gnu' ``` Because that happens inside Astro's content-collection sync, the visible -symptom is `astro check` aborting about two seconds in — which reads like a +symptom is `astro sync` aborting about two seconds in — which reads like a config or content error, not a dependency error. Quick check that your install is intact: @@ -57,12 +57,12 @@ ls node_modules/@oxc-parser/ # must NOT be empty |---|---| | `pnpm install --frozen-lockfile` | Install exactly what the lockfile specifies | | `pnpm run dev` | Dev server at `localhost:4321` | -| `pnpm run build` | **`astro check && astro build`** — type errors fail the build | +| `pnpm run build` | **`astro:check` then `astro build`** — type errors fail the build | | `pnpm run preview` | Serve the production build locally | | `pnpm run astro:check` | Type-check only, no build | | `pnpm run lint` / `lint:fix` | ESLint | | `pnpm run format` / `format:check` | Prettier, plus straightening curly quotes in Markdown | -| `pnpm run check` | `astro check` + lint + format check | +| `pnpm run check` | `astro:check` + lint + format check | | `pnpm run check:fix` | Same, but writes fixes | | `pnpm new:post` | Scaffold a blog post (interactive, or `--title "..."`; `--help` for flags) | @@ -167,9 +167,12 @@ font from a third-party demo host at module scope, which made every production build depend on an unrelated service's uptime. Fonts now come from `public/fonts/`. Don't reintroduce build-time fetches — vendor the asset. -**`astro check` gates the build.** `pnpm run build` runs it first, so a type -error anywhere blocks deployment. Run `pnpm run astro:check` while iterating for -a faster loop. +**Type-checking gates the build.** `pnpm run build` runs `astro:check` first, so +a type error anywhere blocks deployment. That script is `astro sync && astro-check`, +not `astro check`: when `@astrojs/check` fails to import, `astro check` logs an +error and still exits 0, so a broken install silently skips type-checking. +`astro-check` crashes instead. Keep the `astro sync` — without it a fresh checkout +reports false errors. **OG images are generated at build time** by satori + resvg for every post. Changing the OG templates re-renders ~215 PNGs, so image-heavy changes are slow @@ -201,6 +204,12 @@ anything. Vercel picks it up. It deliberately does not deploy; a previous version tried to and produced a second, competing deploy path. +Vercel's `installCommand` deletes `node_modules` before a frozen install. Vercel +restores `node_modules` from its build cache, and pnpm keeps a record there of +optional packages it skipped; when a lockfile change makes one of those +required, an incremental install still skips it. That left `@emnapi/runtime` +missing after Astro 7.4, so `@astrojs/check` could not load. + If you touch `vercel.json`, remember this is a **static multi-page** site that emits real per-route HTML — not an SPA. It does not want a catch-all rewrite to `/index.html`. diff --git a/README.md b/README.md index e83bb8f..96c51d8 100644 --- a/README.md +++ b/README.md @@ -86,13 +86,13 @@ Based on the original Brutal theme with our enhancements: | Command | Action | Notes | |---------|--------|-------| | `pnpm run dev` | Start local dev server at `localhost:4321` | Enhanced with TypeScript support | -| `pnpm run build` | Build production site to `./dist/` | Runs `astro check` first — type errors fail the build | +| `pnpm run build` | Build production site to `./dist/` | Runs `astro:check` first — type errors fail the build | | `pnpm run preview` | Preview build locally before deploying | Test production build | | `pnpm run astro` | Run Astro CLI commands | Full CLI access | | `pnpm run astro:check` | Type-check without building | Faster iteration loop | | `pnpm run lint` / `lint:fix` | ESLint | `:fix` writes fixes | | `pnpm run format` / `format:check` | Prettier | `format:check` is read-only | -| `pnpm run check` / `check:fix` | `astro check` + lint + format | Full pre-commit sweep | +| `pnpm run check` / `check:fix` | `astro:check` + lint + format | Full pre-commit sweep | | `pnpm new:post` | Create a new blog post with frontmatter | Interactive, or pass `--title`; `--help` for flags | A full build takes roughly 70-110 seconds and emits ~215 pages, including a @@ -255,7 +255,7 @@ GitHub repository, builds on every push to `main`, and publishes to #### **GitHub Actions is a build gate, not a deploy path** `.github/workflows/ci.yml` installs dependencies and runs `pnpm run build` -(`astro check && astro build`) on pushes and pull requests to `main`. That's +(type-check, then `astro build`) on pushes and pull requests to `main`. That's all it does. If a change doesn't build, it fails here before Vercel picks it up. An earlier version of this workflow also deployed to Vercel via @@ -302,7 +302,7 @@ graph TD A[Push to main] --> B[GitHub Actions: ci.yml] C[Open Pull Request] --> B B --> D[pnpm install --frozen-lockfile] - D --> E[pnpm run build
astro check && astro build] + D --> E[pnpm run build
astro sync, astro-check, astro build] E --> F{Build passes?} F -->|No| G[Red check, stop] F -->|Yes| H[Green check] diff --git a/package.json b/package.json index 13b7f45..273bc7e 100644 --- a/package.json +++ b/package.json @@ -12,17 +12,17 @@ "scripts": { "dev": "astro dev", "start": "astro dev", - "build": "astro check && astro build", + "build": "pnpm run astro:check && astro build", "preview": "astro preview", "astro": "astro", "new:post": "node scripts/new-post.js", - "astro:check": "astro check", + "astro:check": "astro sync && astro-check", "lint": "eslint .", "lint:fix": "eslint . --fix", "format": "prettier --write .", "format:check": "prettier --check .", - "check": "astro check && pnpm run lint && pnpm run format:check", - "check:fix": "astro check && pnpm run lint:fix && pnpm run format" + "check": "pnpm run astro:check && pnpm run lint && pnpm run format:check", + "check:fix": "pnpm run astro:check && pnpm run lint:fix && pnpm run format" }, "dependencies": { "@astrojs/rss": "^4.0.19", diff --git a/vercel.json b/vercel.json index b687993..b5fd4f9 100644 --- a/vercel.json +++ b/vercel.json @@ -2,7 +2,7 @@ "buildCommand": "pnpm run build", "outputDirectory": "dist", "framework": "astro", - "installCommand": "pnpm install", + "installCommand": "rm -rf node_modules && pnpm install --frozen-lockfile", "devCommand": "pnpm run dev", "redirects": [ {