Configuration reference

This page covers everything you can configure in a Piral project: the runtime (via createInstance), the project files (piral.json and pilet.json), and the relevant environment variables.

createInstance

createInstance creates the central Piral runtime for the app shell. It lives in the shell's entry module.

Signature

function createInstance(config: PiralConfig): PiralInstance
createInstance({
  // Required: returns the pilets to load
  requestPilets(): Promise<PiletMetadata[]>,

  // Optional: override shell components and error pages
  state?: {
    components?: Partial<ComponentsState>,
    errorComponents?: Partial<ErrorComponentsState>,
  },

  // Optional: extend the Pilet API
  plugins?: PiralPlugin[],

  // Optional: additional global state actions
  actions?: GlobalStateActions,
})

requestPilets (required)

Returns the list of pilets to load. Called once at startup.

// From a live feed with auth
async requestPilets() {
  const token = getToken();
  const res = await fetch(FEED_URL, {
    headers: token ? { Authorization: `Bearer ${token}` } : {},
  });
  if (!res.ok) throw new Error(`Feed failed: ${res.status}`);
  return (await res.json()).items;
},

// Static (for tests or demos)
requestPilets() {
  return Promise.resolve([
    { name: 'my-pilet', version: '1.0.0', link: '/pilets/my-pilet.js',
      spec: 'v2', integrity: '', dependencies: {} },
  ]);
},

state.components

Override the shell's structural components. All keys are optional:

KeyTypeDescription
LayoutReact.FC<LayoutProps>Outer wrapper for all pages
RouterReact.FCRouter provider (default: BrowserRouter)
RouteSwitchReact.FCRenders the matched page
LoadingIndicatorReact.FCShown while pilets load
state: {
  components: {
    Layout: MyLayout,
    Router: MyRouter,
    RouteSwitch: MySwitch,
    LoadingIndicator: Spinner,
  },
}

state.errorComponents

Override the error UIs. All keys are optional:

KeyWhen rendered
not_foundNo registered page matches the URL
unknownUnhandled error in a pilet
loadingA pilet bundle failed to load
pageA page component threw during render

plugins

An array of plugin factories that extend the Pilet API (see Piral Plugins). On piral the standard plugins are already included; on piral-core you list exactly the ones you use:

plugins: [
  createMenuApi(),
  createNotificationsApi(),
  createModalsApi(),
  createDashboardApi(),
  createMyCustomApi(),
]

actions (advanced)

Optional additional global state actions, merged into the store. Most apps don't need this — prefer a plugin for custom capabilities.

Return value: PiralInstance

interface PiralInstance {
  context: GlobalStateContext;   // direct store access (advanced)
  options: PiralInstanceOptions; // the config passed in
}

Pass it to <Piral instance={instance} /> to render.

Full example

import { createInstance, Piral } from 'piral';
import { createMenuApi } from 'piral-menu';
import { createNotificationsApi } from 'piral-notifications';
import * as React from 'react';
import { render } from 'react-dom';
import { AppLayout } from './layout/AppLayout';
import { NotFoundPage } from './layout/NotFoundPage';

const instance = createInstance({
  state: {
    components: { Layout: AppLayout },
    errorComponents: { not_found: NotFoundPage },
  },
  plugins: [createMenuApi(), createNotificationsApi()],
  async requestPilets() {
    const res = await fetch(FEED_URL);
    return (await res.json()).items;
  },
});

render(<Piral instance={instance} />, document.querySelector('#app'));

piral.json

The app shell's project-level CLI configuration. It tells piral debug / piral build how to build this shell, so you don't have to pass the same flags every time. It's optional — Piral applies sensible defaults — and lives in the shell project root. (.piralrc is an accepted alternative filename.)

{
  "entry": "src/index.tsx",
  "bundler": "webpack5",
  "emulatorPort": 1234,
  "publicUrl": "/"
}
FieldPurpose
entryThe shell's entry module (where createInstance + render live)
bundlerWhich installed bundler plugin to use (webpack5, esbuild, rspack, vite, parcel2)
emulatorPortPort for the local debug server
publicUrlBase URL the release is served from (affects asset paths)

CLI flags override piral.json, which in turn overrides the built-in defaults.

pilet.json

The pilet-side counterpart. It records how this pilet builds and which shell it targets, so pilet debug / pilet build / pilet publish work without repeated flags. Optional; lives in the pilet project root. (.piletrc is an accepted alternative filename.)

{
  "app": "my-portal",
  "bundler": "webpack5",
  "port": 1234,
  "schema": "v2",
  "feed": "https://feed.example.com/api/v1/pilets"
}
FieldPurpose
appThe target app shell (its package name) — what the emulator/types come from
bundlerWhich installed bundler plugin to use
portPort for the local debug server
schemaPilet output format (v0, v1, v2, mf)
feedDefault feed URL used by pilet debug --feed and pilet publish

Remember the runtime distinction: app here is a development default for typing and debugging — it doesn't bind the built pilet to that one shell. See Pilet portability.

Environment variables

VariableUsed byDescription
NODE_ENVBothdevelopment or production
PORTCLIDev server port override
PUBLIC_URLApp shellBase URL for asset paths