pfy pilet
pfy pilet scaffolds a new pilet and uploads built pilets to the Manager. A pilet is a microfrontend module: a JavaScript bundle that a Piral-based application shell loads at runtime from the Manager's pilet feed.
Commands
pfy pilet create
Scaffold a new pilet package, a framework-neutral setup(api) skeleton, ready to build and serve locally.
Usage:
pfy pilet create <name> [--framework neutral|vue|react] [--dir <parent-dir>] [--project <slug>]Flags:
| Flag | Required | Description |
|---|---|---|
--framework | No | Adapter to target: neutral (default), vue, or react; the setup(api) contract is identical |
--dir | No | Parent directory to create the pilet folder under (default: .) |
--project | No | Project slug used to scope the package name (defaults to project.yaml's project_name) |
The command refuses to overwrite a non-empty target directory.
Example:
pfy pilet create dashboard --framework vueCreated pilet @my-saas/dashboard in dashboard
Next: cd dashboard && npm install && npm run build
Then serve it locally: pfy dev proxy --pilet-bundle dist/index.jspfy pilet upload
Upload a pilet package to the ProductifyFW Manager.
Usage:
pfy pilet upload \
--project PROJECT_SLUG \
--name PILET_NAME \
--version VERSION \
--file PATH_TO_FILE \
[--description DESCRIPTION]Flags:
| Flag | Alias | Required | Description |
|---|---|---|---|
--project | - | No* | Project slug (resolved to an ID) |
--project-id | - | No* | Project ID (overrides --project) |
--name | - | Yes | Pilet package name (e.g., @myapp/dashboard) |
--version | - | Yes | Semantic version (e.g., 1.0.0) |
--file | - | Yes | Path to the pilet package file |
--description | - | No | Optional description of the pilet |
* One project selector is needed: --project, --project-id, or a project_id in project.yaml.
Examples:
Upload a simple pilet:
pfy pilet upload \
--project my-saas \
--name @myapp/dashboard \
--version 1.0.0 \
--file dist/index.jsUpload with description:
pfy pilet upload \
--project-id 550e8400-e29b-41d4-a716-446655440000 \
--name @myapp/settings \
--version 2.1.5 \
--file dist/index.js \
--description "Settings management module"Upload using environment variables:
export PFY_MANAGER_URL=https://manager.example.com
export PFY_MANAGER_TOKEN=your-pat-token
pfy pilet upload \
--project-id 550e8400-e29b-41d4-a716-446655440000 \
--name @myapp/checkout \
--version 3.0.0 \
--file dist/index.jsAuthentication:
Requires a valid Personal Access Token (PAT). Set via:
--tokenflagPFY_MANAGER_TOKENenvironment variable- Login with
pfy login
Output:
Success:
Pilet uploaded successfully: @myapp/dashboard@1.0.0Verbose mode (-v):
Connecting to ProductifyFW manager...
Uploading pilet '@myapp/dashboard' version '1.0.0' to project '550e8400-e29b-41d4-a716-446655440000'...
Pilet uploaded successfully: @myapp/dashboard@1.0.0
Project ID: 550e8400-e29b-41d4-a716-446655440000
File: dist/index.js
Description: Dashboard widget modulePilet Package Format
Pilets are typically JavaScript bundles created by the Piral CLI:
# Build with piral-cli
pilet build
# Results in dist/index.jsThe package should be compatible with Piral v2 specification.
Workflow
1. Build Your Pilet
cd my-pilet
pnpm install
pnpm build # or: pilet build2. Upload to Manager
pfy pilet upload \
--project-id YOUR_PROJECT_ID \
--name my-pilet \
--version 1.0.0 \
--file dist/index.js3. Enable in Application
Enable the pilet for the application in the Manager UI (the application's modules settings). See Pilet API.
4. Verify Loading
The pilet will be included in the feed response:
curl http://your-app.example.com/pilet-feed/APP_IDResponse:
{
"items": [
{
"name": "my-pilet",
"version": "1.0.0",
"link": "/pilets/PROJECT_ID/my-pilet/1.0.0",
"hash": "abc123...",
"spec": "v2"
}
]
}Integration with CI/CD
GitHub Actions Example
name: Deploy Pilet
on:
push:
tags:
- "v*"
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: pnpm install
- name: Build pilet
run: pnpm build
- name: Upload to Productify
env:
PFY_MANAGER_URL: ${{ secrets.MANAGER_URL }}
PFY_MANAGER_TOKEN: ${{ secrets.MANAGER_TOKEN }}
run: |
VERSION=${GITHUB_REF#refs/tags/v}
pfy pilet upload \
--project-id ${{ secrets.PROJECT_ID }} \
--name @myapp/my-pilet \
--version $VERSION \
--file dist/index.jsGitLab CI Example
deploy:
stage: deploy
script:
- pnpm install
- pnpm build
- |
pfy pilet upload \
--project-id $PROJECT_ID \
--name @myapp/my-pilet \
--version $CI_COMMIT_TAG \
--file dist/index.js
only:
- tags
variables:
PFY_MANAGER_URL: $MANAGER_URL
PFY_MANAGER_TOKEN: $MANAGER_TOKENBest Practices
Versioning
Use semantic versioning:
# Patch release
pfy pilet upload --version 1.0.1 ...
# Minor release
pfy pilet upload --version 1.1.0 ...
# Major release
pfy pilet upload --version 2.0.0 ...Scoped Packages
Use scoped package names for organization:
pfy pilet upload --name @mycompany/feature-dashboard ...
pfy pilet upload --name @mycompany/feature-settings ...Descriptions
Include helpful descriptions:
pfy pilet upload \
--description "User dashboard with charts and metrics" \
...Validation
Verify the upload was successful. The feed route needs no token: the proxy serves /pilet-feed/* ahead of the sign-in portal and adds the proxy secret itself.
# Check the pilet feed through the proxied entrypoint
curl https://your-app.example.com/pilet-feed/APP_IDTroubleshooting
Upload Failed
A non-2xx response is reported with the status and the (truncated) response body:
Error: failed to upload pilet: upload failed with status 401: ...Solution: Check the PAT with pfy whoami. A 409 or similar with a body about an existing version means that name@version was already uploaded; bump the version.
A 401 whose body says no authenticated user is not a bad PAT. The Manager's /pilets/* routes take identity only from the X-Token-* headers a browser login produces, so a PAT does not authenticate them through a rendered Manager vhost, however valid it is. Upload through the Manager UI, or point --server at a Manager entrypoint that is not fronted by a rendered vhost. See Known Issues.
File Not Found
Error: failed to upload pilet: failed to open file: open dist/index.js: no such file or directorySolution: Check the --file path (relative to the current directory, or absolute).
Related Commands
pfy login- Authenticate with the managerpfy project- Manage projectspfy application- Manage applications