diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 70e646ddb..fe8f833ff 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -67,8 +67,8 @@ jobs:
with:
commit: "chore(release): version apps"
title: "Release New Version"
- version: pnpm changeset:version
- publish: pnpm changeset-publish
+ version: pnpm changeset:version && pnpm release:postversion
+ publish: pnpm changeset:publish
createGithubReleases: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/release_snapshot.yml b/.github/workflows/release_snapshot.yml
index 1842c00a0..44040a97e 100644
--- a/.github/workflows/release_snapshot.yml
+++ b/.github/workflows/release_snapshot.yml
@@ -83,7 +83,7 @@ jobs:
- name: Publish snapshot packages to NPM
if: steps.snapshot.outputs.hasChanges == 'true'
- run: pnpm changeset-publish:next
+ run: pnpm changeset:publish:next
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
diff --git a/README.md b/README.md
index 12dc0e6d8..1d92932c1 100644
--- a/README.md
+++ b/README.md
@@ -89,13 +89,9 @@ ENSNode is a modern, multichain indexer for ENS. It supports backwards-compatibl
Documentation for the ENSNode suite of apps is available at [ensnode.io](https://ensnode.io).
-## Running with Docker
+## Quickstart
-```bash
-docker compose -f docker/docker-compose.yml up -d
-```
-
-See [`docker/README.md`](docker/README.md) for all use cases and commands.
+Learn how to quickly get started with ENSNode through APIs (including Omnigraph), SDKs (`enssdk`), React components (`enskit`), and Docker Compose in the [ENSNode Quickstart Guide](https://ensnode.io/docs).
## Contributions
diff --git a/docker/README.md b/docker/README.md
index ac8e8f6ba..c7bbcf92d 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -1,90 +1,8 @@
# Docker Compose
-All commands are run from the **monorepo root**.
+ENSNode supports Docker Compose for local development and deployments.
-## Files
+For canonical setup, use cases, and commands, see the docs site:
-| File | Purpose |
-| ---------------------------------------- | -------------------------------------------------------------------------------------- |
-| `docker/docker-compose.yml` | Base stack — ensindexer, ensapi, ensrainbow, ensadmin, postgres. For mainnet/sepolia. |
-| `docker/docker-compose.devnet.yml` | Full stack against local devnet (`ens-test-env`). Includes all base services + devnet. |
-| `docker/docker-compose.orchestrator.yml` | Minimal infra for CI — devnet + postgres only. Used by `orchestrator.ts`. |
-| `docker/services/*.yml` | Individual service definitions. Extended by the compose files above. |
-| `docker/envs/.env.docker.common` | Shared env defaults (postgres credentials, internal service URLs). Committed. |
-| `docker/envs/.env.docker.devnet` | Devnet defaults (PLUGINS, etc.). Committed. Works out of the box. |
-| `docker/envs/.env.docker.example` | Example for user-specific config. Copy to `.env.docker.local` for mainnet/sepolia. |
-| `docker/envs/.env.docker.local` | User config (gitignored). Required for base stack, optional for devnet overrides. |
-
-> To inspect the fully resolved config for any compose file (resolves all `extends`):
->
-> ```
-> docker compose -f docker/docker-compose.yml config
-> ```
-
-## Use cases
-
-### Mainnet / Sepolia
-
-**1. Configure environment** (one-time setup):
-
-```bash
-cp docker/envs/.env.docker.example docker/envs/.env.docker.local
-```
-
-Edit `docker/envs/.env.docker.local` and set `NAMESPACE`, `PLUGINS`, and your RPC endpoints (e.g. `ALCHEMY_API_KEY` or `RPC_URL_1`).
-
-**2. Start/stop the stack:**
-
-```bash
-# Start full stack in background
-docker compose -f docker/docker-compose.yml up -d
-
-# Stop
-docker compose -f docker/docker-compose.yml down
-
-# Stop and remove volumes
-docker compose -f docker/docker-compose.yml down -v
-```
-
-### Local devnet (for developers)
-
-No setup required — devnet defaults are committed in `docker/envs/.env.docker.devnet`.
-
-To override defaults (e.g. change `PLUGINS`), create `docker/envs/.env.docker.local` with your values.
-
-```bash
-# Start full stack against devnet
-docker compose -f docker/docker-compose.devnet.yml up -d
-
-# Start only devnet + core services (no ensadmin)
-docker compose -f docker/docker-compose.devnet.yml up -d devnet postgres ensrainbow ensindexer ensapi
-
-# Start only devnet (quick local EVM node, also shows data information about devnet)
-docker compose -f docker/docker-compose.devnet.yml up devnet
-# or
-pnpm devnet
-
-# Stop
-docker compose -f docker/docker-compose.devnet.yml down
-```
-
-### Build images locally
-
-```bash
-# Build all images
-pnpm docker:build:ensnode
-
-# Build a specific image
-pnpm docker:build:ensindexer
-pnpm docker:build:ensapi
-pnpm docker:build:ensrainbow
-pnpm docker:build:ensadmin
-```
-
-### CI / integration tests
-
-Used internally by `orchestrator.ts` via testcontainers. Starts devnet + postgres only.
-
-```bash
-pnpm test:integration:ci
-```
+- [Deploying ENSNode with Docker](https://ensnode.io/docs/deploying/docker)
+- [ENSNode Quickstart](https://ensnode.io/docs)
diff --git a/docker/docker-compose.devnet.yml b/docker/docker-compose.devnet.yml
index 03bfb243c..5f2e60852 100644
--- a/docker/docker-compose.devnet.yml
+++ b/docker/docker-compose.devnet.yml
@@ -4,12 +4,6 @@ services:
file: services/ensindexer.yml
service: ensindexer
environment:
- # TODO: in future we will migrate devnet to chain_id=1
- # need to remove `RPC_URL_15658733` in that case
- RPC_URL_15658733: http://devnet:8545
- RPC_URL_1: http://devnet:8545
- ENSINDEXER_SCHEMA_NAME: docker_devnet_v1
- LABEL_SET_ID: ens-test-env
NAMESPACE: ens-test-env
env_file:
- path: envs/.env.docker.common
@@ -21,7 +15,7 @@ services:
depends_on:
ensrainbow:
condition: service_healthy
- postgres:
+ ensdb:
condition: service_healthy
devnet:
condition: service_healthy
@@ -30,14 +24,8 @@ services:
extends:
file: services/ensapi.yml
service: ensapi
- environment:
- # TODO: in future we will migrate devnet to chain_id=1
- # need to remove `RPC_URL_15658733` in that case
- RPC_URL_15658733: http://devnet:8545
- RPC_URL_1: http://devnet:8545
- ENSINDEXER_SCHEMA_NAME: docker_devnet_v1
depends_on:
- postgres:
+ ensdb:
condition: service_healthy
env_file:
- path: envs/.env.docker.common
@@ -51,8 +39,6 @@ services:
extends:
file: services/ensrainbow.yml
service: ensrainbow
- environment:
- LABEL_SET_ID: ens-test-env
env_file:
- path: envs/.env.docker.common
required: true
@@ -76,12 +62,12 @@ services:
- path: envs/.env.docker.local
required: false
- postgres:
+ ensdb:
extends:
- file: services/postgres.yml
- service: postgres
+ file: services/ensdb.yml
+ service: ensdb
env_file:
- - path: ./envs/.env.docker.common
+ - path: envs/.env.docker.common
required: true
devnet:
@@ -94,8 +80,8 @@ volumes:
# compose file that references them — they cannot be inherited via `extends`.
# Explicit `name:` prevents collision with the base stack's volumes when both
# are run from the same directory (same project name).
- postgres_data:
- name: ensnode_devnet_postgres_data
+ ensdb_data:
+ name: ensnode_devnet_ensdb_data
driver: local
ensrainbow_data:
name: ensnode_devnet_ensrainbow_data
diff --git a/docker/docker-compose.orchestrator.yml b/docker/docker-compose.orchestrator.yml
index e813e27f6..82290a79e 100644
--- a/docker/docker-compose.orchestrator.yml
+++ b/docker/docker-compose.orchestrator.yml
@@ -1,22 +1,22 @@
# Minimal compose for CI integration tests.
# Provides only the infrastructure services needed by orchestrator.ts:
-# devnet (local EVM) and postgres (database).
+# devnet (local EVM) and ensdb (database).
services:
devnet:
extends:
file: services/devnet.yml
service: devnet
- postgres:
+ ensdb:
extends:
- file: services/postgres.yml
- service: postgres
+ file: services/ensdb.yml
+ service: ensdb
env_file:
- - path: ./envs/.env.docker.common
+ - path: envs/.env.docker.common
required: true
volumes:
# Docker Compose requires volumes used by services to be declared in each
# compose file that references them — they cannot be inherited via `extends`.
- postgres_data:
+ ensdb_data:
driver: local
diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml
index 32bddab5d..ff095b3b6 100644
--- a/docker/docker-compose.yml
+++ b/docker/docker-compose.yml
@@ -8,7 +8,7 @@ services:
depends_on:
ensrainbow:
condition: service_healthy
- postgres:
+ ensdb:
condition: service_healthy
env_file:
- path: envs/.env.docker.common
@@ -24,7 +24,7 @@ services:
environment:
ENSINDEXER_SCHEMA_NAME: docker_ensindexer_v1
depends_on:
- postgres:
+ ensdb:
condition: service_healthy
env_file:
- path: envs/.env.docker.common
@@ -55,10 +55,10 @@ services:
- path: envs/.env.docker.local
required: true
- postgres:
+ ensdb:
extends:
- file: services/postgres.yml
- service: postgres
+ file: services/ensdb.yml
+ service: ensdb
env_file:
- path: envs/.env.docker.common
required: true
@@ -66,7 +66,7 @@ services:
volumes:
# Docker Compose requires volumes used by services to be declared in each
# compose file that references them — they cannot be inherited via `extends`.
- postgres_data:
+ ensdb_data:
driver: local
ensrainbow_data:
driver: local
diff --git a/docker/envs/.env.docker.common b/docker/envs/.env.docker.common
index d8c682539..1d8713c9e 100644
--- a/docker/envs/.env.docker.common
+++ b/docker/envs/.env.docker.common
@@ -1,16 +1,15 @@
# Shared Docker Compose environment variables
# Used by docker/docker-compose.yml and its variants
-
# Postgres
POSTGRES_DB=postgres
POSTGRES_USER=postgres
POSTGRES_PASSWORD=password
# Internal service URLs (container-to-container)
-ENSDB_URL=postgresql://postgres:password@postgres:5432/postgres
+ENSDB_URL=postgresql://postgres:password@ensdb:5432/postgres
ENSRAINBOW_URL=http://ensrainbow:3223
-# ENS Admin
+# ENSAdmin
ENSADMIN_PUBLIC_URL=http://localhost:4173
NEXT_PUBLIC_SERVER_CONNECTION_LIBRARY=http://localhost:4334
diff --git a/docker/envs/.env.docker.devnet b/docker/envs/.env.docker.devnet
index 7c63beef8..6efab20e2 100644
--- a/docker/envs/.env.docker.devnet
+++ b/docker/envs/.env.docker.devnet
@@ -1,6 +1,22 @@
# Default configuration for devnet docker-compose stack.
# These values work out of the box — override by creating .env.docker.local.
+# ENSIndexer
PLUGINS=subgraph,ensv2
+# ENSIndexer and ENSRainbow
+NAMESPACE=ens-test-env
+# ENSIndexer and ENSApi
+ENSINDEXER_SCHEMA_NAME=docker_devnet_v1
+# ENSIndexer and ENSApi
+RPC_URL_1=http://devnet:8545
+# ENSIndexer and ENSRainbow
LABEL_SET_VERSION=0
+# ENSIndexer and ENSRainbow
+LABEL_SET_ID=ens-test-env
+# ENSRainbow
DB_SCHEMA_VERSION=3
+
+
+# TODO: in future we will migrate devnet to chain_id=1
+# need to remove `RPC_URL_15658733` in that case
+RPC_URL_15658733=http://devnet:8545
diff --git a/docker/services/ensadmin.yml b/docker/services/ensadmin.yml
index fbc0fd542..8b7030d78 100644
--- a/docker/services/ensadmin.yml
+++ b/docker/services/ensadmin.yml
@@ -1,7 +1,7 @@
services:
ensadmin:
container_name: ensadmin
- image: ghcr.io/namehash/ensnode/ensadmin:latest
+ image: ghcr.io/namehash/ensnode/ensadmin:${ENSNODE_TAG:-1.10.1}
build:
dockerfile: ./apps/ensadmin/Dockerfile
context: ../..
diff --git a/docker/services/ensapi.yml b/docker/services/ensapi.yml
index 71ce5c7d3..8a28eedb4 100644
--- a/docker/services/ensapi.yml
+++ b/docker/services/ensapi.yml
@@ -1,7 +1,7 @@
services:
ensapi:
container_name: ensapi
- image: ghcr.io/namehash/ensnode/ensapi:latest
+ image: ghcr.io/namehash/ensnode/ensapi:${ENSNODE_TAG:-1.10.1}
build:
dockerfile: ./apps/ensapi/Dockerfile
context: ../..
diff --git a/docker/services/postgres.yml b/docker/services/ensdb.yml
similarity index 74%
rename from docker/services/postgres.yml
rename to docker/services/ensdb.yml
index 85f0f12b2..78554a630 100644
--- a/docker/services/postgres.yml
+++ b/docker/services/ensdb.yml
@@ -1,11 +1,11 @@
services:
- postgres:
- container_name: postgres
+ ensdb:
+ container_name: ensdb
image: postgres:17
ports:
- "5432:5432"
volumes:
- - postgres_data:/var/lib/postgresql/data
+ - ensdb_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 5s
diff --git a/docker/services/ensindexer.yml b/docker/services/ensindexer.yml
index ac472ddaf..360fe3ecf 100644
--- a/docker/services/ensindexer.yml
+++ b/docker/services/ensindexer.yml
@@ -1,7 +1,7 @@
services:
ensindexer:
container_name: ensindexer
- image: ghcr.io/namehash/ensnode/ensindexer:latest
+ image: ghcr.io/namehash/ensnode/ensindexer:${ENSNODE_TAG:-1.10.1}
build:
dockerfile: ./apps/ensindexer/Dockerfile
context: ../..
diff --git a/docker/services/ensrainbow.yml b/docker/services/ensrainbow.yml
index 5e1c3c726..ae4eebc18 100644
--- a/docker/services/ensrainbow.yml
+++ b/docker/services/ensrainbow.yml
@@ -1,7 +1,7 @@
services:
ensrainbow:
container_name: ensrainbow
- image: ghcr.io/namehash/ensnode/ensrainbow:latest
+ image: ghcr.io/namehash/ensnode/ensrainbow:${ENSNODE_TAG:-1.10.1}
build:
dockerfile: ./apps/ensrainbow/Dockerfile
context: ../..
diff --git a/docs/ensnode.io/src/content/docs/docs/contributing/index.mdx b/docs/ensnode.io/src/content/docs/docs/contributing/index.mdx
index 36f271bf2..43367ac7c 100644
--- a/docs/ensnode.io/src/content/docs/docs/contributing/index.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/contributing/index.mdx
@@ -166,7 +166,7 @@ For all available commands and configuration options, see the [Deploying with Do
### Stopping the Applications
-To stop the running applications, you can press `Ctrl + C` in the terminal where Docker Compose is running. To remove the containers and networks:
+To stop detached Docker Compose stacks and remove the containers and networks:
```bash
docker compose -f docker/docker-compose.yml down
diff --git a/docs/ensnode.io/src/content/docs/docs/deploying/docker.mdx b/docs/ensnode.io/src/content/docs/docs/deploying/docker.mdx
index 46196b1e2..7c2487daa 100644
--- a/docs/ensnode.io/src/content/docs/docs/deploying/docker.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/deploying/docker.mdx
@@ -9,37 +9,89 @@ import { LinkCard } from '@astrojs/starlight/components';
The Docker images are the easiest way to run or deploy the ENSNode suite of services, both locally and in the cloud.
+All commands below are run from the monorepo root.
+
:::note[Postgres Requirement]
ENSIndexer runs `CREATE EXTENSION IF NOT EXISTS pg_trgm` at startup to back partial-name search indexes. If you're swapping out the bundled `postgres:17` image for a managed or custom Postgres, make sure the [`pg_trgm`](https://www.postgresql.org/docs/current/pgtrgm.html) extension is available for installation (it ships with stock Postgres contrib and is available for installation on most managed providers).
:::
-
ENSNode provides several [Docker Compose](https://docs.docker.com/compose/) files for different use cases:
-- **`docker/docker-compose.yml`** — base stack for mainnet/sepolia: ensindexer, ensapi, ensrainbow, ensadmin, postgres
+- **`docker/docker-compose.yml`** — base stack for mainnet/sepolia: ensindexer, ensapi, ensrainbow, ensadmin, ensdb (postgres)
- **`docker/docker-compose.devnet.yml`** — full stack against local devnet (ens-test-env), works out of the box with no configuration required
+To inspect the fully resolved config for any compose file (resolves all `extends`):
+
+```bash
+docker compose -f docker/docker-compose.yml config
+```
+
+### Choosing `ENSNODE_TAG`
+
+`ENSNODE_TAG` controls which ENSNode image version is pulled for `ensindexer`, `ensapi`, `ensrainbow`, and `ensadmin`.
+
+- If `ENSNODE_TAG` is not set, compose files use the default tag baked into service definitions.
+- For reproducible environments, pin a specific release tag.
+- For quick local testing, you can override it temporarily from the shell.
+
+* One-off override for a single command.
+
+ ```bash
+ ENSNODE_TAG=1.10.1 docker compose -f docker/docker-compose.yml up -d
+ ```
+
+* Persistent override using `docker/.env`. Docker Compose picks it up automatically.
+ ```bash
+ echo "ENSNODE_TAG=1.10.1" >> docker/.env
+ docker compose -f docker/docker-compose.yml up -d
+ ```
+
+* Persistent override using `docker/envs/.env.docker.local`. Pass it explicitly with `--env-file`.
+ ```bash
+ echo "ENSNODE_TAG=1.10.1" >> docker/envs/.env.docker.local
+ docker compose --env-file docker/envs/.env.docker.local -f docker/docker-compose.yml up -d
+ ```
+
+* Persistent override using `export`.
+
+ ```bash
+ export ENSNODE_TAG=1.10.1
+ docker compose -f docker/docker-compose.yml up -d
+ ```
+
### Mainnet / Sepolia
-Copy the example env file and configure it:
+Copy the example env file and configure it (one-time setup):
```bash
cp docker/envs/.env.docker.example docker/envs/.env.docker.local
```
-Edit `docker/envs/.env.docker.local` to set your `NAMESPACE`, `PLUGINS`, and RPC endpoints (e.g. `ALCHEMY_API_KEY` or `RPC_URL_1`), then run:
+
+
+
+Edit `docker/envs/.env.docker.local` to set `NAMESPACE`, `PLUGINS`, and your RPC endpoints (for example `ALCHEMY_API_KEY` or `RPC_URL_1`), then run:
```bash
+# Start
docker compose -f docker/docker-compose.yml up -d
+
+# Stop
+docker compose -f docker/docker-compose.yml down
+
+# Stop and remove volumes
+docker compose -f docker/docker-compose.yml down -v
```
### Local devnet
+This stack is primarily intended for engineers developing ENS infrastructure and testing against a local chain.
+
Configuration is optional. To customize defaults (e.g. change `PLUGINS`), copy the example as in previous step and edit it.
Otherwise, skip setup and run directly:
@@ -48,12 +100,27 @@ Otherwise, skip setup and run directly:
docker compose -f docker/docker-compose.devnet.yml up -d
```
+To start only specific services:
-
+```bash
+# Devnet + core services (no ENSAdmin)
+# Useful when you do not need UI
+docker compose -f docker/docker-compose.devnet.yml up -d ensindexer ensapi
+
+# Devnet only
+# Useful when you want only a local EVM chain
+docker compose -f docker/docker-compose.devnet.yml up devnet
+
+# Or
+pnpm devnet
+```
+
+To stop stacks:
+
+```bash
+docker compose -f docker/docker-compose.yml down
+docker compose -f docker/docker-compose.devnet.yml down
+```
-## Using ENSNode with ensjs
+### Integrate with ENS Omnigraph API
-You can use ENSNode with ensjs by providing an ENSNode url in place of the subgraph url in viem's `Chain` object.
+Choose this if you need graphql API access and want to build directly against API responses. This guide will cover endpoints, response shapes, and integration patterns for backend services and data pipelines.
-```ts
-import { http, createClient } from "viem";
-import { mainnet } from "viem/chains";
-import { addEnsContracts } from "@ensdomains/ensjs";
-import { getSubgraphRecords } from "@ensdomains/ensjs/subgraph";
+
-const client = createClient({
- chain: {
- ...addEnsContracts(mainnet),
- subgraphs: { ens: { url: "https://api.alpha.ensnode.io/subgraph" } },
- },
- transport: http(),
-});
+### Integrate with `enssdk`
-const names = await getNamesForAddress(client, { name: "validator.eth" });
-```
+Choose this if you prefer a typed SDK experience for app integration. This guide will cover SDK setup, common query patterns, and recommended usage for production applications.
-See the following documentation for examples of how to query ENSNode from ensjs:
+
-
-## Using ENSNode's APIs
+### Integrate with `ensjs`
-For querying ENSNode via its **GraphQL** API, refer to the following documentation:
+Choose this if your app already uses `ensjs` and you want minimal migration effort. This guide explains how to point `ensjs` to ENSNode's subgraph-compatible endpoint and keep familiar `ensjs` query workflows.
-
+
-## Using ENSNode with `viem/chain`
+### Integrate with `enskit`
-If you're integrating with a library that retrieves the url for the ENS Subgraph in a provided `viem/chain` object, see the following documentation for integration.
+Choose this if you are building UI-heavy apps and want reusable ENS-focused components/hooks. This guide will cover how to wire ENSNode-backed data into frontend flows with minimal boilerplate.
-
+
+
+### Integrate through `viem/chain`
+
+Choose this if your tooling expects ENS endpoints via `viem` chain configuration. This guide explains how to configure `viem/chain` objects so ENS-aware libraries can consume ENSNode seamlessly.
+
+
+
+### Run your own ENSNode
+
+Choose this if you need production ownership of uptime, data freshness strategy, and infrastructure. This guide compares deployment options (Docker, Render, Terraform) and links to the setup steps for each path.
+
+
diff --git a/docs/ensnode.io/src/content/docs/docs/usage/api.mdx b/docs/ensnode.io/src/content/docs/docs/usage/api.mdx
index 878dc5bfc..61d9d66d9 100644
--- a/docs/ensnode.io/src/content/docs/docs/usage/api.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/usage/api.mdx
@@ -2,7 +2,7 @@
title: Using ENSNode's API
sidebar:
label: ENSNode's API
- order: 3
+ order: 7
---
import { LinkCard } from "@astrojs/starlight/components";
diff --git a/docs/ensnode.io/src/content/docs/docs/usage/omnigraph-api.mdx b/docs/ensnode.io/src/content/docs/docs/usage/omnigraph-api.mdx
new file mode 100644
index 000000000..6e08b7dca
--- /dev/null
+++ b/docs/ensnode.io/src/content/docs/docs/usage/omnigraph-api.mdx
@@ -0,0 +1,8 @@
+---
+title: ENS Omnigraph API
+sidebar:
+ label: Omnigraph API
+ order: 2
+---
+
+TBD
diff --git a/docs/ensnode.io/src/content/docs/docs/usage/with-ensjs.mdx b/docs/ensnode.io/src/content/docs/docs/usage/with-ensjs.mdx
index cf57b4d34..ba6ed8d6d 100644
--- a/docs/ensnode.io/src/content/docs/docs/usage/with-ensjs.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/usage/with-ensjs.mdx
@@ -2,7 +2,7 @@
title: Using ENSNode with ENSjs
sidebar:
label: Using with ENSjs
- order: 1
+ order: 4
---
import { LinkCard } from '@astrojs/starlight/components';
diff --git a/docs/ensnode.io/src/content/docs/docs/usage/with-enskit.mdx b/docs/ensnode.io/src/content/docs/docs/usage/with-enskit.mdx
new file mode 100644
index 000000000..4dbff5288
--- /dev/null
+++ b/docs/ensnode.io/src/content/docs/docs/usage/with-enskit.mdx
@@ -0,0 +1,8 @@
+---
+title: Using ENSNode with enskit
+sidebar:
+ label: Using with enskit
+ order: 5
+---
+
+TBD
diff --git a/docs/ensnode.io/src/content/docs/docs/usage/with-enssdk.mdx b/docs/ensnode.io/src/content/docs/docs/usage/with-enssdk.mdx
new file mode 100644
index 000000000..fce7b6dfb
--- /dev/null
+++ b/docs/ensnode.io/src/content/docs/docs/usage/with-enssdk.mdx
@@ -0,0 +1,8 @@
+---
+title: Using ENSNode with enssdk
+sidebar:
+ label: Using with enssdk
+ order: 3
+---
+
+TBD
diff --git a/docs/ensnode.io/src/content/docs/docs/usage/with-viem.mdx b/docs/ensnode.io/src/content/docs/docs/usage/with-viem.mdx
index 36f2d72f2..acc8981c2 100644
--- a/docs/ensnode.io/src/content/docs/docs/usage/with-viem.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/usage/with-viem.mdx
@@ -2,7 +2,7 @@
title: Using ENSNode with `viem/chain`
sidebar:
label: Using with viem/chain
- order: 4
+ order: 6
---
Some libraries (for example, `ENSjs`) use a `viem/chain` object to identify the ENS Subgraph url. If you're integrating with a library that expects a url in the `subgraph` key for your chain, you can update the `Chain` spec to use ENSNode like so:
diff --git a/package.json b/package.json
index 7b643b296..e4becc98f 100644
--- a/package.json
+++ b/package.json
@@ -12,20 +12,23 @@
"audit:osv": "osv-scanner scan source --lockfile pnpm-lock.yaml",
"typecheck": "pnpm -r --parallel --aggregate-output typecheck",
"changeset": "changeset",
- "changeset:version": "changeset version && pnpm generate:openapi",
+ "changeset:version": "changeset version",
"changeset:next": "changeset version --snapshot next && pnpm generate:openapi",
- "changeset-publish": "changeset publish",
- "changeset-publish:next": "changeset publish --no-git-tag --snapshot --tag next",
+ "changeset:publish": "changeset publish",
+ "changeset:publish:next": "changeset publish --no-git-tag --snapshot --tag next",
+ "release:postversion": "pnpm docker:tag:sync && pnpm generate:openapi",
"packages:prepublish": "pnpm -r prepublish",
"devnet": "docker compose -f docker/docker-compose.devnet.yml up devnet",
"docker:build:ensnode": "pnpm run -w --parallel \"/^docker:build:.*/\"",
+ "docker:tag:sync": "node ./scripts/sync-docker-services-tags.mjs",
"docker:build:ensindexer": "docker build -f apps/ensindexer/Dockerfile -t ghcr.io/namehash/ensnode/ensindexer:latest .",
"docker:build:ensadmin": "docker build -f apps/ensadmin/Dockerfile -t ghcr.io/namehash/ensnode/ensadmin:latest .",
"docker:build:ensrainbow": "docker build -f apps/ensrainbow/Dockerfile -t ghcr.io/namehash/ensnode/ensrainbow:latest .",
"docker:build:ensapi": "docker build -f apps/ensapi/Dockerfile -t ghcr.io/namehash/ensnode/ensapi:latest .",
"otel-desktop-viewer": "docker run -p 8000:8000 -p 4317:4317 -p 4318:4318 davetron5000/otel-desktop-viewer:alpine-3",
"generate:openapi": "pnpm -r --if-present generate:openapi",
- "generate:gqlschema": "pnpm -F ensapi generate:gqlschema && pnpm -F enssdk generate:gqlschema"
+ "generate:gqlschema": "pnpm -F ensapi generate:gqlschema && pnpm -F enssdk generate:gqlschema",
+ "docs:dev": "pnpm -F @docs/ensnode dev"
},
"devDependencies": {
"@biomejs/biome": "^2.3.1",
diff --git a/packages/integration-test-env/src/orchestrator.ts b/packages/integration-test-env/src/orchestrator.ts
index 17e2a72d5..9b177eaae 100644
--- a/packages/integration-test-env/src/orchestrator.ts
+++ b/packages/integration-test-env/src/orchestrator.ts
@@ -5,14 +5,14 @@
* monorepo-level integration tests, then tears everything down.
*
* Phases:
- * 1. Postgres + devnet via docker-compose (testcontainers DockerComposeEnvironment)
+ * 1. ENSDb (postgres) + devnet via docker-compose (testcontainers DockerComposeEnvironment)
* 2. Download pre-built ENSRainbow LevelDB, extract, start ENSRainbow from source
* 3. Start ENSIndexer, wait for omnichain-following / omnichain-completed
* 4. Start ENSApi
* 5. Run `pnpm test:integration` at the monorepo root
*
* Design decisions:
- * - Postgres and devnet are started from docker/docker-compose.orchestrator.yml via
+ * - ENSDb (postgres) and devnet are started from docker/docker-compose.orchestrator.yml via
* testcontainers DockerComposeEnvironment, ensuring the orchestrator always
* uses the same images and configuration defined there.
* - execa for child process management — automatic cleanup on parent exit,
@@ -22,7 +22,7 @@
* - ENSRainbow database is downloaded via the existing shell script and
* extracted with tar, mirroring the Docker entrypoint behavior.
* - Cleanup stops processes in reverse order (ensapi → ensindexer → ensrainbow)
- * so DB consumers close connections before Postgres is stopped.
+ * so DB consumers close connections before ensdb is stopped.
* - Abort flag pattern: if a background service crashes during polling/health
* checks, the orchestrator fails fast instead of waiting for a timeout.
* - SIGINT/SIGTERM handler is guarded against re-entrance (repeated Ctrl-C).
@@ -237,21 +237,21 @@ async function main() {
log("Starting integration test environment...");
logVersions();
- // Phase 1: Start Postgres + Devnet via docker-compose
- log("Starting Postgres and devnet...");
+ // Phase 1: Start ENSDb + Devnet via docker-compose
+ log("Starting ENSDb and Devnet...");
composeEnvironment = await new DockerComposeEnvironment(
DOCKER_DIR,
"docker-compose.orchestrator.yml",
)
.withWaitStrategy("devnet", Wait.forHealthCheck())
- .withWaitStrategy("postgres", Wait.forListeningPorts())
+ .withWaitStrategy("ensdb", Wait.forListeningPorts())
.withStartupTimeout(120_000)
- .up(["postgres", "devnet"]);
+ .up(["ensdb", "devnet"]);
- const postgresContainer = composeEnvironment.getContainer("postgres");
- const postgresPort = postgresContainer.getMappedPort(5432);
- const ENSDB_URL = `postgresql://postgres:password@localhost:${postgresPort}/postgres`;
- log(`Postgres is ready (port ${postgresPort})`);
+ const ensdbContainer = composeEnvironment.getContainer("ensdb");
+ const ensdbPort = ensdbContainer.getMappedPort(5432);
+ const ENSDB_URL = `postgresql://postgres:password@localhost:${ensdbPort}/postgres`;
+ log(`ENSDb is ready (port ${ensdbPort})`);
log("Devnet is ready");
// Phase 2: Download ENSRainbow database and start from source
diff --git a/scripts/sync-docker-services-tags.mjs b/scripts/sync-docker-services-tags.mjs
new file mode 100644
index 000000000..a2ec80d52
--- /dev/null
+++ b/scripts/sync-docker-services-tags.mjs
@@ -0,0 +1,63 @@
+import { readFile, writeFile } from "node:fs/promises";
+import { resolve } from "node:path";
+
+const rootDir = resolve(import.meta.dirname, "..");
+
+const serviceFiles = [
+ "docker/services/ensadmin.yml",
+ "docker/services/ensapi.yml",
+ "docker/services/ensindexer.yml",
+ "docker/services/ensrainbow.yml",
+];
+
+const semverRegex = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
+
+async function getVersionFromEnsapi() {
+ const ensapiPackageJsonPath = resolve(rootDir, "apps/ensapi/package.json");
+ const packageJsonContent = await readFile(ensapiPackageJsonPath, "utf8");
+ const packageJson = JSON.parse(packageJsonContent);
+
+ if (typeof packageJson.version !== "string" || packageJson.version.length === 0) {
+ throw new Error("Could not read version from apps/ensapi/package.json");
+ }
+
+ return packageJson.version;
+}
+
+function validateVersion(version) {
+ if (!semverRegex.test(version)) {
+ throw new Error(`Invalid version "${version}". Expected SemVer-like value such as 1.10.1`);
+ }
+}
+
+async function updateServiceDefaultTag(version) {
+ const testPattern = /\$\{ENSNODE_TAG:-[^}]+\}/;
+ const replacePattern = /\$\{ENSNODE_TAG:-[^}]+\}/g;
+ const replacement = `\${ENSNODE_TAG:-${version}}`;
+
+ for (const relativePath of serviceFiles) {
+ const absolutePath = resolve(rootDir, relativePath);
+ const content = await readFile(absolutePath, "utf8");
+
+ if (!testPattern.test(content)) {
+ throw new Error(`Could not find ENSNODE_TAG default expression in ${relativePath}`);
+ }
+
+ const updated = content.replace(replacePattern, replacement);
+ await writeFile(absolutePath, updated, "utf8");
+ console.log(`Updated ${relativePath} -> ${version}`);
+ }
+}
+
+async function main() {
+ const versionFromArg = process.argv[2];
+ const version = versionFromArg ?? (await getVersionFromEnsapi());
+
+ validateVersion(version);
+ await updateServiceDefaultTag(version);
+}
+
+main().catch((error) => {
+ console.error(error instanceof Error ? error.message : String(error));
+ process.exit(1);
+});