GraphQL SSG
graphql-ssg (version 0.4.8) is a static site generator (SSG) that specializes in bundling HTML from data feeds, particularly those powered by GraphQL. Unlike many Node.js-based SSGs, it uniquely performs bundling within a browser environment, leveraging native ESModules, URL imports, and import maps. This design choice aligns well with Web Components architectures, allowing for direct use of browser features for content generation. The project is currently in a pre-1.0 development phase, suggesting its API might evolve, but it provides a functional CLI for initializing, watching, and building projects. Key differentiators include its browser-centric bundling, automatic generation of typed GraphQL clients (via the `Chain` helper) based on configured schemas, and secure injection of configuration and environment variables into page-generating functions, preventing secret exposure. It supports both JavaScript and TypeScript page definitions for content creation.
Common errors
-
Error: No default export found in file: {path-to-file}cause A page file (e.g., `pages/my-page.ts`) does not contain an `export default` statement.fixAdd an `export default` statement to your page file, which should return the HTML content or a function that returns it, e.g., `export default () => html`. -
Cannot read properties of undefined (reading 'config')` or `ssg is not defined
cause Attempting to access `ssg.config` or `ssg.env` outside of the `export default` or `export const head` functions within a page file.fixMove the code accessing `ssg.config` or `ssg.env` directly into the `export default` or `export const head` function to leverage the injected context. -
ReferenceError: Chain is not defined` or `Cannot find module '../ssg/{schema-name}/index.jscause Incorrect import path for the generated `Chain` client, `html` helper, or `md` helper, or a GraphQL schema name mismatch in `graphql-ssg.json`.fixVerify the relative import path (`../ssg/...`) matches the expected generated helper location based on your project structure and the schema name in your `graphql-ssg.json` file.
Warnings
- gotcha All page files (`.js`, `.ts`) *must* include an `export default` function or string to define the page content, otherwise they will not be processed correctly by the SSG. This is the primary mechanism for content generation.
- gotcha Configuration (`ssg.config`) and environment variables (`ssg.env`) are strictly injected and accessible *only* within `export default` and `export const head` functions of your page files. Attempting to access them outside these contexts will result in `undefined` or runtime errors, designed to prevent secret leakage.
- gotcha The library is primarily designed for global installation (`npm i -g graphql-ssg`) as a CLI tool. While local installation is technically possible, typical usage and commands assume global availability.
- breaking As `graphql-ssg` is in a pre-1.0 version (currently 0.4.8), its API and internal mechanics may undergo breaking changes in minor or patch releases without explicit major version increments. Users should pin exact versions for production and review changelogs for updates.
Install
-
npm install graphql-ssg -
yarn add graphql-ssg -
pnpm add graphql-ssg
Imports
- Chain
const Chain = require('graphql-ssg/Chain');import { Chain } from '../ssg/{schema-name}/index.js' - html
const html = require('lit-html').html;import { html } from '../ssg/basic.js' - md
import { md } from 'markdown-it';import { md } from '../ssg/md.js'
Quickstart
// Install globally: npm i -g graphql-ssg
// Initialize project: graphql-ssg --init .
// Configure graphql-ssg.json with a 'pokemon' schema pointing to 'https://graphql-pokemon2.vercel.app/'
// ./pages/index.ts
import { html } from '../ssg/basic.js';
import { Chain } from '../ssg/pokemon/index.js'; // Path generated based on 'pokemon' schema name
export default async () => {
// ssg.config is injected and only available within export default/head
const graphQLClient = Chain(ssg.config.graphql.pokemon.url);
const response = await graphQLClient.query({
pokemon: [{ name: 'Pikachu' }, {
id: true,
name: true,
number: true,
types: true,
}],
});
const pikachu = response.pokemon;
return html`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pokemon SSG</title>
</head>
<body>
<h1>Hello, ${pikachu?.name || 'World'}!</h1>
<p>Number: ${pikachu?.number}</p>
<p>Types: ${pikachu?.types?.join(', ') || 'N/A'}</p>
</body>
</html>
`;
};
// To build your site: graphql-ssg --build
// To watch for changes: graphql-ssg