Everything you need before starting:
ideas.asapai.net)https://nowpage-saas.vercel.app
All API endpoints below are relative to this base. Your published pages are served on your custom domain (e.g., https://ideas.asapai.net/your-slug).
Go to your NowPage dashboard. In the left sidebar, click API Keys.
Fill in:
| Field | What to Enter | Example |
|---|---|---|
name | A label so you remember what it's for | Forge VPS |
permissions | Leave empty for full access, or {"publish": true} | {} |
domain_ids | Leave empty for all domains, or specific UUIDs | [] |
expires_in_days | Leave empty for permanent, or a number | (empty) |
The raw key (starts with np_live_) is shown only once. Copy it and save it somewhere safe.
# Create key via API (requires browser session cookie)
curl -X POST https://nowpage-saas.vercel.app/api/keys \
-H "Content-Type: application/json" \
-H "Cookie: your_session_cookie" \
-d '{
"name": "My Automation Key",
"permissions": {"publish": true},
"domain_ids": []
}'
# Response includes raw_key — save it NOW
Before publishing, confirm which domains your API key can access:
curl https://nowpage-saas.vercel.app/api/publish/domains \
-H "Authorization: Bearer np_live_YOUR_KEY_HERE"
[
{
"id": "4f20a885-...",
"full_domain": "ideas.asapai.net",
"status": "active",
"is_custom_domain": true,
"hosting_type": "vercel"
}
]
Use the full_domain value as the domain parameter when publishing.
This is the core operation. Send HTML content and it goes live immediately.
Your HTML should include HC metadata blocks for full compliance:
<!DOCTYPE html>
<html lang="en">
<head>
<title>My Page Title</title>
<script id="hc-metadata" type="application/json">
{
"hc_version": "1.3.3",
"hc_type": "artifact",
"artifact_id": "my-page",
"title": "My Page Title",
"summary": "A brief description of this page",
"tags": ["example", "demo"]
}
</script>
</head>
<body>
<h1>My Page</h1>
<p>Your content here.</p>
</body>
</html>
curl -X POST https://nowpage-saas.vercel.app/api/publish \
-H "Authorization: Bearer np_live_YOUR_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{
"domain": "ideas.asapai.net",
"html_content": "<!DOCTYPE html><html>...your full HTML...</html>",
"tags": ["example", "demo"],
"registry": "auto"
}'
{
"success": true,
"page_id": "abc123-...",
"url": "https://ideas.asapai.net/my-page-title",
"action": "created",
"registry_updated": true
}
Your page is live immediately at the returned URL. No deploy needed.
| Parameter | Required | Type | Description |
|---|---|---|---|
domain | Yes | string | Target domain: "ideas.asapai.net" |
html_content | Yes | string | Full HTML string (min 10 chars) |
slug | No | string | URL slug. Auto-generated from title if empty. |
name | No | string | Page name. Auto-extracted from hc-metadata or <title>. |
folder | No | string | Folder name. Created automatically if missing. |
tags | No | array or string | Array ["a","b"] or comma-string "a,b" |
registry | No | string | "auto" (default), "none", or a registry page UUID |
update_mode | No | string | "version" (default, saves backup), "overwrite", "fail" |
registry is "auto", the system looks at your tags:meeting, standup, transcript → registers in Meeting Intelligence Registryeod, daily, review → registers in EOD Reports RegistryTo update a page, just publish to the same slug again. The update_mode controls what happens:
| Mode | Behavior |
|---|---|
"version" | Saves old content as a version snapshot, then overwrites. Default — recommended. |
"overwrite" | Overwrites without saving a version. Use for scratch/temp pages. |
"fail" | Returns an error if the slug already exists. Use for "create-only" workflows. |
curl -X POST https://nowpage-saas.vercel.app/api/publish \
-H "Authorization: Bearer np_live_YOUR_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{
"domain": "ideas.asapai.net",
"slug": "my-page-title",
"html_content": "<!DOCTYPE html>...updated content...</html>",
"update_mode": "version"
}'
# Response: "action": "updated"
Get notified when pages are published or updated. Great for triggering n8n workflows, Slack alerts, or Forge pipelines.
curl -X POST https://nowpage-saas.vercel.app/api/webhooks \
-H "Cookie: your_session_cookie" \
-H "Content-Type: application/json" \
-d '{
"name": "n8n Page Published",
"url": "https://your-n8n.example.com/webhook/abc123",
"event_types": ["page.published", "page.updated"]
}'
Response includes a secret for HMAC verification. Save it.
When a page is published, your URL receives:
POST https://your-webhook-url.com
Headers:
Content-Type: application/json
X-NowPage-Signature: sha256=abc123def456...
Body:
{
"event": "page.published",
"timestamp": "2026-02-20T10:30:00Z",
"data": {
"page": {
"id": "abc-123",
"url": "https://ideas.asapai.net/my-page",
"title": "My Page",
"tags": ["meeting", "gtm"],
"hc_type": "artifact"
},
"domain": "ideas.asapai.net",
"registry_updated": true
}
}
# Node.js verification example:
const crypto = require('crypto');
const signature = req.headers['x-nowpage-signature'];
const expected = 'sha256=' + crypto
.createHmac('sha256', YOUR_WEBHOOK_SECRET)
.update(JSON.stringify(req.body))
.digest('hex');
if (signature === expected) {
// Verified! Process the event.
}
| Event | Fires When |
|---|---|
page.published | A new page is created via API |
page.updated | An existing page is updated via API |
registry.updated | A registry page is modified (auto or manual) |
For local publishing from your terminal or Claude Code sessions:
The script reads from .env.local in the project root (or parent directories). Required keys: SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY.
node scripts/hc-publish.js \
--domain ideas.asapai.net \
--file /path/to/your-page.html \
--tags "meeting,gtm,sprint" \
--registry auto
| Flag | Description | Default |
|---|---|---|
--domain | Target domain (required) | — |
--file | Path to HTML file (required) | — |
--slug | URL slug | Auto from title |
--name | Page name | Auto from metadata |
--folder | Folder name | Root level |
--tags | Comma-separated tags | None |
--registry | auto, none, or page UUID | auto |
--update | version, overwrite, fail | version |
--dry-run | Preview without saving | — |
--api | Use remote API instead of direct Supabase | — |
--api-url | Base URL for API mode | From .env.local |
pip install "mcp[cli]>=1.0.0" httpx>=0.27.0
Requires Python 3.8+. Verify with: python --version
The MCP server is at:
C:/Users/jason/Downloads/folio-saas/mcp-nowpage/server.py
If you clone the repo elsewhere, update the path accordingly.
You need an np_live_ key (see Step 1). Copy it — you'll paste it in the config.
Open the config file:
# Windows path:
%APPDATA%\Claude\claude_desktop_config.json
# Mac path:
~/Library/Application Support/Claude/claude_desktop_config.json
Add the nowpage server to the mcpServers object:
{
"mcpServers": {
"nowpage": {
"command": "python",
"args": ["C:/Users/jason/Downloads/folio-saas/mcp-nowpage/server.py"],
"env": {
"NP_API_KEY": "np_live_YOUR_KEY_HERE"
}
}
}
}
"nowpage": {...} block alongside them inside the existing mcpServers object. Don't replace the whole file.
Close and reopen Claude Desktop (or use "Reload MCP Servers" if available). You should see "NowPage" in the MCP server list.
In Claude Desktop, try:
"List my NowPage domains"
"Publish a test page to ideas.asapai.net with a hello world"
"Fetch the HTML of ideas.asapai.net/meta-registry"
claude.ai needs an HTTP-based MCP server (not stdio). Use mcp-remote or ngrok to expose your local server:
# Install mcp-remote (bridges stdio → SSE for claude.ai)
npx @anthropic-ai/mcp-remote
# Or use Cloudflare Workers / ngrok to expose the server
# See: https://modelcontextprotocol.io/docs/remote
For always-on access, deploy the MCP server on your VPS:
# On Forge VPS:
cd /opt/forge/mcp-nowpage
pip install "mcp[cli]>=1.0.0" httpx>=0.27.0
# Run with SSE transport (for remote clients)
NP_API_KEY=np_live_YOUR_KEY python server.py --transport sse --port 8765
In claude.ai, go to Settings → Integrations → MCP Servers → Add Server:
| Field | Value |
|---|---|
| Name | NowPage |
| URL | https://your-vps:8765/sse (or ngrok URL) |
| Authentication | None (API key is baked into the server env) |
Both point to the same NowPage API with the same API key. Any page published from Claude Desktop is visible from claude.ai and vice versa. The source of truth is always the Supabase database.
These are the 4 tools available when the NowPage MCP server is connected:
| Parameter | Type | Required | Description |
|---|---|---|---|
domain | string | Yes | Target domain, e.g. "ideas.asapai.net" |
html_content | string | Yes | Full HTML with hc-metadata blocks |
slug | string | No | URL slug (auto from title if empty) |
name | string | No | Page name (auto from metadata) |
folder | string | No | Folder (created if missing) |
tags | string | No | Comma-separated: "meeting,gtm" |
registry | string | No | "auto", "none", or page UUID |
update_mode | string | No | "version", "overwrite", "fail" |
No parameters. Returns all active domains accessible to the API key.
No parameters. Returns 8 HC template references with names and descriptions.
| Parameter | Type | Required | Description |
|---|---|---|---|
domain | string | Yes | Domain name |
slug | string | Yes | Page slug |
Returns raw HTML source (truncated at 50KB for large pages).
| Method | Endpoint | Auth | Purpose |
|---|---|---|---|
| POST | /api/publish | API Key or Session | Publish a page |
| GET | /api/publish/domains | API Key or Session | List accessible domains |
| Method | Endpoint | Auth | Purpose |
|---|---|---|---|
| GET | /api/pages?domain_id=ID | Session | List pages for a domain |
| POST | /api/pages | Session | Create a page |
| PUT | /api/pages?id=ID | Session | Update a page |
| DEL | /api/pages?id=ID | Session | Delete a page |
| Method | Endpoint | Auth | Purpose |
|---|---|---|---|
| GET | /api/keys | API Key or Session | List your keys (no raw values) |
| POST | /api/keys | Session only | Create key (returns raw once) |
| DEL | /api/keys?id=ID | Session only | Revoke a key |
| Method | Endpoint | Auth | Purpose |
|---|---|---|---|
| GET | /api/webhooks | Session | List webhooks |
| POST | /api/webhooks | Session | Create webhook (returns secret once) |
| PUT | /api/webhooks?id=ID | Session | Update webhook |
| DEL | /api/webhooks?id=ID | Session | Delete webhook |
| Method | Endpoint | Auth | Purpose |
|---|---|---|---|
| GET | /api/hc/registries | Session | List your registries |
| POST | /api/hc/update-registry | Session | Add artifact to registry |
| POST | /api/hc/remove-from-registry | Session | Remove artifact from registry |
| POST | /api/hc/analyze | Session | Analyze HTML content with Claude |
| Method | Endpoint | Auth | Purpose |
|---|---|---|---|
| GET | /api/templates | Public | List HC templates |
| GET | /api/page-versions?page_id=ID | Session | Get version history |
| GET | /api/folders?domain_id=ID | Session | List folders |
| GET | /api/navigation?domain=D | Public | Get navigation JSON |
| POST | /api/chat | Public | Claude proxy (keeps API key server-side) |
| Symptom | Cause | Fix |
|---|---|---|
| 401 Unauthorized | Missing or invalid API key | Check Authorization: Bearer np_live_... header |
| 403 Forbidden | Key lacks permission or domain access | Create key with permissions: {} (all) or add the domain to domain_ids |
| 400 "Required fields" | Missing domain or html_content | Both are required in POST /api/publish |
| MCP server not showing | Config path wrong or Python not found | Verify python is on PATH and the args path exists |
| "NP_API_KEY not set" | Env var missing in MCP config | Add "env": {"NP_API_KEY": "np_live_..."} to config |
| Page published but not in registry | Tags don't match any registry pattern | Add meeting or eod tag, or use registry: "none" intentionally |
| Registry row not visible | Missing <tbody id="meeting-feed"> | Registry template must have the correct tbody ID for injection |
| Version history missing | First publish doesn't create a version | Normal — versions are saved on updates, not first create |
# 1. Check domains
curl -s https://nowpage-saas.vercel.app/api/publish/domains \
-H "Authorization: Bearer np_live_YOUR_KEY" | python -m json.tool
# 2. Publish a test page
curl -s -X POST https://nowpage-saas.vercel.app/api/publish \
-H "Authorization: Bearer np_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"domain": "ideas.asapai.net",
"html_content": "<html><head><title>API Test</title></head><body><h1>It works!</h1></body></html>",
"slug": "api-test-delete-me",
"registry": "none"
}' | python -m json.tool
# 3. Verify the page is live
curl -s -o /dev/null -w "%{http_code}" https://ideas.asapai.net/api-test-delete-me