Framework Package Format
The Framework Package Format (FPF) is the specification that all tsx packages follow. An FPF package is a versioned, self-describing bundle of code generators, templates, and metadata that can be installed into any compatible project with a single command.
What is a framework package?
Think of an FPF package as a smart scaffold. Unlike a plain code snippet or a library dependency, a framework package:
- Knows about your project structure and writes files into the right places.
- Declares capabilities it provides (e.g.
auth,crud) so other packages can integrate with it. - Integrates automatically with other installed packages via the
integrates_withslot system. - Is versioned and pinnable, so teams get reproducible scaffolding.
Directory layout
After installation, a package lives under .tsx/packages/<name>/:
.tsx/
└── packages/
└── with-auth/
├── manifest.json # Package manifest (pinned version)
├── generators/ # Rhai or shell generator scripts
│ ├── setup.rhai # Scaffolds the full auth integration
│ └── add-route.rhai # Adds a new protected route
└── templates/ # Handlebars templates
├── auth.server.ts.hbs
├── auth.client.ts.hbs
└── middleware.ts.hbs
The manifest
Every package must have a manifest.json at its root. It declares the package
identity, capabilities, generators, and integration slots. See
manifest.json reference for the full field specification.
Generators
Generators are scripts that receive a JSON input schema and write files to the project.
They are defined in the generators[] array of the manifest and invoked via:
tsx run <package>:<generator> [--input '{"key":"value"}']
The slot system
The integrates_with map in the manifest describes how this package modifies
other packages' output. For example, the with-auth package can inject a
session check into routes generated by tanstack-crud:
"integrates_with": {
"tanstack-crud": {
"slot": "route.beforeLoad",
"inject": "templates/auth-guard-slot.hbs"
}
}
When both packages are installed, tsx automatically threads the slot injection through the generator pipeline — no manual wiring required.