# SSG Commands

> Run static generation from a config file, choose the output directory, and verify what was written.

Source: [https://askrjs.com/docs/tooling/ssg](https://askrjs.com/docs/tooling/ssg)

Status: stable. Packages: @askrjs/askr.

**Published packages are authoritative.** Examples may lag behind a published contract. When guidance differs, verify the exports and TypeScript declarations in your installed package, then file an issue.

## Example

Point the CLI at the application-owned SSG configuration, use an explicit output directory, and fail the build when any registered route cannot render.

```sh
npx askr ssg --config ./ssg.config.ts --output ./dist

# Verify the generated document and hosting fallback.
test -f ./dist/index.html
test -f ./dist/404.html
```

## Configuration

askr ssg --config &lt;path&gt; --output &lt;dir&gt; requires both flags explicitly -- there's no default config path the way openapi has one. --config must point at a TypeScript module (a .ts extension is enforced; passing anything else is a validation error), and that module defines which routes get pre-rendered and how.

## Output directory

--output &lt;dir&gt; is where the generated HTML tree lands, and it's also required -- the command refuses to run without it rather than defaulting to something like dist/. --workers &lt;n|auto&gt; optionally controls how many render workers the build uses, which is the main lever for tuning throughput on large route counts.

## Document and assets

Each pre-rendered route becomes a static HTML document built by whatever `DocumentRenderer` function you pass to `createStaticGen` — the same document-composition primitive SSR uses. That's a shared *contract* (a plain function of `{ appHtml, context }`), not shared machinery with `@askrjs/vite`'s dev-server plugin specifically: the Vite plugin composes documents by replacing HTML-comment markers in `index.html` at request time, a different mechanism built for the dev server, not something SSG output goes through.

## Failure reporting

--incremental reuses a previous build's manifest instead of re-rendering every route from scratch, and --changed-key / --changed-route (both repeatable) let you mark specific invalidation keys or concrete paths as changed so only the affected routes get regenerated. --force-full overrides all of that and forces a complete rebuild even when incremental flags are present. When routes fail to render, the command collects and prints an "Errors encountered" section listing each failure rather than aborting on the first one, so a single bad route doesn't hide problems in the rest of the site.

## Documentation navigation

[Previous](https://askrjs.com/docs/tooling/openapi/index.md) | [Next](https://askrjs.com/docs/tooling/dependency-updates/index.md)
