Manifest
Every package exports a default manifest.ts at its root. The generator reads this file to decide what to wire into the app shell - routes, collections, settings panels, migrations, Go server modules. Fields other than the four base identifiers are all optional; a package contributes only what it declares.
Required fields
Four fields are mandatory:
name- human-readable name used in navigation and the package picker.slug- URL segment and collection-name prefix. Must match the last segment of the npm package name (@tinycld/mail→mail).version- informational only right now; keep it in sync withpackage.json.description- one-line summary shown in the package registry.
Full example
const manifest = {
name: 'Example',
slug: 'example',
version: '0.1.0',
description: 'An example package',
routes: { directory: 'screens' },
publicRoutes: { directory: 'public-screens' },
nav: {
label: 'Example',
icon: 'box',
order: 20,
shortcut: 'e',
},
migrations: { directory: 'pb-migrations' },
hooks: { directory: 'pb-hooks' },
collections: {
register: 'collections',
types: 'types',
},
settings: [
{
slug: 'example',
component: 'settings/example',
label: 'Example settings',
},
],
sidebar: { component: 'sidebar' },
provider: { component: 'provider' },
seed: { script: 'seed' },
tests: { directory: 'tests' },
server: { package: 'server', module: 'tinycld.org/packages/example' },
build: { script: 'build' },
// dependencies: ['other-package-slug'],
}
export default manifest
What each optional field does
routes.directory points to the folder of org-scoped screens the generator re-exports under tinycld/app/a/[orgSlug]/<slug>/. See Screens.
publicRoutes.directory points to a folder whose files become public routes at tinycld/app/p/<slug>/<path>. Use this for pre-auth entry points such as public share links. The per-slug namespace means two packages never collide on the same path.
nav adds a rail entry in the org workspace. icon is a lucide-react-native name, order controls sort priority (lower comes first), and shortcut registers a single-letter keyboard shortcut. Omit nav entirely for packages that don’t belong in the sidebar - a settings-only package has no nav, no routes, no publicRoutes.
migrations.directory and hooks.directory are PocketBase concerns. The generator symlinks their contents into the app shell’s tinycld/server/pb_migrations/ and tinycld/server/pb_hooks/ so PocketBase discovers them on boot.
collections.register and collections.types are subpaths (without extension) to the registerCollections function and schema-type module, respectively. See Collections.
settings is an array of panel contributions to Personal Settings. Each entry needs slug, label, and component (a subpath to the .tsx panel). See Settings.
sidebar.component is a subpath to a component rendered in the secondary sidebar when the package is active. Omit sidebar entirely (as @tinycld/calc does) and the workspace renders no sidebar container at all - the package’s screens get the full viewport width next to the nav rail. provider.component wraps the package’s routes with a custom provider - use it when a package needs its own context (e.g. Drive’s upload state).
seed.script is a subpath to a module that default-exports an async seed function. tests.directory tells the test runners where to find Playwright specs. See Seed and Tests.
server.package is the subdirectory containing a Go module; server.module is the module path it declares. The generator lists each present feature’s server module in a generated tinycld/server/go.work (no per-package replace directive is needed). See Server.
build.script is a subpath (resolved through the package’s exports map) to a TS module the generator runs whenever it generates - before route re-exports land. Use it when the package ships an artifact the bundler can’t produce on its own (for example, a self-contained webview bundle compiled with esbuild). The script runs from the package directory; one-shot builds gate packages:generate and the web export, and the dev launcher can run them in watch mode. Scripts are executed via the workspace’s hoisted tsx, so they can import dependencies the app shell provides - the member package itself has no node_modules.
dependencies is an array of slugs this package expects to be installed. The generator does not enforce these at build time - it’s metadata for humans and for runtime feature gating.
For the exact TypeScript interface, see Manifest schema.