# networkr install brief

> For AI agents: Cursor, Claude Code, Continue, Aider, Lovable, Bolt, v0, ChatGPT.
> Read end-to-end, then install Networkr on the user's site by following the 3 API calls below.

## Shortcut

If `npx` is available and the `networkr` package resolves (`npm view networkr version`), use it instead — it wraps this entire flow:

```
npx networkr init
```

If unavailable, continue with the manual API flow below. Both paths produce the same final state.

## What you're installing

Networkr is an autonomous SEO blog engine. It researches topics from live Google data, writes articles through a quality-gated 9-stage pipeline, cross-links to sibling sites in the user's network, and publishes to the user's domain. One install, then daily or weekly articles with no further maintenance.

The user's content stays theirs. Auth is a per-network tenant key. The escape hatch is `DELETE /api/sites/:id`.

## Before you start — confirm with the user

- They own the domain (DNS resolves, serves public HTML, not behind an auth wall).
- They have an email address.
- They pick a storage mode:
  - **`hosted`** (default, simplest) — Networkr stores articles; frontend fetches via public API.
  - **`supabase`** | **`pocketbase`** | **`firebase`** | **`appwrite`** | **`mongodb`** — Networkr writes to the user's DB. User supplies credentials.
- The site has real content. An admission gate rejects empty, redirecting, or trust-score-low domains.

## Install — 3 API calls

Base URL: `https://api.networkr.dev`

### Step 1. Audit

```
POST /api/onboard
Content-Type: application/json

{ "domain": "example.com", "email": "user@example.com" }
```

Response (fields trimmed):

```json
{
  "token": "<onboard_token>",
  "seo_score": 72,
  "issues": [{ "type": "critical|warning|info", "message": "..." }],
  "brand_detected": { "accent_color": "#...", "logo_url": "..." },
  "database_detected": { "primary": { "type": "supabase|pocketbase|..." } },
  "flavours": [{ "id": "professional|casual|technical|founder", "description": "..." }]
}
```

Show the user the SEO score, any critical issues, and the flavour options. Let them pick a flavour.

### Step 2. Confirm flavour + preview

```
POST /api/onboard/confirm
Content-Type: application/json

{
  "token": "<from step 1>",
  "flavour": "professional",
  "author_name": "User's Real Name",
  "author_bio": "optional short bio",
  "accent_color": "#8FBCBB",
  "topics": ["optional list"],
  "niche": "optional"
}
```

Response:

```json
{
  "preview_url": "/preview/<token>",
  "sample_article": { "title": "...", "body_html": "...", "cover_image": "data:image/png;base64,..." }
}
```

Open `https://api.networkr.dev<preview_url>` in a browser. Show it to the user. They approve before you continue.

### Step 3. Activate

```
POST /api/onboard/activate
Content-Type: application/json

{ "token": "<same>", "db_type": "hosted" }
```

For non-hosted modes, add the DB credentials:

- **supabase**: `db_url`, `db_key`, `db_table`
- **pocketbase**: `db_url`, `db_password`, `db_collection`
- **firebase**: `firebase_project_id`, `firebase_service_email`, `firebase_service_key`, `db_collection`
- **appwrite**: `appwrite_endpoint`, `appwrite_project_id`, `appwrite_api_key`, `appwrite_database_id`, `appwrite_collection_id`
- **mongodb**: `mongodb_endpoint`, `mongodb_api_key`, `mongodb_database`, `mongodb_collection`

Response:

```json
{
  "success": true,
  "site_id": "example-com",
  "network_id": "...",
  "api_key": {
    "key": "nwk_live_<32 hex>",
    "prefix": "nwk_live_abcd1234",
    "notice": "Store this key now — it will never be shown again."
  }
}
```

⚠️ **`api_key.key` is returned ONCE.** Save it before doing anything else.

**If activate returns `403 "Site rejected from network"`,** read `reasons`:
- Trust score too low — site has thin or suspicious content.
- Redirects detected — pick a domain that resolves directly.
- No live pages — site is down.
- IP address or `.local` / `localhost` — use a real domain.

