Skip to content
Closed
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
237de51
poc
notrab Jan 19, 2026
9045cc6
dummy preview page
notrab Jan 19, 2026
cc5f236
fix new line
notrab Jan 19, 2026
ddc8bf6
fmt new spec
notrab Jan 19, 2026
9da0a88
update readme for docs site
notrab Jan 20, 2026
3ae1447
Apply suggestions from code review
notrab Jan 20, 2026
61b4438
move generator file
notrab Jan 20, 2026
06c49c5
remove local dev env arg
notrab Jan 20, 2026
66e4b1e
update ci check
notrab Jan 20, 2026
30dff75
lint
notrab Jan 20, 2026
67ff063
fix frozen lock
notrab Jan 20, 2026
c75e78f
lint spec
notrab Jan 20, 2026
aaf1a73
update readme
notrab Jan 20, 2026
80f06e0
add colored diff
notrab Jan 21, 2026
630309f
test diff
notrab Jan 21, 2026
ab5927b
lint
notrab Jan 21, 2026
fa0119d
revert
notrab Jan 21, 2026
bdca6ea
readme
notrab Jan 21, 2026
fac4754
deploy switch
notrab Jan 21, 2026
1973ef6
run the openapi-check
notrab Jan 23, 2026
911bc3c
add changeset
notrab Jan 23, 2026
f1dd11d
continue-on-error
notrab Jan 23, 2026
b1cea1a
update readme structure
notrab Jan 23, 2026
323e565
Merge branch 'main' into openapi-spec-generator
notrab Jan 23, 2026
98bece8
update spec
notrab Jan 23, 2026
f493d51
announce mintlify errors in slack
notrab Jan 25, 2026
3945545
retry on transient errors
notrab Jan 25, 2026
a16f9eb
rename environment variable
notrab Jan 25, 2026
7ad6563
update wording
notrab Jan 25, 2026
91dfe3c
make right config types
notrab Jan 25, 2026
600294a
remove mintlify comment
notrab Jan 25, 2026
21b72af
update readme variable secret comment
notrab Jan 25, 2026
bba27af
add node types
notrab Jan 25, 2026
692a119
update preview text
notrab Jan 25, 2026
b640ca9
rename types
notrab Jan 25, 2026
16a641f
update mintlify deploy failed comment
notrab Jan 25, 2026
87c5180
replace mock databaseurl for openapi generation
notrab Jan 25, 2026
ac91cff
check server readiness
notrab Jan 25, 2026
4e11eb8
update openapi.json
notrab Jan 25, 2026
8ac20f5
update docs
notrab Jan 25, 2026
83ae0ba
apply coderabbit suggestion
notrab Jan 25, 2026
f7d7031
Merge branch 'main' into openapi-spec-generator
notrab Jan 28, 2026
0d1d1d5
revert to simpler times
notrab Jan 28, 2026
367c991
tidy
notrab Jan 28, 2026
ffb49ae
EnsApiConfigInput
notrab Jan 28, 2026
1a94122
add openapi mock config
notrab Jan 28, 2026
5d7e8ee
apply coderabbit suggestions
notrab Feb 1, 2026
e59fb6f
Merge branch 'main' into openapi-spec-generator
notrab Feb 1, 2026
4037d9f
update openapi.json
notrab Feb 1, 2026
9d1bf2a
update openapi.json
notrab Feb 1, 2026
5cade8d
update readme
notrab Feb 1, 2026
5965d3f
timeout check
notrab Feb 1, 2026
f287094
print parse error
notrab Feb 1, 2026
42a19d0
add docstring for openapi-generator
notrab Feb 1, 2026
731b4fe
Update docs/docs.ensnode.io/scripts/generate-openapi.ts
notrab Feb 1, 2026
690b155
Update .github/workflows/test_ci.yml
notrab Feb 1, 2026
09bf81d
Update .github/workflows/deploy_switch_ensnode_environment.yml
notrab Feb 1, 2026
546d0f4
Update apps/ensapi/src/config/openapi-mock-config.ts
notrab Feb 1, 2026
e82231a
apply suggestions from coderabbit and vercel
notrab Feb 1, 2026
a5ed508
exit trap
notrab Feb 2, 2026
ab00660
apply vercel ai code suggestions
notrab Feb 2, 2026
57261ce
Merge branch 'main' into openapi-spec-generator
notrab Feb 2, 2026
6bd4d09
fix lock
notrab Feb 2, 2026
419468c
log invalid value
notrab Feb 2, 2026
e14ef97
Update .changeset/gentle-clouds-dance.md
notrab Feb 3, 2026
32ea6a4
Update docs/docs.ensnode.io/README.md
notrab Feb 3, 2026
76cab69
Update docs/docs.ensnode.io/README.md
notrab Feb 3, 2026
3d37753
Apply suggestions from code review
notrab Feb 3, 2026
41c95b2
mintlify status check
notrab Feb 3, 2026
c69b37a
apply code suggestions
notrab Feb 3, 2026
cf0fc54
add script for generate openapi spec
notrab Feb 9, 2026
5d563ea
update slack msg
notrab Feb 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions .github/workflows/test_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,46 @@
- uses: ./.github/actions/setup_node_environment
- run: pnpm test

