Browse documentation

Upgrade FlowPanel

Align package versions, review migrations and changes, and validate generated and ejected surfaces.

FlowPanel workspace packages are released together. Most applications should depend on the umbrella @flowpanel/kit and local @flowpanel/cli at the same version rather than pinning lower-level packages independently.

Inspect the current install

pnpm list "@flowpanel/*"
pnpm flowpanel doctor

Before changing versions, record ejected files and any direct lower-level FlowPanel dependencies. Read the changelog for every version you will cross.

Update aligned packages

pnpm up "@flowpanel/*" --latest
pnpm install

Keep direct FlowPanel packages on the same released version. Multiple copies of @flowpanel/core can split request context and module augmentation; flowpanel doctor checks for that condition.

Review database work

pnpm flowpanel migrate --dry-run

Review pending SQL for the target dialect and deployment strategy before applying it. Back up production data according to the application's normal migration policy, then run pnpm flowpanel migrate in the controlled release step.

Validate the application

Run the application's typecheck and production build. Start the admin once so config compilation can catch duplicate/reserved names, stale columns, and unresolved references. Exercise auth, one scoped read/write, forms, actions, realtime, and queues used by the deployment.

Review ejected files

Ejected files contain a version stamp and are application-owned. The upgrade does not rewrite them. Compare their public imports and behavior with the changelog and current reference; test them separately from generated routes.

If a newer config, renderer, page, or slot now covers the customization, consider returning that surface to generated behavior. Re-enabling config also requires removing the explicit Next.js route.

Upgrading from 0.2 to 0.3

0.3 changes a few defaults and removes one dead option. Read this list against your flowpanel.config.ts before you upgrade.

  • Rows open the detail page. A resource that configures detail and no drawer now navigates on row click and on Enter. Set rowClick: false to keep rows inert, or rowClick: "drawer" where a drawer exists.
  • Pie charts show their legend. pieChart({ showLegend: false }) restores the previous look.
  • table() honours emptyState and limit. Both were declared and ignored; a table that relied on seeing every row of a query should drop limit.
  • detail.header is deprecated. Move it to detail.title; subtitle and badge are new slots beside it. title wins when both are set.
  • Validation messages come from labels.form. An empty required field reads "{label} is required" (labels.form.required) instead of a Zod type message; custom messages still pass through. Override the key to change the wording.
  • audit.retention is removed. It was never applied; delete the line and keep retention where the rows live.
  • Drawer field payload shape. A drawer's serialized fields are { name, label? } objects instead of bare names. Only a host reading the drawer payload directly is affected.
  • Workers publish through @flowpanel/kit/publish. createPublisher({ redis }) replaces bindPublisher(config) in a publish-only process. The Redis wire is unchanged, so 0.2 and 0.3 instances interoperate during a rolling deploy.
  • formatNumber's third argument. It is now the resolved formatting object (useFormatting() in a client component, resolveFormatting(config.formatting) on the server), not a locale string. A bare locale string still works and keeps 0.2's USD/UTC, so an ejected widget compiles either way.
  • Date values in cards and ticks. A Date in a stat, statGroup or kv value, and every chart x-axis tick, now renders through the admin's formatting (locale, timeZone) like a table cell instead of the server's own clock. Drop any hand-rolled toISOString().slice(0, 10) in a widget resolver.
  • ctx.count rejects an unknown where key. A key the adapter does not report as a column throws a config error naming the field and the resource, on both count paths, instead of silently counting the whole table on Drizzle and throwing inside Prisma.
  • HealthBanner's error tone is "err". The component now speaks the shared Tone vocabulary; rename tone="error" to tone="err".
  • StatItem.value takes only ctx. Its never-passed second row parameter is gone; the record is ctx.row.
  • The memory realtime driver serialises payloads. Like Redis, it now JSON-encodes on publish and decodes on delivery, so a Date in a payload arrives as a string and a non-serialisable payload throws in development too, with or without a subscriber.
  • ctx.db stays. Its deprecation notice now names 1.0 as the removal target; ctx.sql and ctx.count are the supported way to query from a widget.
  • New package. Add @flowpanel/test as a dev dependency next to @playwright/test to run smokeAdmin in your browser suite.

Pre-1.0 expectations

Before 1.0, minor releases may contain breaking changes. Types and deprecation notes are part of the migration path, but they do not replace the changelog and application tests. Upgrade in a reviewable branch and avoid mixing unrelated dependency changes.

If the installed behavior and current site disagree, use the versioned package types and release notes as the authority and report the documentation mismatch.