From dcf8264c306c738f9bbf0304ada9334cde6c3896 Mon Sep 17 00:00:00 2001 From: Ethan Arrowood Date: Mon, 27 Apr 2026 17:05:25 -0600 Subject: [PATCH 1/4] docs: add AGENTS.md for AI agent guidance Co-Authored-By: Claude Sonnet 4.6 --- AGENTS.md | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..f4037b0 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,127 @@ +# Agent Guidelines: @harperfast/nextjs + +This is the `@harperfast/nextjs` package — a [Harper Plugin](https://docs.harperdb.io/docs/reference/components/plugins) for running Next.js applications (v14, v15, v16) within the Harper distributed runtime. It wraps Next.js config, manages the application lifecycle within Harper, and optionally provides ISR caching backed by Harper's database. + +## Repository Structure + +``` +src/ + plugin.ts # Harper plugin entry point (ESM, loaded by Harper runtime) + withHarper.cts # withHarper() Next.js config helper (CJS, loaded by Next.js) + CacheHandler.cts # Harper-backed ISR cache handler (CJS, loaded by Next.js at runtime) +schema.graphql # Harper table definitions (NextBuildInfo, NextISRCache) +config.yaml # Harper plugin configuration (pluginModule, graphqlSchema) +fixtures/ # Minimal Next.js apps used as integration test targets + next-14/ # next.config.js (CommonJS require) + next-15/ # next.config.mjs (ESM import) + next-16/ # next.config.ts (TypeScript) + next-16-caching/ # Experimental ISR caching fixture +integrationTests/ # Playwright integration test suite + fixture.ts # Harper lifecycle wiring for Playwright + next-14.pw.ts # Tests for next-14 fixture + next-15.pw.ts # Tests for next-15 fixture + next-16.pw.ts # Tests for next-16 fixture + playwright.config.ts +scripts/ + install-fixtures.js # Installs dependencies for all fixture apps +dist/ # Compiled output (do not edit) +``` + +## Development + +**Build** (compiles `.cts` files to `dist/cjs/`): +```sh +npm run build +``` + +`src/plugin.ts` is **not** compiled — Harper loads it directly via Node's type-stripping. Only `src/withHarper.cts` and `src/CacheHandler.cts` are compiled. + +**Format:** +```sh +npm run format:check # check +npm run format:fix # fix +``` + +**Requirements:** Node.js ≥ 20, npm. + +## Module System Notes + +`.cts` marks a file as CommonJS. This is required for `withHarper.cts` and `CacheHandler.cts` because Next.js config files use CommonJS resolution. `plugin.ts` stays ESM since it is loaded only by Harper's runtime. Do not change file extensions without understanding this distinction. + +## Testing + +See [CONTRIBUTING.md#testing](./CONTRIBUTING.md#testing) for the full testing guide. Tests are Playwright integration tests that run against real Harper instances using `@harperfast/integration-testing` for lifecycle management. + +**Setup (once, and after updating fixture deps):** +```sh +npm run install:fixtures +``` + +**Run all tests:** +```sh +npm run test:integration +``` + +**Run a specific test file:** +```sh +npm run test:integration -- integrationTests/next-15.pw.ts +``` + +### How Tests Are Structured + +Each test file maps to one fixture. The `fixture()` helper in `integrationTests/fixture.ts` starts Harper with the named fixture, exposes `harper`, `page`, and `request` to every test, then tears down Harper when the file finishes. Tests within a file run **sequentially**; separate test files run **in parallel** across Playwright workers. + +Each test callback may receive: +- **`harper`** — `HarperContext` from `@harperfast/integration-testing` (includes `harper.httpURL`, `harper.operationsAPIURL`) +- **`page`** — Playwright `Page` for browser-based assertions +- **`request`** — Playwright `APIRequestContext` for raw HTTP calls + +### Adding a New Test File + +1. Create a fixture app in `fixtures//` with the plugin installed and configured (see existing fixtures for reference). +2. Run `npm run install:fixtures` to install its dependencies. +3. Create `integrationTests/.pw.ts`: + +```ts +import { fixture } from './fixture.ts'; + +const { test, expect } = fixture(''); + +test('home page renders', async ({ page, harper }) => { + await page.goto(harper.httpURL); + await expect(page.locator('h1')).toHaveText('Expected heading'); +}); + +test('health endpoint returns 200', async ({ request, harper }) => { + const response = await request.get(`${harper.operationsAPIURL}/health`); + expect(response.status()).toBe(200); +}); +``` + +## Key Source Files + +**`src/plugin.ts`** — Harper plugin implementation. Handles the full Next.js application lifecycle: config resolution, build (version-specific for v14/15/16), serving via Harper's HTTP middleware, dev mode with HMR, and build info tracking to avoid redundant rebuilds across threads. Reads `HARPER_NEXTJS_MODE` env var (`dev` / `build` / `prod`). + +**`src/withHarper.cts`** — Wraps user's Next.js config. Adds `harper`, `harper-pro`, and `harperdb` to `serverExternalPackages` so Harper's native dependencies are excluded from bundling. Optionally enables ISR caching via `experimentalHarperCache: true`. + +**`src/CacheHandler.cts`** — Implements Next.js `CacheHandler` interface. Stores ISR cached page data in Harper's `harperfast_nextjs.nextjs_isr_cache` table instead of the filesystem, making cached pages available across all nodes in a Harper cluster. + +## Database Schema + +Defined in `schema.graphql`, used by `harperfast_nextjs` database: + +- **`NextBuildInfo`** — tracks build state per app (`appName` PK, `buildId`, `status`) +- **`NextISRCache`** — stores ISR cache entries (`id` PK, `data`, `lastModified` auto-updated) + +## Environment Variables + +| Variable | Description | +|----------|-------------| +| `HARPER_NEXTJS_MODE` | Plugin mode: `dev` (HMR), `build` (build-only, then exit), `prod` (default) | +| `HARPER_INTEGRATION_TEST_LOG_DIR` | If set, Harper test logs are written here (used in CI) | + +## CI + +The GitHub Actions workflow (`.github/workflows/integration-tests.yml`) runs integration tests on push to `main` and on pull requests. It installs dependencies, builds, installs fixture dependencies, installs Playwright browsers, and runs the full test suite. Playwright traces and Harper logs are uploaded as artifacts on failure. + +> Note: CI jobs are currently disabled (`if: false`). When re-enabling, set the matrix job condition back to `true`. From 21ac6613985d273a05cd7c491e7e0e4af9cfef09 Mon Sep 17 00:00:00 2001 From: Ethan Arrowood Date: Mon, 27 Apr 2026 19:02:34 -0600 Subject: [PATCH 2/4] docs: rewrite AGENTS.md to focus on behavioral contracts, grounding, and failure surface Co-Authored-By: Claude Sonnet 4.6 --- AGENTS.md | 133 +++++++++--------------------------------------------- 1 file changed, 22 insertions(+), 111 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index f4037b0..14b356d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,127 +1,38 @@ # Agent Guidelines: @harperfast/nextjs -This is the `@harperfast/nextjs` package — a [Harper Plugin](https://docs.harperdb.io/docs/reference/components/plugins) for running Next.js applications (v14, v15, v16) within the Harper distributed runtime. It wraps Next.js config, manages the application lifecycle within Harper, and optionally provides ISR caching backed by Harper's database. +## Autonomous Actions -## Repository Structure +Run freely without confirmation: +- `npm run build` +- `npm run format:fix` +- `npm run install:fixtures` +- `npm run test:integration` (and with `-- ` to target one file) -``` -src/ - plugin.ts # Harper plugin entry point (ESM, loaded by Harper runtime) - withHarper.cts # withHarper() Next.js config helper (CJS, loaded by Next.js) - CacheHandler.cts # Harper-backed ISR cache handler (CJS, loaded by Next.js at runtime) -schema.graphql # Harper table definitions (NextBuildInfo, NextISRCache) -config.yaml # Harper plugin configuration (pluginModule, graphqlSchema) -fixtures/ # Minimal Next.js apps used as integration test targets - next-14/ # next.config.js (CommonJS require) - next-15/ # next.config.mjs (ESM import) - next-16/ # next.config.ts (TypeScript) - next-16-caching/ # Experimental ISR caching fixture -integrationTests/ # Playwright integration test suite - fixture.ts # Harper lifecycle wiring for Playwright - next-14.pw.ts # Tests for next-14 fixture - next-15.pw.ts # Tests for next-15 fixture - next-16.pw.ts # Tests for next-16 fixture - playwright.config.ts -scripts/ - install-fixtures.js # Installs dependencies for all fixture apps -dist/ # Compiled output (do not edit) -``` +Ask before doing: +- Modifying fixture `package.json` files or their installed dependencies +- Changing `schema.graphql` or `config.yaml` +- Touching anything in `dist/` (it's compiled output — change the source) -## Development +## Operational Grounding -**Build** (compiles `.cts` files to `dist/cjs/`): -```sh -npm run build -``` +**Module system:** The repo is `"type": "module"` (ESM), but `src/withHarper.cts` and `src/CacheHandler.cts` must be CommonJS because Next.js config files require CJS resolution. The `.cts` extension enforces this. `src/plugin.ts` is ESM and is **not compiled** — Harper loads it directly via Node's type-stripping. Do not change file extensions. -`src/plugin.ts` is **not** compiled — Harper loads it directly via Node's type-stripping. Only `src/withHarper.cts` and `src/CacheHandler.cts` are compiled. +**Build output:** Only `.cts` files compile to `dist/cjs/`. After editing `src/withHarper.cts` or `src/CacheHandler.cts`, run `npm run build` before testing. Editing `src/plugin.ts` takes effect immediately without a build. -**Format:** -```sh -npm run format:check # check -npm run format:fix # fix -``` +**Fixture dependencies are isolated:** Each `fixtures//` app is a self-contained package with its own `node_modules`. `npm install` at the repo root does not install fixture deps. Run `npm run install:fixtures` after adding or changing fixture dependencies. -**Requirements:** Node.js ≥ 20, npm. +**Test startup is slow:** Each test file starts a real Harper instance and waits up to 2 minutes for Next.js to build. This is expected — do not assume a hanging test is broken. -## Module System Notes +**Tests run sequentially within a file, parallel across files.** See [CONTRIBUTING.md#testing](./CONTRIBUTING.md#testing) for structure and how to add a new test file. -`.cts` marks a file as CommonJS. This is required for `withHarper.cts` and `CacheHandler.cts` because Next.js config files use CommonJS resolution. `plugin.ts` stays ESM since it is loaded only by Harper's runtime. Do not change file extensions without understanding this distinction. +## Failure Surface -## Testing +**Do not rename or re-extension source files** without updating `tsconfig.build.json`, `config.yaml`, and any import paths. The ESM/CJS split is load-order-sensitive; getting it wrong produces silent runtime failures, not build errors. -See [CONTRIBUTING.md#testing](./CONTRIBUTING.md#testing) for the full testing guide. Tests are Playwright integration tests that run against real Harper instances using `@harperfast/integration-testing` for lifecycle management. +**`npm run install:fixtures` must re-run after any fixture `package.json` change.** If tests fail with module-not-found errors inside a fixture, this is the likely cause. -**Setup (once, and after updating fixture deps):** -```sh -npm run install:fixtures -``` +**The ISR cache tests in `integrationTests/next-16.pw.ts` are intentionally skipped.** `CacheHandler.cts` is a work in progress. Do not remove the `.skip` without verifying the implementation is complete. -**Run all tests:** -```sh -npm run test:integration -``` +**CI is currently disabled** (`if: false` on the matrix job in `.github/workflows/integration-tests.yml`). Tests must be run locally. -**Run a specific test file:** -```sh -npm run test:integration -- integrationTests/next-15.pw.ts -``` - -### How Tests Are Structured - -Each test file maps to one fixture. The `fixture()` helper in `integrationTests/fixture.ts` starts Harper with the named fixture, exposes `harper`, `page`, and `request` to every test, then tears down Harper when the file finishes. Tests within a file run **sequentially**; separate test files run **in parallel** across Playwright workers. - -Each test callback may receive: -- **`harper`** — `HarperContext` from `@harperfast/integration-testing` (includes `harper.httpURL`, `harper.operationsAPIURL`) -- **`page`** — Playwright `Page` for browser-based assertions -- **`request`** — Playwright `APIRequestContext` for raw HTTP calls - -### Adding a New Test File - -1. Create a fixture app in `fixtures//` with the plugin installed and configured (see existing fixtures for reference). -2. Run `npm run install:fixtures` to install its dependencies. -3. Create `integrationTests/.pw.ts`: - -```ts -import { fixture } from './fixture.ts'; - -const { test, expect } = fixture(''); - -test('home page renders', async ({ page, harper }) => { - await page.goto(harper.httpURL); - await expect(page.locator('h1')).toHaveText('Expected heading'); -}); - -test('health endpoint returns 200', async ({ request, harper }) => { - const response = await request.get(`${harper.operationsAPIURL}/health`); - expect(response.status()).toBe(200); -}); -``` - -## Key Source Files - -**`src/plugin.ts`** — Harper plugin implementation. Handles the full Next.js application lifecycle: config resolution, build (version-specific for v14/15/16), serving via Harper's HTTP middleware, dev mode with HMR, and build info tracking to avoid redundant rebuilds across threads. Reads `HARPER_NEXTJS_MODE` env var (`dev` / `build` / `prod`). - -**`src/withHarper.cts`** — Wraps user's Next.js config. Adds `harper`, `harper-pro`, and `harperdb` to `serverExternalPackages` so Harper's native dependencies are excluded from bundling. Optionally enables ISR caching via `experimentalHarperCache: true`. - -**`src/CacheHandler.cts`** — Implements Next.js `CacheHandler` interface. Stores ISR cached page data in Harper's `harperfast_nextjs.nextjs_isr_cache` table instead of the filesystem, making cached pages available across all nodes in a Harper cluster. - -## Database Schema - -Defined in `schema.graphql`, used by `harperfast_nextjs` database: - -- **`NextBuildInfo`** — tracks build state per app (`appName` PK, `buildId`, `status`) -- **`NextISRCache`** — stores ISR cache entries (`id` PK, `data`, `lastModified` auto-updated) - -## Environment Variables - -| Variable | Description | -|----------|-------------| -| `HARPER_NEXTJS_MODE` | Plugin mode: `dev` (HMR), `build` (build-only, then exit), `prod` (default) | -| `HARPER_INTEGRATION_TEST_LOG_DIR` | If set, Harper test logs are written here (used in CI) | - -## CI - -The GitHub Actions workflow (`.github/workflows/integration-tests.yml`) runs integration tests on push to `main` and on pull requests. It installs dependencies, builds, installs fixture dependencies, installs Playwright browsers, and runs the full test suite. Playwright traces and Harper logs are uploaded as artifacts on failure. - -> Note: CI jobs are currently disabled (`if: false`). When re-enabling, set the matrix job condition back to `true`. +**`dist/` is gitignored.** It is not committed and not published from the repo directly — it is built as part of the publish step. From c0ca073eddc5e99d1ab7ad53f48d5ca53435467b Mon Sep 17 00:00:00 2001 From: Ethan Arrowood Date: Mon, 27 Apr 2026 20:08:20 -0600 Subject: [PATCH 3/4] docs: simplify AGENTS.md to match integration-testing format Co-Authored-By: Claude Sonnet 4.6 --- AGENTS.md | 58 +++++++++++++++++++------------------------------------ 1 file changed, 20 insertions(+), 38 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 14b356d..1379e38 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,38 +1,20 @@ -# Agent Guidelines: @harperfast/nextjs - -## Autonomous Actions - -Run freely without confirmation: -- `npm run build` -- `npm run format:fix` -- `npm run install:fixtures` -- `npm run test:integration` (and with `-- ` to target one file) - -Ask before doing: -- Modifying fixture `package.json` files or their installed dependencies -- Changing `schema.graphql` or `config.yaml` -- Touching anything in `dist/` (it's compiled output — change the source) - -## Operational Grounding - -**Module system:** The repo is `"type": "module"` (ESM), but `src/withHarper.cts` and `src/CacheHandler.cts` must be CommonJS because Next.js config files require CJS resolution. The `.cts` extension enforces this. `src/plugin.ts` is ESM and is **not compiled** — Harper loads it directly via Node's type-stripping. Do not change file extensions. - -**Build output:** Only `.cts` files compile to `dist/cjs/`. After editing `src/withHarper.cts` or `src/CacheHandler.cts`, run `npm run build` before testing. Editing `src/plugin.ts` takes effect immediately without a build. - -**Fixture dependencies are isolated:** Each `fixtures//` app is a self-contained package with its own `node_modules`. `npm install` at the repo root does not install fixture deps. Run `npm run install:fixtures` after adding or changing fixture dependencies. - -**Test startup is slow:** Each test file starts a real Harper instance and waits up to 2 minutes for Next.js to build. This is expected — do not assume a hanging test is broken. - -**Tests run sequentially within a file, parallel across files.** See [CONTRIBUTING.md#testing](./CONTRIBUTING.md#testing) for structure and how to add a new test file. - -## Failure Surface - -**Do not rename or re-extension source files** without updating `tsconfig.build.json`, `config.yaml`, and any import paths. The ESM/CJS split is load-order-sensitive; getting it wrong produces silent runtime failures, not build errors. - -**`npm run install:fixtures` must re-run after any fixture `package.json` change.** If tests fail with module-not-found errors inside a fixture, this is the likely cause. - -**The ISR cache tests in `integrationTests/next-16.pw.ts` are intentionally skipped.** `CacheHandler.cts` is a work in progress. Do not remove the `.skip` without verifying the implementation is complete. - -**CI is currently disabled** (`if: false` on the matrix job in `.github/workflows/integration-tests.yml`). Tests must be run locally. - -**`dist/` is gitignored.** It is not committed and not published from the repo directly — it is built as part of the publish step. +# AGENTS.md + +Review the `README.md` and `CONTRIBUTING.md` for all relevant repository information. + +## Development Tips +- Use `npm run build` to compile `src/withHarper.cts` and `src/CacheHandler.cts` to `dist/`. `src/plugin.ts` is not compiled — Harper loads it directly. +- Do not edit files in `dist/`; it is compiled output and gitignored. +- Do not run `npm version` or `npm publish`; these commands are for humans only. +- The `.cts` extension is intentional and load-order-sensitive. Do not change file extensions in `src/`. + +## Code Style +- Use Prettier for formatting: `npm run format:fix` +- `src/plugin.ts` is ESM. `src/withHarper.cts` and `src/CacheHandler.cts` are CommonJS (required by Next.js config resolution). Keep them that way. + +## Testing Tips +- Run `npm run install:fixtures` before running tests for the first time, and again after changing any fixture's `package.json`. +- Run `npm run test:integration` to run all tests, or `npm run test:integration -- integrationTests/next-15.pw.ts` for a single file. +- Test startup is slow by design — each test file starts a real Harper instance and waits for Next.js to build (up to 2 minutes). A slow start is not a failure. +- The ISR cache tests in `integrationTests/next-16.pw.ts` are intentionally skipped; `CacheHandler.cts` is a work in progress. +- CI is currently disabled (`if: false` in `.github/workflows/integration-tests.yml`). Run tests locally. From 7ec52e14579ff3f01477c2e9ab02b482705a3bc1 Mon Sep 17 00:00:00 2001 From: Ethan Arrowood Date: Mon, 27 Apr 2026 20:15:04 -0600 Subject: [PATCH 4/4] okay ai sucks at this --- AGENTS.md | 4 +++- CONTRIBUTING.md | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 1379e38..f0f2174 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,7 +3,8 @@ Review the `README.md` and `CONTRIBUTING.md` for all relevant repository information. ## Development Tips -- Use `npm run build` to compile `src/withHarper.cts` and `src/CacheHandler.cts` to `dist/`. `src/plugin.ts` is not compiled — Harper loads it directly. +- Use `npm install` to install dependencies +- Use `npm run build` to build the project files - Do not edit files in `dist/`; it is compiled output and gitignored. - Do not run `npm version` or `npm publish`; these commands are for humans only. - The `.cts` extension is intentional and load-order-sensitive. Do not change file extensions in `src/`. @@ -13,6 +14,7 @@ Review the `README.md` and `CONTRIBUTING.md` for all relevant repository informa - `src/plugin.ts` is ESM. `src/withHarper.cts` and `src/CacheHandler.cts` are CommonJS (required by Next.js config resolution). Keep them that way. ## Testing Tips +- Use `npm link` in this directory and `npm link @harperfast/nextjs` in other project directories to test out changes locally - Run `npm run install:fixtures` before running tests for the first time, and again after changing any fixture's `package.json`. - Run `npm run test:integration` to run all tests, or `npm run test:integration -- integrationTests/next-15.pw.ts` for a single file. - Test startup is slow by design — each test file starts a real Harper instance and waits for Next.js to build (up to 2 minutes). A slow start is not a failure. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 68d3158..330af79 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,9 +10,7 @@ The key source files are: - `schema.graphql` — the plugin table schemas - `config.yaml` — Harper configuration for the plugin -The `.cts` extension marks files as CommonJS, which is required because Next.js config files (`next.config.js`, `next.config.mjs`, `next.config.ts`) all use CommonJS module resolution. `plugin.ts` stays as ESM since it is only loaded by Harper's own runtime. - -Run `npm run build` to compile `src/withHarper.cts` and `src/CacheHandler.cts` to `dist/cjs/`. The `src/plugin.ts` file is not compiled — Harper loads it directly using Node's type-stripping support. +Run `npm run build` to compile the `src/` directory. The `.cts` extension marks files as CommonJS, which is required because Next.js config files (`next.config.js`, `next.config.mjs`, `next.config.ts`) all use CommonJS module resolution. `plugin.ts` stays as ESM since it is only loaded by Harper's own runtime. The published module includes `dist/`, `config.yaml`, and `schema.graphql`.