openapi-sync-check:
name: "OpenAPI Spec Sync Check"
runs-on: blacksmith-4vcpu-ubuntu-2204
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup_node_environment

- name: Start ENSApi in OpenAPI CI check mode
run: |
OPENAPI_CI_CHECK=true pnpm --filter ensapi start &
# Wait for server to be ready
for i in {1..30}; do
if curl -s http://localhost:4334/openapi.json > /dev/null 2>&1; then
echo "ENSApi is ready"
break
fi
echo "Waiting for ENSApi to start... ($i/30)"
sleep 1
done

- name: Generate OpenAPI spec from local build
working-directory: docs/docs.ensnode.io
run: pnpm openapi:generate http://localhost:4334

- name: Verify OpenAPI spec matches committed version
run: |
if git diff --quiet docs/docs.ensnode.io/openapi.json; then
echo "✅ OpenAPI spec is in sync with codebase"
else
echo "❌ OpenAPI spec is out of sync"
echo ""
echo "The committed openapi.json differs from what ENSApi generates:"
echo ""
git diff --color docs/docs.ensnode.io/openapi.json
echo ""
echo "Run 'OPENAPI_CI_CHECK=true pnpm --filter ensapi start' then 'pnpm --filter @docs/mintlify openapi:generate http://localhost:4334' and commit the changes."
Copy link
Member

Choose a reason for hiding this comment

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

Why all of these commands? Don't they just need to run openapi:generate http://localhost:4334 and commit?

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah they're needed, but I'll improve the formatting here. We need to start ensapi, then run the generator.

exit 1
fi

integrity-check:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium test

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
name: "Integrity Check"
runs-on: blacksmith-4vcpu-ubuntu-2204
services:
Expand Down
55 changes: 55 additions & 0 deletions apps/ensapi/src/config/config.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,68 @@ const EnsApiConfigSchema = z

export type EnsApiConfig = z.infer<typeof EnsApiConfigSchema>;

const EnsApiConfigSchemaForOpenApiCiCheck = z.object({
port: PortSchema.default(ENSApi_DEFAULT_PORT),
databaseUrl: DatabaseUrlSchema,
databaseSchemaName: DatabaseSchemaNameSchema,
ensIndexerUrl: EnsIndexerUrlSchema,
theGraphApiKey: TheGraphApiKeySchema,
namespace: ENSNamespaceSchema,
rpcConfigs: RpcConfigsSchema,
ensIndexerPublicConfig: makeENSIndexerPublicConfigSchema("ensIndexerPublicConfig"),
ensHolidayAwardsStart: z.number(),
ensHolidayAwardsEnd: z.number(),
});

function buildConfigForOpenApiCiCheck(env: EnsApiEnvironment): EnsApiConfig {
logger.info("OPENAPI_CI_CHECK mode enabled - using minimal mock config");

return EnsApiConfigSchemaForOpenApiCiCheck.parse({
port: env.PORT || ENSApi_DEFAULT_PORT,
databaseUrl: "postgresql://openapi:openapi@localhost:5432/openapi",
databaseSchemaName: "public",
ensIndexerUrl: "http://localhost:42069",
theGraphApiKey: undefined,
namespace: "mainnet",
rpcConfigs: {
"1": "https://rpc.example.com",
},
ensIndexerPublicConfig: {
labelSet: {
labelSetId: "ens-default",
labelSetVersion: 1,
},
indexedChainIds: [1],
isSubgraphCompatible: false,
namespace: "mainnet",
plugins: ["subgraph"],
databaseSchemaName: "public",
versionInfo: {
nodejs: process.version,
ponder: "0.0.0",
ensDb: packageJson.version,
ensIndexer: packageJson.version,
ensNormalize: "0.0.0",
ensRainbow: packageJson.version,
ensRainbowSchema: 1,
},
},
ensHolidayAwardsStart: getUnixTime(new Date(ENS_HOLIDAY_AWARDS_START_DATE)),
ensHolidayAwardsEnd: getUnixTime(new Date(ENS_HOLIDAY_AWARDS_END_DATE)),
}) as EnsApiConfig;
}

