stnd.buildSTANDARD MANUAL2026-09-20

Introduction

What a module is, and when you reach for one.

Introduction

A Standard module is a self-contained vertical slice — routes, styles,
components, config, and behavior, dropped into modules/ and wired up
automatically. No central router to edit, no import to add anywhere else,
no manual registration step.

Philosophy: A module should do one thing and declare everything it
needs. No hidden globals, no manual registration. The system finds it,
loads it, and merges it in.

The shape of a module

Every module is a folder with an index.module.js (or .ts) at its root:

// modules/blog/index.module.js
export default {
  id: "blog", // unique — collision throws a build error
  routes: [{ path: "/blog", entrypoint: "./routes/index.astro" }],
  styles: ["./styles/blog.scss"],
  hooks: {
    "stnd:base": ["./components/BlogAnnouncement.astro"],
  },
};

Only id is required — everything else is opt-in. Delete the folder and
the feature disappears; the app keeps running. That’s the litmus test of
a real vertical slice.

Discovery

Modules are auto-discovered from your modules/ folder (configurable via
moduleFolder in astro.config.mjs) — any file matching
**/*.module.{js,ts} is picked up, no registration step. A module that
doesn’t live in your project’s own modules/ folder — a packaged one like
@stnd/fonts/kalice, or a third-party module — is loaded explicitly via
moduleLoad instead.

Where to go from here

Page Covers
Building a Module Recipes for routes, styles, config, dependencies, disabling — plus the full manifest key reference
Hooks & Extension Points How modules talk to each other and to the framework’s own zones, without ever importing one another

Reading order

Start here, then Building a Module for the day-to-day recipes. Hooks is
worth reading end-to-end before you need it — the two calling conventions
(runHook vs runPipeline) are easy to reach for backwards the first
time you need one.