Content Type System & Code Generation
How SveltyCMS generates TypeScript types for collections at build time, using the consolidated content architecture.
On this page
SveltyCMS uses a build-time code generation system to create TypeScript types for your collections, providing full type safety across the entire codebase.
🎯 Overview
When you define collections in config/collections/, SveltyCMS automatically:
- ✅ Compiles TypeScript definitions to
.compiledCollections/*.js(Vite build). - ✅ Scans compiled modules via
engine.server.ts(scanCompiledCollections) with mtime caching. - ✅ Loads schemas via
loader.server.ts(loadSchemaNative()or worker pool in production). - ✅ Generates TypeScript union types via
scripts/generate-content-types.ts. - ✅ Updates
src/content/types.generated.tswith theContentTypesunion andCollectionMap. - ✅ Provides IDE autocomplete for all collection names (re-exported from
src/content/types.ts).
🔄 How It Works
1. Type Generation Script
Types are generated by scripts/generate-content-types.ts, not by a Vite plugin:
- It scans
.compiledCollections/for*.jsmodules and builds theContentTypesstring union plusCollectionMapfield stubs. - It is invoked from the collection watcher in
vite.config.ts:497-511after a successful compile —if ((result.compiled?.processed ?? 0) > 0)→generateContentTypes(server)— and a failure there is logged, never fatal to HMR. - The write is atomic (temp file + rename) and skipped when the content is unchanged.
2. Marker Comments for Stability
To prevent file corruption during rapid Vite reloads, the generator rewrites only the Marker Comments region:
/* AUTOGEN_START: ContentTypes */ and /* AUTOGEN_END: ContentTypes */ (see src/content/types.generated.ts).
Everything outside those markers — manual types, imports — is preserved.
3. No Separate Production Path
Runtime schema discovery does not depend on the generated types: engine.server.ts (scanCompiledCollections()) is the same scanner used by the generator and by runtime reconciliation, so a stale types file can never break boot. Run the generator only for IDE/type-checking accuracy.
📊 Benefits
1. Type Safety Everywhere
Autocomplete for collection names and validation for field types.
import type { ContentTypes } from "@src/content/types";
function getCollection(name: ContentTypes) {
return contentSystem.getCollection(name);
}
2. Refactoring Safety
When you rename a collection file, TypeScript catches all references across the app.
📁 Key Files
| File | Purpose |
|---|---|
src/content/index.ts |
Browser-safe public API facade |
src/content/index.server.ts |
Server-only entry (init, CRUD, ensureContentInitialized) |
src/content/engine.server.ts |
Scanner, reconciliation, cache, watcher |
src/content/loader.server.ts |
Schema module loading (native + worker pool) |
src/stores/content-registry.svelte.ts |
Reactive state using Svelte 5 runes |
src/content/content-utils.ts |
Navigation, metrics, pure helpers |
src/content/types.ts |
Unified interfaces; re-exports generated types |
src/content/types.generated.ts |
Autogenerated ContentTypes union (do not edit manually) |
scripts/generate-content-types.ts |
Generates the union from .compiledCollections/ (AUTOGEN markers) |
🚀 Performance
- Zero Runtime Overhead: Types are stripped during compilation.
- Tree-Shakable: Server-only logic in
engine.server.ts/loader.server.tsis never sent to the client. - Incremental Updates: Only modified collections trigger an update in the types file.
- Single scanner: Vite and runtime share
scanCompiledCollections()— consistent schema discovery.