Stability & Versioning

What won't break under you.

Apex publishes a public API contract: a listed surface that's treated as a promise, split into ๐ŸŸข Stable and ๐ŸŸก Experimental, with a deprecation policy that holds even before 1.0. Anything not on the list is internal and may change. This is the road to a version you can build on.

The promise #

Everything in the API contract (API.md) is public; anything not listed is internal and may change without notice. The goal is the road to 1.0: a surface people can build on without it breaking under them. A CI-enforced contract test fails the build if a Stable export disappears or changes kind, so the promise isn't just prose โ€” it's checked on every commit.

The golden rule

If a change to a Stable API isn't deliberate and deprecated-first, it doesn't ship. A framework that hasn't broken you in months feels 1.0; one that breaks weekly never earns it.

Stability levels #

LevelMeaningChange policy
๐ŸŸข StableBattle-tested; treated as a contract.No breaking change without a deprecation notice first (see below).
๐ŸŸก ExperimentalWorks, but the shape may still change.May change in any minor โ€” the changeset will say so. Don't build load-bearing code on it yet.

Everything not in API.md is internal โ€” import it and you're on your own.

Deprecation policy #

  • Post-1.0: semver, strictly. No breaking change to a ๐ŸŸข Stable API in a minor or patch โ€” breaking changes wait for a major.
  • Pre-1.0 (now): a ๐ŸŸข Stable API is never removed or changed without (1) a @deprecated JSDoc tag naming the replacement, (2) an entry in the changeset, and (3) at least two minor releases of overlap before removal. ๐ŸŸก Experimental APIs may change in any minor, always noted in the changeset.
  • Graduation: new surface lands as ๐ŸŸก Experimental. It becomes ๐ŸŸข Stable after โ‰ฅ2 minors unchanged and at least one real app using it.

The public surface #

The full, authoritative list โ€” every export with its level โ€” lives in API.md. The headline Stable entry points:

ImportStable surface
@apex-stack/coredefineApexRoute, defineConfig, useRuntimeConfig, defineStore, defineMiddleware, defineAuth, isApexResource (+ their types)
@apex-stack/core/serversessionAuth, login, logout, getSession, checkCsrf, applySecurityHeaders (+ more)
@apex-stack/core/clientregisterApexComponent, installNav, createAction
@apex-stack/core/testingcreateTestApp
@apex-stack/datadefineModel, defineResource, createDb, applyMigrations, timestamps/owned/softDeletes, factory
CLIdev build start new make add migrate theme upgrade test mcp โ€” command names + documented flags are part of the contract

Currently ๐ŸŸก Experimental (may still change): createI18n/resolveLocale, rate limiting, the serverless building blocks (createProdNodeHandler โ€ฆ), postgresOptions, apex extend, and apex build --preset. @apex-stack/kit, /vite, /theme, and /components are internal โ€” use them only via @apex-stack/core and the apex CLI.

How packages are versioned #

Apex is a monorepo of independently versioned packages, released with Changesets. @apex-stack/core and @apex-stack/data move at their own pace; always install with @latest:

npm create apexjs@latest my-app        # scaffolder โ€” always latest
npm i -g @apex-stack/core@latest       # the CLI

Each release ships a changeset entry (a human-readable note of what changed and at what level), so an upgrade never surprises you. Run apex upgrade to move an existing app to current scaffold defaults non-destructively.

The invisible API #

Some contracts aren't exported symbols โ€” they're conventions the framework reads. Changing these breaks apps silently, so they're ๐ŸŸข Stable too:

  • apex.config.ts โ€” runtimeConfig (+ public), i18n: { defaultLocale, locales }.
  • File routing โ€” pages/**/*.alpine; [param] dynamic segments; index.alpine โ†’ parent path.
  • The .alpine SFC โ€” <script server> (loader() / head()), <script client>, <template>, <style scoped>.
  • Islands โ€” client:load / client:visible / client:idle.
  • Server โ€” server/api/*.ts default-exports a route or resource; server/auth.ts default-exports an AuthConfig; middleware/*.ts.
  • Data โ€” models/*.ts, db/migrations/*.sql, locales/*.json.

The canonical, always-current version of this contract is API.md in the repository.