docs / grandstack / Concepts

Building on GRANDstack, not beside it

GRANDstack is a set of building blocks that people shape into a solution of their own: a server image driven by a schema file, a federation gateway, an auth layer, an agent endpoint, a web app, and compose files that put them together. A new repository or setup should be made from those blocks. If it copies one, forks one, or re-implements one, it is a silo: it cannot be combined with the others, it drifts, and nobody who learns GRANDstack can reuse what they learned.

This page is for coding agents and the people directing them, and for anyone adding a repository or a setup. Read it before you create a repository, a compose file, a server, a gateway or a docs structure.

The rule

Use what is here. If a block is missing something, improve the block. Only what is genuinely new lives in the new repository.

You needUse this blockDo not
A GraphQL API over Neo4jgrandstack-server (the image), configured with a schema file and environment variableswrite another server, or copy its code
A different schema, setup or sample dataA model (MODEL=<name>, a mounted models/<name>/ folder), or SCHEMA_PATH, SCHEMA_EXTRA_PATHS, SETUP_CYPHER_PATHS, SEED=falsefork the server to change its schema
A read-only copy of an APIREAD_ONLY=true on a second serverbuild a second schema by hand
One API from several servicesgrandstack-federation’s gateway image, with your own supergraph.graphql and gateway.config.ts mounted over its ownbuild another gateway image
Login and access rulesgrandstack-auth (the gateway, Keycloak, schema rules)write your own sign-in unless the block cannot do it, and then say why
Agents using the APIgrandstack-agents (the MCP server)write another tool server
A browser front endA web app in the style of grandstack-web (urql, typed operations, URL state), served by its own web servercopy grandstack-web wholesale for different data without saying what is shared
Running it allCompose overlay files in the grandstack repository (compose.<setup>.yaml), used with compose.yamlput a root compose.yaml in the new repository

A new setup normally adds custom code in only two places: the part that is really new (for example a subgraph that talks to an external system, like the Wikipedia subgraph or the Aura subgraph), and the front end. The data layer, the gateway, the auth and the compose files come from the blocks.

When a block does not do what you need

Change the block, in its own repository, in a way that is generic and backward compatible, and use that. Do not work around it in the new repository.

Example: the Aura web UI needed the server to serve a different model, and to run a read-only copy beside a writable one. The answer was not a second server in the Aura repository. It was MODEL and READ_ONLY in grandstack-server, which any other setup can now use too, with the default (Movies) unchanged and tests and docs in that repository. The Aura repository kept only its model files.

Do this on a branch in the block’s repository, with its tests and its docs, and say in your change that another repository depends on it. Do not edit a block’s main.

What a new setup must do

Treat this as a checklist. Each item is how the existing setups (auth, agents, federation) already behave.

Compose, in the grandstack repository

  • An overlay compose.<name>.yaml, used with compose.yaml, that builds the other repositories from sibling folders (../grandstack-<name>).
  • The standard ports (3000 web, 4000 GraphQL, 7474 and 7687 Neo4j). A setup that replaces another says so and replaces it on those ports rather than inventing new ones.
  • Its own Neo4j volume if it uses a different model, so two setups never mix data.
  • Images pinned to an exact version and a digest.
  • A line in .env.example for every new setting, a section in docs/configuration.md, the README’s “Run it with …” section, AGENTS.md, docs/agents.md, docs/roadmap.md and llms.txt.
  • A setup in scripts/integration.sh and the nightly integration.yml, so it is run end to end with the others.

The repository itself

  • README.md, AGENTS.md, and the same docs set the other repositories have: docs/architecture.md, features.md, customising.md, recipes.md, testing.md (and deploying.md or similar if it has a deployment story), with diagrams in docs/diagrams/ that carry a numbered legend. npm run docs:check passes (the link and diagram checker is copied from grandstack-web).
  • The two-line copyright header on every code file (node ../grandstack/scripts/add-headers.mjs --check), and LICENSE and NOTICE (Apache 2.0, like every GRANDstack repository).
  • Exact-pinned dependencies, and the pins that must hold (graphql 16.x, @apollo/subgraph 2.14.4).
  • The release workflows (release.yml, release-cut.yml, dependency-review.yml, dependabot.yml), calling the shared workflows in the organisation’s .github repository. Do not make tags or bump versions by hand.
  • An entry in grand-stack.github.io’s docs-manifest.json, so its docs reach the website, and a row in docs/versioning-and-releases.md and docs/releasing.md in the grandstack repository.

Safety, because these blocks run beside each other

  • Say plainly what the setup can change and what it exposes, and bind to loopback by default if it can do harm without a sign-in.
  • Never run docker compose down -v under the default project name beside a stack you want to keep: the merged files include the other setups’ data volumes. Use a project name of your own when testing.

Warning signs of a silo

If you are about to do any of these, stop and ask what block already does it:

  • copying a file from grandstack-server, grandstack-web or grandstack-federation into a new repository;
  • a Dockerfile that rebuilds the server or the gateway;
  • a compose.yaml at the root of a repository other than grandstack;
  • a port other than the standard ones for a role that already has one;
  • a new sign-in, token or secret scheme next to grandstack-auth;
  • documentation in a shape the other repositories do not use;
  • a repository that cannot be started by adding one file to grandstack’s compose command.

If a block really cannot serve the need, write down why in the new repository’s docs/architecture.md, and propose the change to the block rather than going around it.

Worked example: the Aura web UI

grandstack-web-aura is the first setup restructured onto the blocks. The first version had its own store server, its own gateway image and its own compose files. It was rebuilt on the blocks: the store is grandstack-server with MODEL=aura (read-only and writable), the gateway is grandstack-federation’s image with its own config files, and the compose files are compose.aura.yaml here. What stayed in its repository is what is new: the graph model, the Aura subgraph, a fake Aura for tests, the web app, and an optional TLS and sign-in edge. Its architecture page shows the result.

Next: architecture, configuration, agent guide, build your own app.

Source: grandstack/docs/building-on-grandstack.md (this page is a copy; edit it in the repository)