← Back to docs

FAQ

Common questions about local setup, deployment, sites and modules

Local development

Why do localhost:7300 and 127.0.0.1:7300 show different things?

They are two entrances. localhost is the product site (the default tenant), 127.0.0.1 is the platform console. This falls out of Host-based routing — see Host-based routing.

Why was I redirected away from /platform?

Asking a product-site Host for /platform sends you to PLATFORM_URL. The console only exists on its own Host.

How do I test tenant subdomains locally?

Set TENANT_BASE_DOMAIN=localhost and open http://{slug}.localhost:7300. Browsers resolve *.localhost to the loopback address natively, so there is no hosts file to edit.

My new module's page 404s

Its routes must live under /app/<module>. Mounted at the top level (say /site) they get taken over by the CMS on tenant Hosts — / belongs to the tenant site, and the app area always goes under /app/*.

Database and migrations

migrate dev produced DROP statements I didn't ask for

It diffs your development database against the schema, so leftovers in that database — old branches, tables from another project — turn into DROPs. Use an offline diff instead: replay the migration history into an empty shadow database and compare that against the schema, independent of whatever your dev database has accumulated.

Can I just drop the stray tables in my dev database?

No. Dropping tables doesn't change the migration history, so you create drift in the opposite direction and Prisma escalates from "one extra drop" to "the whole schema must be reset". The only correct fix is making the migration history and the schema agree.

Where do external modules' migrations live?

External modules only declare prisma/schema.prisma; migrations are owned by apps/server. One database has one migration history — the module's schema is symlinked into the main schema and the consumer generates the migration.

Do I have to run migrations in production?

Not with Docker: docker/entrypoint.sh runs migrate deploy for you. Outside containers, run pnpm --filter server exec prisma migrate deploy once.

Building a site

Why does a new site only have a home page?

Initialization creates a blank home page on purpose. Add pricing, about or contact pages in the CMS when you need them. For a product home, pick a module's layout in site settings.

Where did the "Get started" header button go?

Defaults no longer ship a header button — it used to point at member registration, which 403s while members are disabled. Add your own call to action in the header settings.

Can I use /docs as a page path?

No, it is reserved for the documentation library. The same goes for language codes (en, zh-CN).

I edited a page and visitors still see the old one

The editor changes the draft; publish it from the list. Pages and documents both work this way.

Documentation

How do I write the English version of a document?

Choose the language when creating it — one row per language under the same path. The public site serves the version matching the visitor; the primary language has no URL prefix and the rest live at /{locale}/docs. See Documentation library.

Can I change a document's language later?

No. That would move the row into another translation set, which may already contain a document with the same path. Create it in the target language instead.

Will "export all" produce duplicate filenames?

No. The primary language exports as faq.md and other languages as faq.en.md, and imports read the suffix back.

Deployment

How do I configure a single-tenant install?

Set SINGLE_TENANT=true: the console is hidden, creating tenants is disabled, and every request belongs to the default tenant. Run pnpm check:prod-app-env before committing.

Do I need to seed the default tenant's site?

No. The server publishes a starter site and documentation library on startup — idempotently, and evaluated per language, so it never overwrites content you changed.

Modules

check:modules is failing

It verifies registries, tenant columns, toggles, permissions, ordering, shell wiring, navigation and import boundaries. Work through the errors — usually something is missing from a registry, modules are in the wrong order, or a forbidden package was imported.

Can an external module depend on another module?

Not by importing it. Cross-module work goes through extension points (events, providers, slots). requires declares dependency and load order only, not code access.