/**
* Builds the EnsApiConfig from an EnsApiEnvironment object, fetching the EnsIndexerPublicConfig.
*
* @returns A validated EnsApiConfig object
* @throws Error with formatted validation messages if environment parsing fails
*/
export async function buildConfigFromEnvironment(env: EnsApiEnvironment): Promise<EnsApiConfig> {
if (env.OPENAPI_CI_CHECK === "true") {
return buildConfigForOpenApiCiCheck(env);
}

try {
const ensIndexerUrl = EnsIndexerUrlSchema.parse(env.ENSINDEXER_URL);

Expand Down
4 changes: 3 additions & 1 deletion apps/ensapi/src/config/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ export type EnsApiEnvironment = Omit<DatabaseEnvironment, "DATABASE_SCHEMA"> &
PortEnvironment &
LogLevelEnvironment &
TheGraphEnvironment &
EnsHolidayAwardsEnvironment;
EnsHolidayAwardsEnvironment & {
OPENAPI_CI_CHECK?: string;
Copy link
Member

Choose a reason for hiding this comment

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

All environment variables must always be fully documented (up to a high standard) in apps/ensapi/.env.local.example

};
2 changes: 1 addition & 1 deletion apps/ensapi/src/handlers/ensanalytics-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const app = factory
.get(
"/referrers",
describeRoute({
tags: ["ENSAwards"],
tags: ["ENSAwardsssss"],
summary: "Get Referrer Leaderboard",
description: "Returns a paginated page from the referrer leaderboard",
responses: {
Expand Down
60 changes: 44 additions & 16 deletions docs/docs.ensnode.io/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,61 @@

[docs.ensnode.io](https://docs.ensnode.io) runs on [Mintlify](https://mintlify.com).

## Local Development
Learn more about [ENSNode](https://ensnode.io) from [the "Starlight" ENSNode docs](https://ensnode.io/docs/). Everything from these "Starlight" docs is planned to be transitioned into these Mintlify docs soon.
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider splitting the long introductory sentence for readability.

This line is quite long. A line break or splitting into two sentences would improve readability in raw Markdown.

🤖 Prompt for AI Agents
In `@docs/docs.ensnode.io/README.md` at line 5, Split the long introductory
sentence "Learn more about [ENSNode](https://ensnode.io) from [the "Starlight"
ENSNode docs](https://ensnode.io/docs/). Everything from these "Starlight" docs
is planned to be transitioned into these Mintlify docs soon." into two shorter
sentences or insert a line break after the first clause so it reads as a brief
invitation (e.g., "Learn more about ENSNode from the 'Starlight' ENSNode docs."
followed by the transitional sentence about migrating content into Mintlify
docs); update the README.md entry containing that exact sentence accordingly for
improved raw Markdown readability.


### Getting Started
## API Docs

This Mintlify site serves two (potentially distinct) sets of API docs from two sources:

| Section | Source | Purpose |
| -------------------- | ------------------ | ------------------------------------------- |
| **API Reference** | Production API URL | Always reflects the live deployed API |
| **Preview** (hidden) | `./openapi.json` | PR preview deployments for upcoming changes |

When you change API routes or schemas, update the committed `openapi.json` to preview changes in Mintlify's PR deployments.

## OpenAPI Spec Management

We use a combination of runtime URLs and committed files to keep API docs in sync across environments. This setup achieves:

1. Clone the repository:
- Production API docs match the production deployment, even when production lags behind `main`
- Non-API docs stay in sync with `main` through normal Git flow
- Each branch has its own `openapi.json`, validated by the CI to be in sync with the `openapi.json` that would actually be returned by the code for ENSApi in the same branch.
- PR previews show upcoming API changes before merge

```bash
git clone https://github.com/namehash/ensnode.git
```
### Generating the Spec

2. Navigate to the docs directory:
To generate the OpenAPI spec, you need a running ENSApi instance. For local development without external dependencies, use the `OPENAPI_CI_CHECK` mode:

```bash
cd ensnode/docs/docs.ensnode.io
```
```bash
# Start ENSApi in CI check mode (no external dependencies required)
OPENAPI_CI_CHECK=true pnpm --filter ensapi start

3. Start the local development server:
# In another terminal, generate the spec
pnpm --filter docs.ensnode.io openapi:generate http://localhost:4334
```
Comment on lines +46 to +52
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Clarify the working directory for the generation script.

The "Generating the Spec" section follows the "Local Development" section which instructs cd docs/docs.ensnode.io. The script path ./.github/scripts/generate_openapi_spec.sh is relative to the repository root, not the docs directory. A reader following the README top-to-bottom may already be in the docs/docs.ensnode.io directory.

Consider adding a note like "Run from the repository root:" above the code block to prevent confusion.

🤖 Prompt for AI Agents
In `@docs/docs.ensnode.io/README.md` around lines 46 - 52, Update the "Generating
the Spec" section so it's explicit which working directory to use: add a short
note (e.g., "Run from the repository root:") immediately above the code block
referencing ./ .github/scripts/generate_openapi_spec.sh, or change the
invocation to an absolute/root-relative form that clearly runs from repo root;
ensure the script name generate_openapi_spec.sh is unchanged and the code block
shows the correct command to run from the repository root.


```bash
pnpm mint dev
```
The URL argument is required — there is no default to avoid accidentally generating from the wrong source.

### CI Validation

CI runs an `openapi-sync-check` job that starts ENSApi in `OPENAPI_CI_CHECK` mode and compares the generated spec against the committed `openapi.json`. If they differ, the check fails.

Update the committed spec when you've changed API routes or schemas.

## Local Development

### Getting Started

1. `git clone https://github.com/namehash/ensnode.git`
2. `cd docs/docs.ensnode.io`
3. `pnpm mint dev`
4. Open [http://localhost:3000](http://localhost:3000) in your browser

### Troubleshooting

- If a page loads as a 404, make sure you are running in a folder with a valid `docs.json`.
- Run `pnpm mint --help` to read more details about Mintlify CLI.
- If a page loads as a 404, ensure you're running in a folder with a valid `docs.json`
- Run `pnpm mint --help` for more Mintlify CLI details

## Publishing Changes

Expand All @@ -38,3 +65,4 @@ Changes pushed to the main branch are automatically deployed to production.
## Resources

- [Mintlify documentation](https://mintlify.com/docs)
- [ENSNode "Starlight" docs](https://ensnode.io/docs/)
8 changes: 7 additions & 1 deletion docs/docs.ensnode.io/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@
},
{
"group": "API Reference",
"openapi": "https://gist.githubusercontent.com/notrab/94b637e77468cbddd895d7933ce88f64/raw/12cb5ed183558a9bdda5d1c7004db6c794dbd13e/green-ensnode-openapi.json"
"openapi": "https://api.alpha.ensnode.io/openapi.json"
},
{
"group": "Preview",
"pages": ["ensapi/preview"],
"openapi": "./openapi.json",
"hidden": true
Copy link
Member

Choose a reason for hiding this comment

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

Please update the description of this PR to include a section for post-merge follow-up actions. This needs to include the following goal:

  • Ensure that the "hidden" preview API docs remain truly hidden from search engines once we merge this PR. It's possible they are only hidden in preview environments but may not be hidden in production.

Copy link
Member Author

Choose a reason for hiding this comment

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

Noted. You can’t have a page only hidden in production but visible in previews using ‎hidden. I also don't think we need to wait for this support if they end up exposing an API to deploy a specific github sha, since we'd remove this "hidden" page, and reference the local file for all deployments (prod/previews) and then control what/when that is deployed in our switching action.

}
]
}
Expand Down
9 changes: 9 additions & 0 deletions docs/docs.ensnode.io/ensapi/preview.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
title: API Preview
sidebarTitle: Preview
description: Preview upcoming API changes from the current branch.
---

This page shows the OpenAPI specification from the current branch, which may include unreleased API changes.

For the production API documentation, see the [API Reference](/ensapi).
Loading
Loading