Report the reasons to the user. They fix and restart from Step 1.

## Save to the user's repo

Create or update `.env.local` at the repo root:

```
NETWORKR_API=https://api.networkr.dev
NETWORKR_SITE_ID=<site_id from step 3>
NETWORKR_KEY=<api_key.key from step 3>
```

Ensure `.env.local` is in `.gitignore`.

Optionally drop a copy of this brief at `.networkr/AGENT.md` so future agents in this repo find the install context.

## Verify

```
GET /api/sites/<site_id>/agent/brief
Authorization: Bearer <api_key.key>
```

Returns a deterministic 10-item checklist with statuses (`ok` / `warning` / `missing` / `info`), each with an exact API call to fix it if needed, plus a `next_step` object. Show the checklist to the user.

## Hosted mode — render the blog

Frontend fetches posts from these **public** endpoints (no auth required):

- `GET /api/blog/<site_id>/posts?limit=20` — list
- `GET /api/blog/<site_id>/posts/<slug>` — single post (body, transparency, lineage, related, prev/next)
- `GET /api/blog/<site_id>/covers/<file>` — cover image
- `GET /api/blog/<site_id>/rss.xml` — RSS feed
- `GET /api/blog/<site_id>/content-policy` — auto-generated transparency policy
- `GET /api/blog/<site_id>/authors/<slug>` — author profile

Reference implementation (Next.js 16): https://github.com/HEIMLANDR/networkr/tree/main/frontend/src/app/blog

Adapt for the user's framework (Next / Astro / Hugo / 11ty / SvelteKit / plain HTML). The API is framework-agnostic.

## Build hook — after install

When the user's site deploys via a static host (Netlify / Vercel / Cloudflare / Render / Fly / GitHub Actions), Networkr needs a build hook URL to trigger rebuilds on every new post.

Ask the user for their build hook URL, then:

```
PUT /api/sites/<site_id>
Authorization: Bearer <key>
Content-Type: application/json

{ "build_hook_url": "https://api.netlify.com/build_hooks/..." }
```

Verify:

```
POST /api/sites/<site_id>/build-hook/test
Authorization: Bearer <key>
```

## Hard rules

- **Never invent endpoints.** Use only what this brief lists. Unknown routes 404.
- **Never edit published posts.** Not supported. To change a post: `DELETE /api/sites/<id>/blog/posts/<slug>` then regenerate.
- **The tenant key scopes to the network, not the site.** Reuse it across sibling sites on the same email.
- **Onboard token expires in 24h.** On `410` error, restart from Step 1.
- **Do not modify user code** outside `.env.local` and `.gitignore` unless the user asks (e.g., they want blog-rendering components scaffolded).
- **Respect rate limits.** `429` = wait 60s, retry once. Do not loop.

## Error contract

- `400` — missing or invalid body field. Read `error`.
- `401` — missing or invalid `Authorization` header.
- `403` — admin-only endpoint hit with a tenant key, or activation rejected by admission gate.
- `404` — wrong network scope, missing site, or invalid token.
- `409` — site already registered for that domain.
- `410` — onboard token expired; restart Step 1.
- `429` — rate-limited; wait 60s and retry once.
- `5xx` — backend issue; retry once with exponential backoff.

## Final message to the user

- Site `<domain>` is registered as `<site_id>`.
- Tenant key saved in `.env.local` (this is their auth going forward).
- Sample article already published (hosted mode).
- First pipeline article generates within a few minutes.
- Daily cadence starts tomorrow (default 06:00 Europe/Stockholm).
- Monitor with:
  ```
  curl https://api.networkr.dev/api/sites/<site_id>/agent/brief \
    -H "Authorization: Bearer $NETWORKR_KEY"
  ```
- To pause cron: `POST /api/sites/<id>/blog/stop`
- To remove entirely: `DELETE /api/sites/<id>`

## Further reading

- [API reference](https://networkr.dev/docs)
- [How it works](https://networkr.dev/how-it-works)
- [Content policy](https://networkr.dev/content-policy)
- [Standards](https://networkr.dev/standards)
