This skill provides the unified, authoritative standard for building, configuring, deploying, and managing all static sites and web applications across the Hanzo ecosystem.
Category: Hanzo Ecosystem Related Skills: hanzo/hanzo-deploy.md, hanzo/hanzo-website.md, hanzo/hanzo-static.md, hanzo/hanzo-commerce.md, hanzo/hanzo-iam.md
This skill provides the unified, authoritative standard for building, configuring, deploying, and managing all static sites and web applications across the Hanzo ecosystem. It covers:
hanzo.yml (or hanzo.config.toml, ~/.hanzo/settings.json, hanzo.config.ts)..github/workflows and .hanzo/workflows on push to forge git.hanzo.ai).bin/site <slug> <dir>, Docker container images (ghcr.io/hanzoai/static:0.5.15), and native /v1/projects/sites/deploy.https://api.hanzo.ai/v1/commerce and https://pay.hanzo.ai) backed by Square (Sandbox & Production), Crypto, and Wire.api.hanzo.ai/v1/commerce / pay.hanzo.ai) using Square, Crypto, or Wire.hanzo.yml (or hanzo.config.ts / hanzo.config.toml).git.hanzo.ai (the forge) reads .hanzo/workflows and .github/workflows..github/workflows..hanzo/workflows synchronized with .github/workflows (e.g. symlinked via ln -s ../.github/workflows .hanzo/workflows) so pushes to both remotes trigger identical CI/CD.https://hanzo.id) via OIDC PKCE, and billing is managed at https://billing.hanzo.ai. `` https://pay.hanzo.ai/?plan=<planId>&return=<returnUrl> ``
hanzo.yml)Place hanzo.yml in the root of any site or application repo:
name: agency
slug: agency
version: 0.1.6
type: site # site | app | service
framework:
name: vite # vite | next | astro | static | react
preset: react
buildCommand: pnpm build
outputDir: dist # dist | out | build | public
singlePageApp: true # true for BrowserRouter / SPA routing fallback
routing:
domain: hanzo.agency
aliases:
- www.hanzo.agency
- agency.hanzo.ai
deploy:
plane: sites # sites (S3/SeaweedFS static plane) | k8s (container image)
publishScript: https://git.hanzo.ai/hanzoai/ci/.github/actions/site@v1
image: ghcr.io/hanzoai/agency # when built as container
kubernetes:
namespace: hanzo
service: agency
port: 3000
commerce:
org: hanzo
checkoutUrl: https://pay.hanzo.ai
commerceApi: https://api.hanzo.ai/v1/commerce
providers:
- square # Square Sandbox/Production Web Payments SDK
- crypto # BTC, ETH, USDC
- wire # Bank wire (ACH / SWIFT)
disallowed:
- stripe # STRICT RULE: No Stripe
iam:
issuer: https://hanzo.id
clientId: hanzo-agency
billingPortal: https://billing.hanzo.ai
calendar:
bookingUrl: https://calendar.app.google/z1YsZQrqR4s6jQqD8
analytics:
googleAnalyticsId: G-BCXWVKFL1K
insightsUrl: https://api.hanzo.ai/v1/event
hanzo.config.ts)For TypeScript packages using @hanzo/ai or hanzo:
import { defineConfig } from '@hanzo/config';
export default defineConfig({
name: 'agency',
slug: 'agency',
type: 'site',
framework: 'vite',
build: {
command: 'pnpm build',
output: 'dist',
spa: true,
},
commerce: {
org: 'hanzo',
checkoutUrl: 'https://pay.hanzo.ai',
providers: ['square', 'crypto', 'wire'],
},
iam: {
issuer: 'https://hanzo.id',
clientId: 'hanzo-agency',
},
});
bin/site via CI Action)The static export plane sends zero runtime compute to Kubernetes; files are served directly from S3/SeaweedFS edge cache:
POST https://api.hanzo.ai/v1/projects (creates or confirms project slug).POST https://api.hanzo.ai/v1/projects/<slug>/deployments -> returns {id, bucket, prefix, upload: {url, fields}}.POST https://api.hanzo.ai/v1/projects/<slug>/deployments/<id>/complete with the key manifest.ghcr.io/hanzoai/static:0.5.15)For deployments requiring a Kubernetes Service and Ingress:
# Dockerfile
FROM node:22 AS build
WORKDIR /src
RUN npm i -g pnpm@9
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
FROM ghcr.io/hanzoai/static:0.5.15
COPY --from=build /src/dist /public
ENTRYPOINT ["/static", "-spa"]
/v1/projects/sites/deploy)Agents and tools can programmatically publish a static site in one API call:
curl -X POST "https://api.hanzo.ai/v1/projects/sites/deploy" \
-H "Authorization: Bearer $HANZO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"slug": "my-site",
"name": "My Site",
"files": [
{"path": "index.html", "content": "<!DOCTYPE html><html>...</html>"},
{"path": "style.css", "content": "body { background: #000; color: #fff; }"}
]
}'
User clicks "Get Started" / Plan CTA
│
├──> https://pay.hanzo.ai/?plan=agency&return=https://hanzo.agency/payment-success
│ │
│ ├── Square Web Payments SDK (Sandbox or Production)
│ ├── Crypto Rails (BTC, ETH, USDC)
│ └── Bank Wire Instructions
│
└──> POST https://api.hanzo.ai/v1/billing/topup/token
│
└── Hanzo Commerce Engine (authorizes & captures via Square)
src/lib/commerce.ts)const PAY = 'https://pay.hanzo.ai';
const COMMERCE = 'https://api.hanzo.ai/v1/commerce';
const ORG = 'hanzo';
export function checkoutUrl(planId?: string, returnPath = '/payment-success'): string {
if (!planId) return PAY;
const back = new URL(returnPath, window.location.origin).toString();
return `${PAY}/?plan=${encodeURIComponent(planId)}&return=${encodeURIComponent(back)}`;
}
https://billing.hanzo.ai or https://hanzo.id.https://hanzo.id (/v1/iam/oauth/authorize).hanzo.yml exists and defines slug, framework, routing, commerce, and iam..github/workflows and .hanzo/workflows are synchronized.@stripe/*), scripts (js.stripe.com), or keys exist in codebase.checkoutUrl(planId) resolving to pay.hanzo.ai.GET /v1/commerce/org?org=hanzo.G-BCXWVKFL1K or repo tag) tracks both initial load and SPA route changes.https://hanzo.id or use Hanzo IAM OIDC.https://calendar.app.google/z1YsZQrqR4s6jQqD8).