Troubleshooting

Symptoms listed first, fixes below each. Most of these are first-time-integration papercuts - once you’ve hit one, you learn to spot the shape.

My package’s screens 404 in the app shell

Two common causes:

  1. The package isn’t a present member. Is its directory cloned in beside the tinycld shell? Re-run @tinycld/bootstrap to make sure (it skips members that already exist), then re-install so pnpm creates the symlink and the generator picks the new member up:

    cd ~/code/tinycld
    npx @tinycld/bootstrap@latest --assemble-only --with <slug>
    pnpm install
  2. The generator output is stale. The member is present, but tinycld/app/a/[orgSlug]/<slug>/ is empty or out of date. Regenerate from the app shell:

    cd ~/code/tinycld/tinycld
    pnpm run packages:generate

    If you’re running pnpm run dev, quit and restart - the dev launcher runs the generator on startup.

TypeScript sees two copies of react (or anything else)

Symptom: hundreds of “Type X is not assignable to type X” errors, usually involving React.ReactNode, View, ScrollView, or Transaction. Shapes match but inference treats them as different types.

Cause: you ran pnpm install (or any other PM’s install) inside a member directory instead of at the workspace root. Members declare framework deps as peerDependencies and have no node_modules of their own; a member-level install materializes those peers a second time, so TypeScript sees a duplicate react, react-native, pbtsdb, etc.

Fix:

rm -rf <member>/node_modules <member>/package-lock.json
cd ~/code/tinycld && pnpm install   # always at the workspace root

Every member’s .gitignore should cover node_modules/ and package-lock.json. If they aren’t there, add them before the next commit.

Unable to resolve module @tinycld/<pkg> in a Docker build

The Docker image builds from the assembled workspace. If the generator didn’t run inside the Docker context, the tinycld/lib/generated/* wiring and the node_modules/@tinycld/* symlinks don’t exist.

Fix: ensure the build assembles the workspace (bootstrap --assemble-only) and runs the root pnpm install (whose postinstall runs the generator) in a stage where the members are present.

A Go build complains about a missing module or go.work

Cause: the generated tinycld/server/go.work (which ties the app, core, and each feature’s server module together) is stale or missing - usually because the generator hasn’t run since you added or removed a feature with a Go server.

Fix:

cd ~/code/tinycld/tinycld
pnpm run packages:generate

This rewrites tinycld/server/go.work and tinycld/server/package_extensions.go for the current set of present members. The app’s go.mod keeps a hand-written replace tinycld.org/core => ../core/server; individual feature modules need no replace because go.work resolves their locations. If a go.sum still drifts during a build, run cd tinycld/server && go mod tidy once.

A bracket-path route file won’t resolve

Symptom: a dynamic route like screens/[id].tsx works in pnpm run dev but fails at bundle time with Unable to resolve "@tinycld/<pkg>/screens/[id]".

Cause: your package.json exports uses a literal bracket subpath ("./screens/[id]": "./tinycld/<pkg>/screens/[id].tsx"). Metro cannot resolve that form, even though TypeScript and Node both can.

Fix: use a wildcard instead:

{
    "exports": {
        "./screens/*": "./tinycld/<pkg>/screens/*.tsx"
    }
}

This matches both screens/index and screens/[id]. See Screens for the full pattern.

My migrations don’t run in dev

The generator symlinks files from each feature’s pb-migrations/ (and core’s pb_migrations/) into tinycld/server/pb_migrations/. If your migration isn’t showing up in PocketBase’s migration list on the admin UI, the symlink is probably missing or stale.

Fix:

cd ~/code/tinycld/tinycld
pnpm run packages:generate

Verify the symlink exists in tinycld/server/pb_migrations/ and points at your package’s file. If PocketBase is already running, restart it - migrations are loaded at boot.

My settings panel is present but doesn’t appear

Three things to check, in order:

  1. Is the package a present member (its directory cloned in, and the root install re-run)?
  2. Does manifest.ts export a settings array with at least one entry?
  3. Does the file at settings/<component>.tsx default-export the panel component? Named exports are not picked up.

If all three are right and it still isn’t showing, regenerate (pnpm run packages:generate from tinycld/) and reload the app.

Two packages register the same nav.shortcut

The generator doesn’t reject this — it just registers both, and tinykeys (the keyboard-shortcut library) fires whichever it sees first when the user presses the key. The result is a feature that “sometimes” navigates to the wrong screen.

Fix: change one of them. shortcut in the manifest can be any single lowercase letter or omitted. Letters currently in use across first-party packages, in case you want to avoid them: m (mail), o (contacts), c (calendar), d (drive). The package picker UI shows every active shortcut, which is the quickest way to audit for collisions.

Two packages declare the same public route

manifest.publicRoutes mounts files directly under tinycld/app/<path> with no namespacing. If two packages emit the same <path>, the generator writes both — the second wins silently, the first 404s in practice. Coordinate paths between packages or prefix them with the slug (e.g. drive-share/[token].tsx instead of share/[token].tsx).