Inspired by the cookbook github action deployment guide, permaweb-deploy is a Node.js command-line tool designed to streamline the deployment of web applications to the permaweb using Arweave. It uploads your build folder or a single file, creates Arweave manifests, and updates ArNS (Arweave Name Service) records via ANT (Arweave Name Token) with the transaction ID.
- Turbo SDK Integration: Uses Turbo SDK for fast, reliable file uploads to Arweave
- On-Demand Payment: Pay with ARIO or Base-ETH tokens on-demand during upload
- Arweave Manifest v0.2.0: Creates manifests with fallback support for SPAs
- ArNS Updates: Updates ArNS records via ANT with new transaction IDs and metadata
- Automated Workflow: Integrates with GitHub Actions for continuous deployment
- Git Hash Tagging: Automatically tags deployments with Git commit hashes
- 404 Fallback Detection: Automatically detects and sets 404.html as fallback
- Network Support: Supports mainnet, testnet, and custom ARIO process IDs
- Flexible Deployment: Supports deploying a folder or a single file
- Modern CLI: Built with oclif for a robust command-line experience
- TypeScript: Fully typed for better developer experience
Install the package using pnpm (recommended):
pnpm add -D permaweb-deployOr with npm:
npm install --save-dev permaweb-deployOr with yarn:
yarn add --dev permaweb-deploy-
For Arweave signer (default): Encode your Arweave wallet key in base64 format and set it as a GitHub secret:
base64 -i wallet.json | pbcopy -
For Ethereum/Polygon/KYVE signers: Use your raw private key (no encoding needed) as the
DEPLOY_KEY. -
Ensure that the secret name for the encoded wallet or private key is
DEPLOY_KEY.
Command Menu:
Simply run the CLI for an interactive command selector:
permaweb-deploy
# or explicitly
permaweb-deploy interactiveThis shows a menu with options:
- Deploy to Permaweb - Start the deployment wizard
- Show Help - Display help information
- Exit - Exit the CLI
Interactive Deploy (Guided):
Run the deploy command without arguments to be guided through all deployment options:
permaweb-deploy deployThis will prompt you for:
- ArNS name
- Wallet method (file, string, or environment variable)
- Signer type (Arweave, Ethereum, Polygon, KYVE)
- What to deploy (folder or file)
- Advanced options (optional: undername, TTL, network)
Use flags for faster, scriptable deployments:
# Basic deployment with wallet file
permaweb-deploy deploy --arns-name my-app --wallet ./wallet.jsonDeploy using private key directly:
permaweb-deploy deploy --arns-name my-app --private-key "$(cat wallet.json)"Deploy using environment variable:
DEPLOY_KEY=$(base64 -i wallet.json) permaweb-deploy deploy --arns-name my-appDeploy a specific folder:
permaweb-deploy deploy --arns-name my-app --wallet ./wallet.json --deploy-folder ./buildDeploy a single file:
permaweb-deploy deploy --arns-name my-app --wallet ./wallet.json --deploy-file ./path/to/file.txtDeploy to an undername (subdomain):
permaweb-deploy deploy --arns-name my-app --wallet ./wallet.json --undername stagingDeploy with a custom TTL:
permaweb-deploy deploy --arns-name my-app --wallet ./wallet.json --ttl-seconds 7200Deploy using Ethereum wallet (file):
permaweb-deploy deploy --arns-name my-app --sig-type ethereum --wallet ./private-key.txtDeploy using Ethereum wallet (direct key):
permaweb-deploy deploy --arns-name my-app --sig-type ethereum --private-key "0x1234..."Use on-demand payment to automatically fund uploads with ARIO or Base-ETH tokens when your Turbo balance is insufficient:
Deploy with ARIO on-demand payment:
permaweb-deploy deploy --arns-name my-app --wallet ./wallet.json --on-demand ario --max-token-amount 1.5Deploy with Base-ETH on-demand payment (using Ethereum signer):
permaweb-deploy deploy --arns-name my-app --sig-type ethereum --private-key "0x..." --on-demand base-eth --max-token-amount 0.1On-Demand Payment Options:
--on-demand: Token to use for on-demand payment (arioorbase-eth)--max-token-amount: Maximum token amount to spend (in native token units, e.g.,1.5for 1.5 ARIO or0.1for 0.1 ETH)
How it works:
- Checks your Turbo balance before upload
- If balance is insufficient, converts tokens to Turbo credits on-demand
- Automatically adds a 10% buffer (
topUpBufferMultiplier: 1.1) for reliability - Proceeds with upload once funded
Token compatibility:
- ARIO: Works with Arweave signer
- Base-ETH: Works with Ethereum signer (Base Network)
--arns-name, -n(required): The ArNS name to update--ario-process, -p: ARIO process to use (mainnet,testnet, or a custom process ID). Default:mainnet--deploy-folder, -d: Folder to deploy. Default:./dist--deploy-file, -f: Deploy a single file instead of a folder--undername, -u: ANT undername to update. Default:@--ttl-seconds, -t: TTL in seconds for the ANT record (60-86400). Default:60--sig-type, -s: Signer type for deployment. Choices:arweave,ethereum,polygon,kyve. Default:arweave--wallet, -w: Path to wallet file (JWK for Arweave, private key for Ethereum/Polygon/KYVE)--private-key, -k: Private key or JWK JSON string (alternative to--wallet)--on-demand: Enable on-demand payment with specified token. Choices:ario,base-eth--max-token-amount: Maximum token amount for on-demand payment (used with--on-demand)
Add deployment scripts to your package.json:
{
"scripts": {
"build": "vite build",
"deploy": "pnpm build && permaweb-deploy deploy --arns-name <ARNS_NAME>",
"deploy:staging": "pnpm build && permaweb-deploy deploy --arns-name <ARNS_NAME> --undername staging",
"deploy:testnet": "pnpm build && permaweb-deploy deploy --arns-name <ARNS_NAME> --ario-process testnet",
"deploy:on-demand": "pnpm build && permaweb-deploy deploy --arns-name <ARNS_NAME> --on-demand ario --max-token-amount 1.5"
}
}Then deploy with:
DEPLOY_KEY=$(base64 -i wallet.json) pnpm deployOr with on-demand payment:
DEPLOY_KEY=$(base64 -i wallet.json) pnpm deploy:on-demandThe easiest way to integrate permaweb-deploy into your CI/CD pipeline is using our official GitHub Action.
- uses: permaweb/permaweb-deploy@v1
with:
deploy-key: ${{ secrets.DEPLOY_KEY }}
arns-name: myapp
deploy-folder: ./distAutomatically deploy preview builds for each pull request. The preview mode auto-generates an undername from the PR number and posts a comment with the preview URL:
name: Deploy PR Preview
on:
pull_request:
types: [opened, synchronize]
jobs:
deploy-preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Deploy Preview
uses: permaweb/permaweb-deploy@v1
with:
deploy-key: ${{ secrets.DEPLOY_KEY }}
arns-name: myapp
preview: 'true'
github-token: ${{ secrets.GITHUB_TOKEN }}
deploy-folder: ./distWhen preview is enabled, the action will:
- Auto-generate an undername like
pr-123from the PR number - Post a comment on the PR with the preview URL
- Update the comment on subsequent pushes instead of creating new ones
Deploy to your base ArNS name when pushing to main:
name: Deploy to Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Deploy to Permaweb
uses: permaweb/permaweb-deploy@v1
with:
deploy-key: ${{ secrets.DEPLOY_KEY }}
arns-name: myapp
deploy-folder: ./dist- name: Deploy with ARIO on-demand
uses: permaweb/permaweb-deploy@v1
with:
deploy-key: ${{ secrets.DEPLOY_KEY }}
arns-name: myapp
deploy-folder: ./dist
on-demand: ario
max-token-amount: '2.0'You can also use the CLI directly in your workflows:
Basic Workflow:
name: Deploy to Permaweb
on:
push:
branches:
- main
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- run: pnpm install
- run: pnpm deploy
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}With On-Demand Payment:
name: Deploy to Permaweb with On-Demand Payment
on:
push:
branches:
- main
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- run: pnpm install
- run: pnpm build
- name: Deploy with ARIO on-demand
run: permaweb-deploy deploy --arns-name my-app --on-demand ario --max-token-amount 2.0
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
# Or deploy with Ethereum and Base-ETH:
# - name: Deploy with Base-ETH on-demand
# run: |
# permaweb-deploy deploy \
# --arns-name my-app \
# --sig-type ethereum \
# --on-demand base-eth \
# --max-token-amount 0.2
# env:
# DEPLOY_KEY: ${{ secrets.ETH_PRIVATE_KEY }}# Install dependencies
pnpm install
# Build the project
pnpm build
# Run in development mode
pnpm dev
# Run tests
pnpm test
# Run linter
pnpm lint
# Format code
pnpm formatpermaweb-deploy/
├── src/
│ ├── commands/ # oclif commands
│ │ └── deploy.ts
│ ├── types/ # TypeScript type definitions
│ │ └── index.ts
│ ├── utils/ # Utility functions
│ │ ├── constants.ts
│ │ ├── signer.ts
│ │ ├── uploader.ts
│ │ └── __tests__/ # Unit tests
│ └── index.ts # Main entry point
├── bin/ # Executable scripts
│ ├── run.js
│ └── dev.js
├── .changeset/ # Changesets configuration
├── .husky/ # Git hooks
└── dist/ # Build output
- Dedicated Wallet: Always use a dedicated wallet for deployments to minimize security risks
- Wallet Encoding: Arweave wallets must be base64 encoded to be used in the deployment script
- ArNS Name: The ArNS Name must be passed so that the ANT Process can be resolved to update the target undername or root record
- Turbo Credits: Ensure your wallet has sufficient Turbo Credits, or use on-demand payment for automatic funding
- On-Demand Limits: Set reasonable
--max-token-amountlimits to prevent unexpected costs - Secret Management: Keep your
DEPLOY_KEYsecret secure and never commit it to your repository - Build Security: Always check your build for exposed environmental secrets before deployment, as data on Arweave is permanent
- Error: "DEPLOY_KEY environment variable not set": Verify your base64 encoded wallet is set as the
DEPLOY_KEYenvironment variable - Error: "deploy-folder does not exist": Check that your build folder exists and the path is correct
- Error: "deploy-file does not exist": Check that your build file exists and the path is correct
- Error: "ArNS name does not exist": Verify the ArNS name is correct and exists in the specified network
- Upload timeouts: Files have a timeout for upload. Large files may fail and require optimization
- Insufficient Turbo Credits: Use
--on-demandwith--max-token-amountto automatically fund uploads when balance is low - On-demand payment fails: Ensure your wallet has sufficient tokens (ARIO or Base-ETH) and the token type matches your signer (
ariowith Arweave,base-ethwith Ethereum)
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests and linter:
pnpm test && pnpm lint - Create a changeset:
pnpm changeset - Commit your changes using conventional commits
- Push and create a pull request
This project uses Conventional Commits. Commit messages should follow this format:
type(scope): subject
body (optional)
Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
We use changesets for version management. When making changes:
pnpm changesetFollow the prompts to describe your changes.
- @ar.io/sdk - For ANT operations and ArNS management
- @ardrive/turbo-sdk - For fast file uploads to Arweave
- @permaweb/aoconnect - For AO network connectivity
- @oclif/core - CLI framework
- mime-types - MIME type detection
ISC
NickJ202