Skip to content

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:

bash
pfy pilet create <name> [--framework neutral|vue|react] [--dir <parent-dir>] [--project <slug>]

Flags:

FlagRequiredDescription
--frameworkNoAdapter to target: neutral (default), vue, or react; the setup(api) contract is identical
--dirNoParent directory to create the pilet folder under (default: .)
--projectNoProject 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:

bash
pfy pilet create dashboard --framework vue
Created 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.js

pfy pilet upload ​

Upload a pilet package to the ProductifyFW Manager.

Usage:

bash
pfy pilet upload \
  --project PROJECT_SLUG \
  --name PILET_NAME \
  --version VERSION \
  --file PATH_TO_FILE \
  [--description DESCRIPTION]

Flags:

FlagAliasRequiredDescription
--project-No*Project slug (resolved to an ID)
--project-id-No*Project ID (overrides --project)
--name-YesPilet package name (e.g., @myapp/dashboard)
--version-YesSemantic version (e.g., 1.0.0)
--file-YesPath to the pilet package file
--description-NoOptional description of the pilet

* One project selector is needed: --project, --project-id, or a project_id in project.yaml.

Examples:

Upload a simple pilet:

bash
pfy pilet upload \
  --project my-saas \
  --name @myapp/dashboard \
  --version 1.0.0 \
  --file dist/index.js

Upload with description:

bash
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:

bash
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.js

Authentication:

Requires a valid Personal Access Token (PAT). Set via:

  1. --token flag
  2. PFY_MANAGER_TOKEN environment variable
  3. Login with pfy login

Output:

Success:

Pilet uploaded successfully: @myapp/dashboard@1.0.0

Verbose 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 module

Pilet Package Format ​

Pilets are typically JavaScript bundles created by the Piral CLI:

bash
# Build with piral-cli
pilet build

# Results in dist/index.js

The package should be compatible with Piral v2 specification.

Workflow ​

1. Build Your Pilet ​

bash
cd my-pilet
pnpm install
pnpm build  # or: pilet build

2. Upload to Manager ​

bash
pfy pilet upload \
  --project-id YOUR_PROJECT_ID \
  --name my-pilet \
  --version 1.0.0 \
  --file dist/index.js

3. 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:

bash
curl http://your-app.example.com/pilet-feed/APP_ID

Response:

json
{
  "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 ​

yaml
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.js

GitLab CI Example ​

yaml
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_TOKEN

Best Practices ​

Versioning ​

Use semantic versioning:

bash
# 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:

bash
pfy pilet upload --name @mycompany/feature-dashboard ...
pfy pilet upload --name @mycompany/feature-settings ...

Descriptions ​

Include helpful descriptions:

bash
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.

bash
# Check the pilet feed through the proxied entrypoint
curl https://your-app.example.com/pilet-feed/APP_ID

Troubleshooting ​

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 directory

Solution: Check the --file path (relative to the current directory, or absolute).

See Also ​