Skip to main content
A Lab is a React app that runs as the app of a Parable. You build it with your own tools, package it as one ZIP file, and import it into a Parable. Parable supplies React, the shared design-system controls, the reader’s Workspace data, and the publishing lifecycle. A Lab therefore reaches its readers through the same review and access checks as any other Parable. Use a Lab when your team already has a React app, or needs full control of its screens. An app with twenty pages is still one package.
Parable gives you a Lab kit: the type declarations of the parable module and the shared controls, and a tool that packs your app into a ZIP. Ask your Parable representative for the Lab kit.

What a package holds

Without parable.lab.json, Parable looks for src/App.tsx, src/App.jsx, App.tsx, or App.jsx, and refuses a package that has more than one of them. An entry file ends in .tsx, .ts, .jsx, .js, or .mjs. Leave out node_modules, .git, .env files, React, and the design system. Parable never runs install or build scripts. Bundle any other browser library into the app’s own files. Import images and other assets in code: a literal path such as /logo.svg has no server inside the Lab. The host supplies these modules, so do not bundle them:

The manifest

parable.lab.json
Parable refuses a field that it does not know. A Plot slug starts with a lowercase letter and holds lowercase letters, digits, and single underscores, such as weekly_load. Parable does not change a slug for you: Weekly-Load is refused. lab_data is reserved. Each slug and each .sql file belongs to one Plot.

Read data from the app

Import the SDK from the parable module:
src/App.tsx
query() and readPlot() resolve to the same result: The context has the Workspace, the Parable and the revision being read, the data reading (CURRENT, or a stored Refresh), the reader, and the reader’s seat. A failed call rejects with an error that has a message and a code, such as HANDLE_UNDECLARED. Always put values in parameters. Never paste them into the SQL text. The app holds no credentials, database connections, or Provider SDKs. It cannot choose another Workspace or another person.

Give every reader the data

Who can run SQL in a Parable depends on the reader:
  • A reader who can edit the Parable reads every pool that their role allows. Editing needs the tenant.parables.manage permission and a Publishing or Primary seat on the Parable.
  • Every other reader, such as a reader with a Peeking seat, reads only the Parable’s own Plots. Their query() over a providers., artifacts., or workspace. table is refused with 403 and PA-AU-019.
So put the SQL that reads the pools into declared Plots, and read the Plots from the app:
  1. Put each query in its own .sql file, such as plots/capacity.sql.
  2. Declare it under plots in parable.lab.json, with a slug, a name, and the file path.
  3. In the app, read it with readPlot('capacity'). To filter it with bound parameters, use query() over plotTable('capacity').
Every reader with a seat on the Parable can read a declared Plot. A Plot’s rows, Artifact and Workspace rows included, show to each of them. A Plot takes no parameters, and returns text, numbers, booleans, JSON, and lists or objects of them. A slug that parable.lab.json does not declare fails with HANDLE_UNDECLARED. When you import a package, Parable warns you about each line of app source whose SQL names providers, artifacts, or workspace tables. A warning does not block the import. Resolve it before you publish, so that every reader sees data.

Import the package

  1. Open a new or empty Parable in the app. Lab mode can be turned on only for an empty Parable.
  2. Turn on LAB, choose Import Lab Package, and upload the ZIP.
  3. Preview the app as an active member of the target Workspace, so that its queries return that Workspace’s data.
  4. In a Personal Parable, the import saves directly. In a Parable with Published Versions, the import adds to your pending Changes: preview them, propose them, publish a Version, and deploy it.
To update the app, change your files and import a replacement ZIP with the upload icon next to LAB. Parable replaces the whole package. A Plot keeps its slug across imports. A changed .sql file or name updates the Plot, and a Plot that parable.lab.json no longer lists is deleted. If an import fails, the previous package stays in place.

Import over the Workspace API

The app’s import calls two operations, which you can also call with a Parable token:
  1. POST /api/parable/authoring/primaries/{rootRefId}/actions/plan-archive-import checks the ZIP and changes nothing. Send it as multipart/form-data with the ZIP in file. The plan returns changes, diagnostics, warnings, applicable, baseVersion, and planDigest.
  2. POST /api/parable/authoring/primaries/{rootRefId}/actions/apply-archive-import applies the plan. Send the same file, with expectedVersion set to the plan’s baseVersion and the plan’s planDigest. If the Parable changed since the plan, plan again.
rootRefId is the Parable’s root_ref_id in workspace.parables. Add ?proposalId=<id> to import into your own open Changes. The API refuses an MCP token here.

Limits

Parable also refuses a package with symbolic links, encrypted or ZIP64 entries, absolute paths or .. in a path, or two paths that differ only by letter case. It ignores __MACOSX/ and .DS_Store, and it unwraps one folder that encloses the whole app.

Permissions

The Workspace Administrator role holds all of them. A reader without the file permission sees the app alone. The browser still downloads every file of the package to run the app, so keep private data out of the package and read it through declared Plots.

What a Lab does not do

  • A Lab draws no structured Pieces or Preferences. Keep filters and navigation in React state, inside the app.
  • A Lab does not store query results as Reports. Results show in the app.
  • Deploying a Lab does not copy data. Each Workspace that receives it needs its own Provider connections and Artifacts.
  • A Lab with content cannot become a structured Parable. Start from an empty Parable for that.
Lab Parables explains how Ponder builds and changes a Lab for you.