From fe04731fc1c567ba85cba857322ab8348541344b Mon Sep 17 00:00:00 2001 From: Trezy Date: Fri, 24 Apr 2026 10:14:30 -0500 Subject: [PATCH] docs: fix broken links --- packages/docs/docs/README.md | 22 ++++---- .../docs/getting-started/authentication.md | 10 ++-- .../docs/getting-started/configuration.md | 6 +-- .../docs/docs/getting-started/dashboard.md | 18 +++---- .../docs/getting-started/deployment/docker.md | 2 +- .../docs/getting-started/deployment/other.md | 2 +- .../getting-started/deployment/railway.md | 2 +- .../getting-started/production-deployment.md | 16 +++--- .../docs/docs/getting-started/quickstart.md | 4 +- packages/docs/docs/guides/admin/api-keys.md | 8 +-- packages/docs/docs/guides/admin/event-logs.md | 18 +++---- .../docs/docs/guides/admin/permissions.md | 4 +- .../docs/guides/database/database-setup.md | 4 +- .../database/postgres-to-sqlite-migration.md | 4 +- .../database/sqlite-to-postgres-migration.md | 4 +- .../docs/docs/guides/features/api-clients.md | 18 +++---- .../guides/features/developing-plugins.md | 4 +- .../docs/docs/guides/features/labelers.md | 8 +-- packages/docs/docs/guides/features/plugins.md | 4 +- .../docs/docs/guides/indexing/backfill.md | 6 +-- .../docs/docs/guides/indexing/index-hooks.md | 22 ++++---- .../docs/docs/guides/indexing/lexicons.md | 14 ++--- packages/docs/docs/guides/scripting.md | 30 +++++------ .../docs/guides/scripting/algolia-sync.md | 2 +- .../docs/docs/guides/scripting/batch-save.md | 4 +- .../docs/guides/scripting/cascading-delete.md | 2 +- .../guides/scripting/complex-mutations.md | 2 +- .../docs/guides/scripting/create-record.md | 2 +- .../docs/guides/scripting/expanded-query.md | 2 +- .../docs/docs/guides/scripting/get-record.md | 2 +- .../docs/guides/scripting/list-or-fetch.md | 4 +- .../docs/guides/scripting/meilisearch-sync.md | 4 +- .../docs/guides/scripting/paginated-list.md | 2 +- .../docs/guides/scripting/sidecar-records.md | 2 +- .../docs/guides/scripting/update-or-delete.md | 4 +- .../docs/guides/scripting/upsert-record.md | 2 +- .../docs/docs/reference/admin/admin-api.md | 30 +++++------ .../docs/docs/reference/admin/api-clients.md | 2 +- .../docs/docs/reference/admin/api-keys.md | 2 +- .../docs/docs/reference/admin/backfill.md | 2 +- packages/docs/docs/reference/admin/events.md | 2 +- .../docs/docs/reference/admin/labelers.md | 2 +- .../docs/docs/reference/admin/lexicons.md | 6 +-- packages/docs/docs/reference/admin/plugins.md | 2 +- packages/docs/docs/reference/admin/users.md | 2 +- packages/docs/docs/reference/architecture.md | 2 +- packages/docs/docs/reference/glossary.md | 10 ++-- .../docs/docs/reference/lua/atproto-api.md | 2 +- .../docs/docs/reference/lua/database-api.md | 4 +- packages/docs/docs/reference/lua/http-api.md | 2 +- packages/docs/docs/reference/lua/json-api.md | 2 +- .../docs/reference/lua/utility-globals.md | 2 +- .../docs/docs/reference/troubleshooting.md | 12 ++--- packages/docs/docs/reference/xrpc-api.md | 6 +-- packages/docs/docs/tutorials/statusphere.md | 8 +-- packages/docs/sidebars.ts | 52 +++++++++---------- 56 files changed, 208 insertions(+), 208 deletions(-) diff --git a/packages/docs/docs/README.md b/packages/docs/docs/README.md index c6cc4a1..1dfda7a 100644 --- a/packages/docs/docs/README.md +++ b/packages/docs/docs/README.md @@ -1,20 +1,20 @@ # HappyView -HappyView is the best way to build an [AppView](https://atproto.com/guides/glossary#app-view) for the [AT Protocol](https://atproto.com). Upload your [lexicon](reference/glossary.md#atproto-terms) schemas and get a fully functional AppView, complete with [XRPC](reference/glossary.md#atproto-terms) endpoints, OAuth, real-time network sync, and historical [backfill](guides/backfill.md), without writing a single line of server code. +HappyView is the best way to build an [AppView](https://atproto.com/guides/glossary#app-view) for the [AT Protocol](https://atproto.com). Upload your [lexicon](reference/glossary.md#atproto-terms) schemas and get a fully functional AppView, complete with [XRPC](reference/glossary.md#atproto-terms) endpoints, OAuth, real-time network sync, and historical [backfill](guides/indexing/backfill.md), without writing a single line of server code. Building an AppView from scratch means wiring up real-time event streams, record storage, XRPC routing, OAuth flows, and PDS write proxying before you can even think about your application. HappyView handles all of that. Define your data model with lexicons, add custom logic with Lua scripts when you need it, and ship your app. ## Features -- **Schema-driven endpoints:** Upload a [lexicon](guides/lexicons.md) and HappyView generates XRPC query and procedure routes, storage, and indexing from it — updatable at runtime with no restart. +- **Schema-driven endpoints:** Upload a [lexicon](guides/indexing/lexicons.md) and HappyView generates XRPC query and procedure routes, storage, and indexing from it — updatable at runtime with no restart. -- **Network sync built in:** Real-time record streaming via [Jetstream](https://github.com/bluesky-social/jetstream), historical [backfill](guides/backfill.md) from each user's PDS, and atproto OAuth with DPoP-bound proxy writes back to the PDS. +- **Network sync built in:** Real-time record streaming via [Jetstream](https://github.com/bluesky-social/jetstream), historical [backfill](guides/indexing/backfill.md) from each user's PDS, and atproto OAuth with DPoP-bound proxy writes back to the PDS. -- **Customize with Lua, hooks, and plugins:** [Lua scripts](guides/scripting.md) for query and procedure logic, [index hooks](guides/index-hooks.md) that fire on every record change, WASM [plugins](guides/plugins.md) for external platform integration, and [labeler](guides/labelers.md) subscriptions for content moderation. +- **Customize with Lua, hooks, and plugins:** [Lua scripts](guides/scripting.md) for query and procedure logic, [index hooks](guides/indexing/index-hooks.md) that fire on every record change, WASM [plugins](guides/features/plugins.md) for external platform integration, and [labeler](guides/features/labelers.md) subscriptions for content moderation. -- **Protocol-native:** Works with any PDS, resolves DIDs through the directory, and fetches [network lexicons](guides/lexicons.md#network-lexicons) via DNS authority resolution. +- **Protocol-native:** Works with any PDS, resolves DIDs through the directory, and fetches [network lexicons](guides/indexing/lexicons.md#network-lexicons) via DNS authority resolution. -- **Full admin surface:** Built-in [dashboard](getting-started/dashboard.md) and [admin API](reference/admin-api.md) for managing lexicons, users, API keys, API clients, backfill jobs, and plugins. +- **Full admin surface:** Built-in [dashboard](getting-started/dashboard.md) and [admin API](reference/admin/admin-api.md) for managing lexicons, users, API keys, API clients, backfill jobs, and plugins. ## Design Principles @@ -29,9 +29,9 @@ Building an AppView from scratch means wiring up real-time event streams, record ## Next Steps - [Quickstart](getting-started/deployment/railway.md): Deploy HappyView on Railway or run it locally -- [Lexicons](guides/lexicons.md): Upload lexicon schemas and start indexing records +- [Lexicons](guides/indexing/lexicons.md): Upload lexicon schemas and start indexing records - [Lua Scripting](guides/scripting.md): Write custom query and procedure logic -- [Index Hooks](guides/index-hooks.md): React to record changes in real time -- [Labelers](guides/labelers.md): Subscribe to external labelers and manage content labels -- [Plugins](guides/plugins.md): Integrate with external platforms using WASM plugins -- [Event Logs](guides/event-logs.md): Monitor system activity, debug script errors, and audit admin actions +- [Index Hooks](guides/indexing/index-hooks.md): React to record changes in real time +- [Labelers](guides/features/labelers.md): Subscribe to external labelers and manage content labels +- [Plugins](guides/features/plugins.md): Integrate with external platforms using WASM plugins +- [Event Logs](guides/admin/event-logs.md): Monitor system activity, debug script errors, and audit admin actions diff --git a/packages/docs/docs/getting-started/authentication.md b/packages/docs/docs/getting-started/authentication.md index 8f1494e..d5d9de2 100644 --- a/packages/docs/docs/getting-started/authentication.md +++ b/packages/docs/docs/getting-started/authentication.md @@ -3,7 +3,7 @@ HappyView has two distinct authentication surfaces: - **XRPC** (`/xrpc/*`) — client-level identification via an **API client key** on every request, plus optional user-level atproto OAuth for endpoints that need a specific user's identity (e.g. procedures that write to a PDS). -- **Admin API** (`/admin/*`) — user-level authentication via admin API keys or service auth JWTs, gated by [permissions](../guides/permissions.md). +- **Admin API** (`/admin/*`) — user-level authentication via admin API keys or service auth JWTs, gated by [permissions](../guides/admin/permissions.md). ## Which endpoints require what? @@ -11,7 +11,7 @@ HappyView has two distinct authentication surfaces: | ---------------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------- | | Queries (`GET /xrpc/{method}`) | `X-Client-Key` required | Optional — DPoP auth if the query needs to know who the user is | | Procedures (`POST /xrpc/{method}`) | `X-Client-Key` required | Required — DPoP auth so HappyView can proxy writes to the user's PDS | -| Admin API (`/admin/*`) | — | Required — admin API key or service auth JWT with the right [permissions](../guides/permissions.md) | +| Admin API (`/admin/*`) | — | Required — admin API key or service auth JWT with the right [permissions](../guides/admin/permissions.md) | | Health check (`GET /health`) | — | — | ## XRPC: API client identification @@ -91,7 +91,7 @@ Admin endpoints don't use API clients. They require a real HappyView user, ident ### Admin API key -For automation — CI/CD, monitoring, cron jobs — create an [admin API key](../guides/api-keys.md) at **Settings > API Keys** or via `POST /admin/api-keys` and pass it as a bearer token: +For automation — CI/CD, monitoring, cron jobs — create an [admin API key](../guides/admin/api-keys.md) at **Settings > API Keys** or via `POST /admin/api-keys` and pass it as a bearer token: ```sh export TOKEN="hv_your-api-key-here" @@ -315,6 +315,6 @@ This deletes the stored session and the associated DPoP key. ## Next steps - [JavaScript SDK](../sdk/overview.md) — authenticate and make XRPC calls from JavaScript -- [Permissions](../guides/permissions.md) — full list of permissions and what each one grants -- [API Keys](../guides/api-keys.md) — create scoped admin API keys for automation +- [Permissions](../guides/admin/permissions.md) — full list of permissions and what each one grants +- [API Keys](../guides/admin/api-keys.md) — create scoped admin API keys for automation - [Admin API — API Clients](../reference/admin/api-clients.md) — register API clients and configure rate limits diff --git a/packages/docs/docs/getting-started/configuration.md b/packages/docs/docs/getting-started/configuration.md index a38d5cd..634f300 100644 --- a/packages/docs/docs/getting-started/configuration.md +++ b/packages/docs/docs/getting-started/configuration.md @@ -1,6 +1,6 @@ # Configuration -HappyView is configured via environment variables. A `.env` file in the project root is loaded automatically on startup. See [Deployment](deployment/docker.md) for local setup or [Production Deployment](../reference/production-deployment.md) for production setup. +HappyView is configured via environment variables. A `.env` file in the project root is loaded automatically on startup. See [Deployment](deployment/docker.md) for local setup or [Production Deployment](production-deployment.md) for production setup. ## Environment variables @@ -13,7 +13,7 @@ HappyView is configured via environment variables. A `.env` file in the project | `HOST` | no | `0.0.0.0` | Bind host | | `PORT` | no | `3000` | Bind port | | `JETSTREAM_URL` | no | `wss://jetstream1.us-east.bsky.network` | Jetstream WebSocket URL for real-time record streaming | -| `RELAY_URL` | no | `https://bsky.network` | Relay URL for [backfill](../guides/backfill.md) repo discovery | +| `RELAY_URL` | no | `https://bsky.network` | Relay URL for [backfill](../guides/indexing/backfill.md) repo discovery | | `PLC_URL` | no | `https://plc.directory` | [PLC directory](https://github.com/did-method-plc/did-method-plc) URL for DID resolution | | `STATIC_DIR` | no | `./web/out` | Directory containing the built dashboard static assets | | `EVENT_LOG_RETENTION_DAYS` | no | `30` | Number of days to keep event logs before automatic cleanup. Set to `0` to disable cleanup | @@ -59,4 +59,4 @@ SESSION_SECRET=change-me-in-production - [Authentication](authentication.md) — set up OAuth and admin users - [Dashboard](dashboard.md) — explore the admin dashboard -- [Production deployment](../reference/production-deployment.md) — deploy HappyView to production +- [Production deployment](production-deployment.md) — deploy HappyView to production diff --git a/packages/docs/docs/getting-started/dashboard.md b/packages/docs/docs/getting-started/dashboard.md index 59b599f..f8e361f 100644 --- a/packages/docs/docs/getting-started/dashboard.md +++ b/packages/docs/docs/getting-started/dashboard.md @@ -1,6 +1,6 @@ # Dashboard -HappyView ships with a web dashboard that provides a visual interface for everything the [admin API](../reference/admin-api.md) offers. It runs as a separate Next.js application alongside the Rust backend and authenticates via atproto OAuth. +HappyView ships with a web dashboard that provides a visual interface for everything the [admin API](../reference/admin/admin-api.md) offers. It runs as a separate Next.js application alongside the Rust backend and authenticates via atproto OAuth. On a fresh deployment with no users in the database, the first person to log in to the dashboard is automatically bootstrapped as the super user with all permissions — so log in with the handle you want to own the instance first. @@ -23,7 +23,7 @@ HappyView generates a default Lua script when you first set the type to query or Toggle **Enable backfill** to index historical records when uploading a record-type lexicon. -**Network** lexicons are fetched from the atproto network. Enter an NSID (e.g. `xyz.statusphere.status`) and HappyView resolves the schema automatically. If found, the lexicon JSON is displayed in a read-only editor. Click **Add** to track it. Network lexicons are kept up to date via the Jetstream subscription. See [Lexicons - Network lexicons](../guides/lexicons.md#network-lexicons) for how resolution works. +**Network** lexicons are fetched from the atproto network. Enter an NSID (e.g. `xyz.statusphere.status`) and HappyView resolves the schema automatically. If found, the lexicon JSON is displayed in a read-only editor. Click **Add** to track it. Network lexicons are kept up to date via the Jetstream subscription. See [Lexicons - Network lexicons](../guides/indexing/lexicons.md#network-lexicons) for how resolution works. ### JSON editor @@ -45,11 +45,11 @@ Navigate to **Records** to browse all indexed atproto records. Records are group ## Backfill -Navigate to **Backfill** to view and manage backfill jobs. You can start a new backfill for any record-type lexicon to import historical records from the network. The page shows job status, progress (repos processed / total), and record counts. See [Backfill](../guides/backfill.md) for how the process works. +Navigate to **Backfill** to view and manage backfill jobs. You can start a new backfill for any record-type lexicon to import historical records from the network. The page shows job status, progress (repos processed / total), and record counts. See [Backfill](../guides/indexing/backfill.md) for how the process works. ## Users -Navigate to **Users** to manage who can access the admin API and dashboard. You can add users by DID, assign permissions individually or via a template (`viewer`, `operator`, `manager`, `full_access`), and remove users. The super user is highlighted and has all permissions by default. See [Permissions](../guides/permissions.md) for what each permission grants. +Navigate to **Users** to manage who can access the admin API and dashboard. You can add users by DID, assign permissions individually or via a template (`viewer`, `operator`, `manager`, `full_access`), and remove users. The super user is highlighted and has all permissions by default. See [Permissions](../guides/admin/permissions.md) for what each permission grants. ## Events @@ -69,7 +69,7 @@ Register and manage third-party API clients. Each client gets an `hvc_…` clien ### API Keys -Create and revoke admin API keys for automation. Each key is scoped to specific permissions and tied to the creating user. See [API Keys](../guides/api-keys.md) for details. +Create and revoke admin API keys for automation. Each key is scoped to specific permissions and tied to the creating user. See [API Keys](../guides/admin/api-keys.md) for details. ### Users @@ -77,11 +77,11 @@ An alternative path to the top-level Users page for managing user accounts and p ### Plugins -Manage installed plugins and configure plugin secrets. Plugins extend HappyView with additional functionality. Plugin secrets are encrypted at rest when `TOKEN_ENCRYPTION_KEY` is configured. See [Plugins](../guides/plugins.md) for details. +Manage installed plugins and configure plugin secrets. Plugins extend HappyView with additional functionality. Plugin secrets are encrypted at rest when `TOKEN_ENCRYPTION_KEY` is configured. See [Plugins](../guides/features/plugins.md) for details. ### Labelers -Configure labeler subscriptions for content labeling. See [Labelers](../guides/labelers.md) for details. +Configure labeler subscriptions for content labeling. See [Labelers](../guides/features/labelers.md) for details. ### Environment Variables @@ -93,7 +93,7 @@ Manage connected atproto accounts used by the instance. ## Next steps -- [Lexicons](../guides/lexicons.md) — how lexicons drive HappyView's indexing and routing +- [Lexicons](../guides/indexing/lexicons.md) — how lexicons drive HappyView's indexing and routing - [Lua Scripting](../guides/scripting.md) — write custom query and procedure logic -- [Permissions](../guides/permissions.md) — manage user access to admin features +- [Permissions](../guides/admin/permissions.md) — manage user access to admin features - [Configuration](configuration.md) — full list of environment variables diff --git a/packages/docs/docs/getting-started/deployment/docker.md b/packages/docs/docs/getting-started/deployment/docker.md index f9ef722..e4ef67d 100644 --- a/packages/docs/docs/getting-started/deployment/docker.md +++ b/packages/docs/docs/getting-started/deployment/docker.md @@ -34,7 +34,7 @@ HappyView runs migrations automatically on startup. The first build will take a The `happyview` container serves its own bundled dashboard at `http://localhost:3000`, but that copy is baked in at container build time and only updates when you rebuild the image. For day-to-day development, use the dev dashboard at `http://localhost:3001` — it hot-reloads on changes to the `web/` source. :::tip -SQLite is the default and requires no extra services. To use Postgres instead, uncomment the `postgres` service in `docker-compose.yml` and update `DATABASE_URL` in `.env`. See the [database setup guide](../../guides/database-setup.md). +SQLite is the default and requires no extra services. To use Postgres instead, uncomment the `postgres` service in `docker-compose.yml` and update `DATABASE_URL` in `.env`. See the [database setup guide](../../guides/database/database-setup.md). ::: ## Next steps diff --git a/packages/docs/docs/getting-started/deployment/other.md b/packages/docs/docs/getting-started/deployment/other.md index 7fb5b3c..061c3d5 100644 --- a/packages/docs/docs/getting-started/deployment/other.md +++ b/packages/docs/docs/getting-started/deployment/other.md @@ -30,7 +30,7 @@ Or if you prefer Postgres: DATABASE_URL=postgres://happyview:happyview@localhost/happyview ``` -See [Configuration](../configuration.md) for all available variables and the [database setup guide](../../guides/database-setup.md) for details on both backends. +See [Configuration](../configuration.md) for all available variables and the [database setup guide](../../guides/database/database-setup.md) for details on both backends. ## 2. Create the database (Postgres only) diff --git a/packages/docs/docs/getting-started/deployment/railway.md b/packages/docs/docs/getting-started/deployment/railway.md index 1864c48..0fe4493 100644 --- a/packages/docs/docs/getting-started/deployment/railway.md +++ b/packages/docs/docs/getting-started/deployment/railway.md @@ -24,4 +24,4 @@ After deploying the template, you'll need to configure a few things before the s - [Configuration](../configuration.md) — full list of environment variables - [Dashboard](../dashboard.md) — manage lexicons, users, and plugins via the web UI -- [Production deployment](../../reference/production-deployment.md) — hardening checklist for production instances +- [Production deployment](../production-deployment.md) — hardening checklist for production instances diff --git a/packages/docs/docs/getting-started/production-deployment.md b/packages/docs/docs/getting-started/production-deployment.md index 1632d17..6c07f4e 100644 --- a/packages/docs/docs/getting-started/production-deployment.md +++ b/packages/docs/docs/getting-started/production-deployment.md @@ -14,7 +14,7 @@ Never commit the secret to source control. Store it in your platform's secret ma ## Token encryption key -If you use [plugins](../guides/plugins.md) that require secrets (API keys, OAuth credentials), set `TOKEN_ENCRYPTION_KEY` to a base64-encoded 32-byte key. This encrypts plugin secrets at rest using AES-256-GCM: +If you use [plugins](../guides/features/plugins.md) that require secrets (API keys, OAuth credentials), set `TOKEN_ENCRYPTION_KEY` to a base64-encoded 32-byte key. This encrypts plugin secrets at rest using AES-256-GCM: ```sh openssl rand -base64 32 @@ -40,13 +40,13 @@ SQLite is fine for small to medium instances and is the default. Switch to Postg - Larger-than-memory working sets - External tools that need direct read access to the records table -See the [database setup guide](../guides/database-setup.md) for configuration details and [Postgres → SQLite migration](../guides/postgres-to-sqlite-migration.md) if you're moving the other direction. Migrations run automatically on startup regardless of backend. +See the [database setup guide](../guides/database/database-setup.md) for configuration details and [Postgres → SQLite migration](../guides/database/postgres-to-sqlite-migration.md) if you're moving the other direction. Migrations run automatically on startup regardless of backend. ## Rate limits -HappyView has a per-client token-bucket rate limiter for XRPC endpoints. The defaults (set via `DEFAULT_RATE_LIMIT_CAPACITY` and `DEFAULT_RATE_LIMIT_REFILL_RATE`) apply to any [API client](../guides/api-keys.md) that doesn't have per-client overrides. Raise the defaults cautiously — they exist so one misbehaving integrator can't saturate the server. +HappyView has a per-client token-bucket rate limiter for XRPC endpoints. The defaults (set via `DEFAULT_RATE_LIMIT_CAPACITY` and `DEFAULT_RATE_LIMIT_REFILL_RATE`) apply to any [API client](../guides/admin/api-keys.md) that doesn't have per-client overrides. Raise the defaults cautiously — they exist so one misbehaving integrator can't saturate the server. -Per-client overrides are set at client creation or via `PUT /admin/api-clients/{id}` (see [Admin API — API Clients](admin/api-clients.md)). +Per-client overrides are set at client creation or via `PUT /admin/api-clients/{id}` (see [Admin API — API Clients](../reference/admin/api-clients.md)). ## Logging @@ -60,7 +60,7 @@ Structured logs go to stdout, so any platform that captures container stdout (Ra ## Event log retention -The admin [event log](../guides/event-logs.md) is stored in the same database as records. `EVENT_LOG_RETENTION_DAYS` (default `30`) controls automatic cleanup. Set to `0` to keep events indefinitely — useful for compliance-sensitive deployments, but plan for database growth. +The admin [event log](../guides/admin/event-logs.md) is stored in the same database as records. `EVENT_LOG_RETENTION_DAYS` (default `30`) controls automatic cleanup. Set to `0` to keep events indefinitely — useful for compliance-sensitive deployments, but plan for database growth. ## Health checks @@ -73,10 +73,10 @@ For a deeper check, hit `GET /xrpc/com.atproto.server.describeServer` — this e - **SQLite**: back up the database file (e.g. `data/happyview.db`) plus its `-wal` and `-shm` sidecar files. Use `sqlite3 happyview.db ".backup '/path/backup.db'"` for a consistent snapshot while HappyView is running. - **Postgres**: standard `pg_dump` / managed-Postgres snapshots. -Most of what HappyView stores is derivable from the network — lost records can be re-indexed via [backfill](../guides/backfill.md). You can't recover from the network: user accounts and permissions, API keys, API clients, plugin secrets, and the Jetstream cursor. Prioritize those in your backup plan. +Most of what HappyView stores is derivable from the network — lost records can be re-indexed via [backfill](../guides/indexing/backfill.md). You can't recover from the network: user accounts and permissions, API keys, API clients, plugin secrets, and the Jetstream cursor. Prioritize those in your backup plan. ## Next steps - [Configuration](../getting-started/configuration.md) — full environment variable reference -- [Permissions](../guides/permissions.md) — lock down admin access before exposing the dashboard publicly -- [Troubleshooting](troubleshooting.md) — diagnose issues with a running instance +- [Permissions](../guides/admin/permissions.md) — lock down admin access before exposing the dashboard publicly +- [Troubleshooting](../reference/troubleshooting.md) — diagnose issues with a running instance diff --git a/packages/docs/docs/getting-started/quickstart.md b/packages/docs/docs/getting-started/quickstart.md index b0c1de3..4fcf78d 100644 --- a/packages/docs/docs/getting-started/quickstart.md +++ b/packages/docs/docs/getting-started/quickstart.md @@ -29,7 +29,7 @@ Lexicons tell HappyView what data to index and what endpoints to serve. The quic HappyView starts indexing records for that collection. A backfill job fetches historical records, and new records stream in via Jetstream. -You can also upload lexicons manually via the dashboard or the [admin API](../reference/admin-api.md). See [Lexicons](../guides/lexicons.md) for the full details. +You can also upload lexicons manually via the dashboard or the [admin API](../reference/admin/admin-api.md). See [Lexicons](../guides/indexing/lexicons.md) for the full details. ## 4. Verify records are being indexed @@ -50,7 +50,7 @@ For custom query logic, attach a [Lua script](../guides/scripting.md). ## Next steps - [**Statusphere tutorial**](../tutorials/statusphere.md): full walkthrough building a complete AppView with record, query, and procedure lexicons -- [**Lexicons guide**](../guides/lexicons.md): target collections, backfill flag, network lexicons +- [**Lexicons guide**](../guides/indexing/lexicons.md): target collections, backfill flag, network lexicons - [**Lua Scripting**](../guides/scripting.md): custom query and procedure logic - [**Configuration**](configuration.md): environment variables and tuning - [**Authentication**](authentication.md): how OAuth works and how to get API tokens diff --git a/packages/docs/docs/guides/admin/api-keys.md b/packages/docs/docs/guides/admin/api-keys.md index 684a1bf..11f90c8 100644 --- a/packages/docs/docs/guides/admin/api-keys.md +++ b/packages/docs/docs/guides/admin/api-keys.md @@ -31,7 +31,7 @@ curl http://localhost:3000/admin/lexicons \ -H "Authorization: Bearer hv_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4" ``` -This works for all [admin API](../reference/admin-api.md) endpoints that the key has permissions for. Unlike OAuth tokens which carry the user's full permissions, API keys are limited to the specific permissions assigned at creation time. +This works for all [admin API](../../reference/admin/admin-api.md) endpoints that the key has permissions for. Unlike OAuth tokens which carry the user's full permissions, API keys are limited to the specific permissions assigned at creation time. ## Revoking a key @@ -55,6 +55,6 @@ The **Last Used** column in the API Keys table shows when each key was last used ## Next steps -- [Admin API reference](../reference/admin-api.md) — full endpoint documentation -- [Scripting](scripting.md) — automate record processing with Lua scripts -- [Index hooks](index-hooks.md) — push records to external services on write +- [Admin API reference](../../reference/admin/admin-api.md) — full endpoint documentation +- [Scripting](../scripting.md) — automate record processing with Lua scripts +- [Index hooks](../indexing/index-hooks.md) — push records to external services on write diff --git a/packages/docs/docs/guides/admin/event-logs.md b/packages/docs/docs/guides/admin/event-logs.md index 9f723a0..274626d 100644 --- a/packages/docs/docs/guides/admin/event-logs.md +++ b/packages/docs/docs/guides/admin/event-logs.md @@ -1,6 +1,6 @@ # Event Logs -HappyView maintains an internal event log that records system activity — lexicon changes, record operations, Lua script executions and errors, user actions, API key events, backfill jobs, and Jetstream connectivity. Events are stored in the database and queryable via the [admin API](../reference/admin/events.md). +HappyView maintains an internal event log that records system activity — lexicon changes, record operations, Lua script executions and errors, user actions, API key events, backfill jobs, and Jetstream connectivity. Events are stored in the database and queryable via the [admin API](../../reference/admin/events.md). ## Event types @@ -14,7 +14,7 @@ Events follow a `category.action` naming convention. Each event has a severity l | `lexicon.updated` | info | Lexicon NSID | `revision`, `has_script`, `source` | | `lexicon.deleted` | info | Lexicon NSID | — | -Logged when lexicons are uploaded, updated, or deleted via the [admin API](../reference/admin/lexicons.md). The `actor_did` is the user who performed the action. +Logged when lexicons are uploaded, updated, or deleted via the [admin API](../../reference/admin/lexicons.md). The `actor_did` is the user who performed the action. ### Record events @@ -48,7 +48,7 @@ For query scripts (unauthenticated), `caller_did` and `input` are omitted from t | `user.permissions_updated` | info | User ID | `granted`, `revoked` | | `user.super_transferred` | warn | New super user ID | `from_user_id` | -The `user.bootstrapped` event is logged when the first user is auto-promoted to super user (see [Auth - Auto-bootstrap](../reference/admin-api.md#auth)). +The `user.bootstrapped` event is logged when the first user is auto-promoted to super user (see [Auth - Auto-bootstrap](../../reference/admin/admin-api.md#auth)). ### Auth events @@ -79,7 +79,7 @@ Logged when a user attempts to access an endpoint they don't have permission for | `hook.executed` | info | Record AT URI | `lexicon_id` | | `hook.dead_lettered` | error | Record AT URI | `lexicon_id`, `error` | -Logged when [index hooks](index-hooks.md) run. Dead-lettered events indicate a hook failed all retry attempts. You can manage dead letters from the **Data > Dead Letters** page in the dashboard — see [Dead Letters](#dead-letters) below. +Logged when [index hooks](../indexing/index-hooks.md) run. Dead-lettered events indicate a hook failed all retry attempts. You can manage dead letters from the **Data > Dead Letters** page in the dashboard — see [Dead Letters](#dead-letters) below. ### Backfill events @@ -89,7 +89,7 @@ Logged when [index hooks](index-hooks.md) run. Dead-lettered events indicate a h | `backfill.completed` | info | Collection NSID | `job_id`, `total_repos` | | `backfill.failed` | error | Collection NSID | `job_id`, `error` | -See [Backfill](backfill.md) for background on backfill jobs. +See [Backfill](../indexing/backfill.md) for background on backfill jobs. ### Jetstream events @@ -118,7 +118,7 @@ curl "http://localhost:3000/admin/events?category=lexicon" -H "$AUTH" curl "http://localhost:3000/admin/events?limit=20&cursor=2026-03-01T11:59:00Z" -H "$AUTH" ``` -See the [Admin API reference](../reference/admin/events.md#list-event-logs) for full parameter documentation. +See the [Admin API reference](../../reference/admin/events.md#list-event-logs) for full parameter documentation. ## Retention @@ -126,7 +126,7 @@ Event logs are automatically cleaned up based on the `EVENT_LOG_RETENTION_DAYS` Set `EVENT_LOG_RETENTION_DAYS=0` to disable automatic cleanup and keep logs indefinitely. -See [Configuration](../getting-started/configuration.md) for all environment variables. +See [Configuration](../../getting-started/configuration.md) for all environment variables. ## Dead Letters @@ -142,6 +142,6 @@ Bulk actions are available for selected rows or all entries matching the current ## Next steps -- [Admin API — Event Logs](../reference/admin/events.md) — full query parameters and response format +- [Admin API — Event Logs](../../reference/admin/events.md) — full query parameters and response format - [Permissions](permissions.md) — control which users can read event logs -- [Troubleshooting](../reference/troubleshooting.md) — using event logs to diagnose issues +- [Troubleshooting](../../reference/troubleshooting.md) — using event logs to diagnose issues diff --git a/packages/docs/docs/guides/admin/permissions.md b/packages/docs/docs/guides/admin/permissions.md index 35d2f80..b6aa668 100644 --- a/packages/docs/docs/guides/admin/permissions.md +++ b/packages/docs/docs/guides/admin/permissions.md @@ -132,10 +132,10 @@ Go to **Settings > Users** to view and manage user permissions. Click on a user - `PATCH /admin/users/{id}/permissions` — grant or revoke individual permissions - `POST /admin/users/transfer-super` — transfer super user status (super user only) -See the [Admin API — Users](../reference/admin/users.md) for full details. +See the [Admin API — Users](../../reference/admin/users.md) for full details. ## Next steps -- [Admin API reference](../reference/admin-api.md) — endpoint documentation with required permissions +- [Admin API reference](../../reference/admin/admin-api.md) — endpoint documentation with required permissions - [API Keys](api-keys.md) — creating scoped API keys - [Event Logs](event-logs.md) — permission-denied events are logged for auditing diff --git a/packages/docs/docs/guides/database/database-setup.md b/packages/docs/docs/guides/database/database-setup.md index b26a50e..88919e5 100644 --- a/packages/docs/docs/guides/database/database-setup.md +++ b/packages/docs/docs/guides/database/database-setup.md @@ -74,5 +74,5 @@ If you are migrating existing Lua scripts from Postgres SQL syntax to SQLite syn - [SQLite → Postgres migration](sqlite-to-postgres-migration.md) — switch an existing instance from SQLite to Postgres - [Postgres → SQLite migration](postgres-to-sqlite-migration.md) — switch an existing instance from Postgres to SQLite -- [Lua scripting](scripting.md) — write queries that target either backend -- [Configuration](../getting-started/configuration.md) — `DATABASE_URL` and related variables +- [Lua scripting](../scripting.md) — write queries that target either backend +- [Configuration](../../getting-started/configuration.md) — `DATABASE_URL` and related variables diff --git a/packages/docs/docs/guides/database/postgres-to-sqlite-migration.md b/packages/docs/docs/guides/database/postgres-to-sqlite-migration.md index bec47b6..5a8afc0 100644 --- a/packages/docs/docs/guides/database/postgres-to-sqlite-migration.md +++ b/packages/docs/docs/guides/database/postgres-to-sqlite-migration.md @@ -87,5 +87,5 @@ To switch back to Postgres, revert your `DATABASE_URL` to the Postgres connectio - [SQLite → Postgres migration](sqlite-to-postgres-migration.md) — migrate in the opposite direction - [Database setup](database-setup.md) — choose between SQLite and Postgres for new instances -- [Backfill](backfill.md) — re-index records from the network after switching backends -- [Lua scripting](scripting.md) — write SQL that works against either backend +- [Backfill](../indexing/backfill.md) — re-index records from the network after switching backends +- [Lua scripting](../scripting.md) — write SQL that works against either backend diff --git a/packages/docs/docs/guides/database/sqlite-to-postgres-migration.md b/packages/docs/docs/guides/database/sqlite-to-postgres-migration.md index 349d670..d75c814 100644 --- a/packages/docs/docs/guides/database/sqlite-to-postgres-migration.md +++ b/packages/docs/docs/guides/database/sqlite-to-postgres-migration.md @@ -84,5 +84,5 @@ To switch back to SQLite, revert your `DATABASE_URL` to the SQLite connection st - [Postgres → SQLite migration](postgres-to-sqlite-migration.md) — migrate in the opposite direction - [Database setup](database-setup.md) — choose between SQLite and Postgres for new instances -- [Backfill](backfill.md) — re-index records from the network after switching backends -- [Lua scripting](scripting.md) — write SQL that works against either backend +- [Backfill](../indexing/backfill.md) — re-index records from the network after switching backends +- [Lua scripting](../scripting.md) — write SQL that works against either backend diff --git a/packages/docs/docs/guides/features/api-clients.md b/packages/docs/docs/guides/features/api-clients.md index bd42d2e..9ebe347 100644 --- a/packages/docs/docs/guides/features/api-clients.md +++ b/packages/docs/docs/guides/features/api-clients.md @@ -2,7 +2,7 @@ API clients identify your application to a HappyView instance. Every XRPC request — even unauthenticated queries — must include a client key. This guide walks through creating a client, choosing between public and confidential types, and authenticating users. -For the admin CRUD endpoints, see the [API reference](../reference/admin/api-clients.md). For the JavaScript SDK, see the [SDK docs](../sdk/overview.md). +For the admin CRUD endpoints, see the [API reference](../../reference/admin/api-clients.md). For the JavaScript SDK, see the [SDK docs](../../sdk/overview.md). ## Concepts @@ -63,7 +63,7 @@ curl -X POST http://localhost:3000/admin/api-clients \ }' ``` -See the [API reference](../reference/admin/api-clients.md#create-an-api-client) for all fields. +See the [API reference](../../reference/admin/api-clients.md#create-an-api-client) for all fields. ## Using your client key @@ -91,7 +91,7 @@ curl 'https://happyview.example.com/xrpc/com.example.feed.getHot' \ ### Authenticated requests (user identity) -Procedures — and queries whose scripts need to know who the caller is — require a user's OAuth session. This uses [DPoP authentication](../getting-started/authentication.md#dpop-key-provisioning-for-third-party-apps), where each request includes a cryptographic proof that the caller holds the right key. +Procedures — and queries whose scripts need to know who the caller is — require a user's OAuth session. This uses [DPoP authentication](../../getting-started/authentication.md#dpop-key-provisioning-for-third-party-apps), where each request includes a cryptographic proof that the caller holds the right key. ```sh curl -X POST 'https://happyview.example.com/xrpc/com.example.createPost' \ @@ -141,7 +141,7 @@ if (session) { } ``` -For server-side Node.js apps, use the core [`@happyview/oauth-client`](../sdk/oauth-client.md) package with a confidential client. For type-safe XRPC calls, pair either client with [`@happyview/lex-agent`](../sdk/lex-agent.md). +For server-side Node.js apps, use the core [`@happyview/oauth-client`](../../sdk/oauth-client.md) package with a confidential client. For type-safe XRPC calls, pair either client with [`@happyview/lex-agent`](../../sdk/lex-agent.md). ### Manual DPoP flow @@ -348,7 +348,7 @@ Rate limit state is returned in response headers: | `RateLimit-Reset` | Unix timestamp when the bucket will be full | | `Retry-After` | Seconds to wait (only on `429` responses) | -Adjust per-client rate limits via the dashboard or the [admin API](../reference/admin/api-clients.md#update-an-api-client). +Adjust per-client rate limits via the dashboard or the [admin API](../../reference/admin/api-clients.md#update-an-api-client). ## Security notes @@ -359,7 +359,7 @@ Adjust per-client rate limits via the dashboard or the [admin API](../reference/ ## Next steps -- [Authentication](../getting-started/authentication.md) — full protocol details and security model -- [JavaScript SDK](../sdk/overview.md) — get started with the SDK -- [Admin API — API Clients](../reference/admin/api-clients.md) — CRUD endpoints -- [Permissions](permissions.md) — control who can manage API clients +- [Authentication](../../getting-started/authentication.md) — full protocol details and security model +- [JavaScript SDK](../../sdk/overview.md) — get started with the SDK +- [Admin API — API Clients](../../reference/admin/api-clients.md) — CRUD endpoints +- [Permissions](../admin/permissions.md) — control who can manage API clients diff --git a/packages/docs/docs/guides/features/developing-plugins.md b/packages/docs/docs/guides/features/developing-plugins.md index 198b5aa..5ff51f6 100644 --- a/packages/docs/docs/guides/features/developing-plugins.md +++ b/packages/docs/docs/guides/features/developing-plugins.md @@ -101,5 +101,5 @@ Plugins can import these host functions: - [Official plugins repository](https://github.com/gamesgamesgamesgamesgames/happyview-plugins) — ready-to-use plugins and the plugin SDK - [Plugins guide](plugins.md) — install and configure plugins -- [API Keys](api-keys.md) — authenticate programmatic access to admin endpoints -- [Permissions](permissions.md) — configure user access to plugin management +- [API Keys](../admin/api-keys.md) — authenticate programmatic access to admin endpoints +- [Permissions](../admin/permissions.md) — configure user access to plugin management diff --git a/packages/docs/docs/guides/features/labelers.md b/packages/docs/docs/guides/features/labelers.md index 1186ceb..5997b5f 100644 --- a/packages/docs/docs/guides/features/labelers.md +++ b/packages/docs/docs/guides/features/labelers.md @@ -65,7 +65,7 @@ Labels appear in the **Labels** column on the Records page as color-coded badges Self-labels (applied by the record author) use an outline badge style to distinguish them from external labels. Hover over a badge to see the source labeler's DID. -Labels are also available in the records API response and in Lua scripts via the [`atproto.get_labels` and `atproto.get_labels_batch`](../reference/lua/atproto-api.md#atprotoget_labels) functions. +Labels are also available in the records API response and in Lua scripts via the [`atproto.get_labels` and `atproto.get_labels_batch`](../../reference/lua/atproto-api.md#atprotoget_labels) functions. ## Using labels in your AppView @@ -85,6 +85,6 @@ Labeler subscriptions give your AppView access to content moderation signals wit ## Next steps -- [Admin API — Labelers](../reference/admin/labelers.md) — full endpoint documentation -- [atproto API](../reference/lua/atproto-api.md) — access labels in Lua scripts with `get_labels` and `get_labels_batch` -- [Permissions](permissions.md) — manage user access to labeler operations +- [Admin API — Labelers](../../reference/admin/labelers.md) — full endpoint documentation +- [atproto API](../../reference/lua/atproto-api.md) — access labels in Lua scripts with `get_labels` and `get_labels_batch` +- [Permissions](../admin/permissions.md) — manage user access to labeler operations diff --git a/packages/docs/docs/guides/features/plugins.md b/packages/docs/docs/guides/features/plugins.md index 8b59aba..c3031f4 100644 --- a/packages/docs/docs/guides/features/plugins.md +++ b/packages/docs/docs/guides/features/plugins.md @@ -75,5 +75,5 @@ These are only necessary if you can't configure variables via the dashboard. Das - [Developing Plugins](developing-plugins.md) — create your own plugins with the WASM plugin API - [Official plugins repository](https://github.com/gamesgamesgamesgamesgames/happyview-plugins) — ready-to-use plugins for Steam, Xbox, itch.io, and more -- [API Keys](api-keys.md) — authenticate programmatic access to admin endpoints -- [Permissions](permissions.md) — configure user access to plugin management +- [API Keys](../admin/api-keys.md) — authenticate programmatic access to admin endpoints +- [Permissions](../admin/permissions.md) — configure user access to plugin management diff --git a/packages/docs/docs/guides/indexing/backfill.md b/packages/docs/docs/guides/indexing/backfill.md index 746aab8..292a05c 100644 --- a/packages/docs/docs/guides/indexing/backfill.md +++ b/packages/docs/docs/guides/indexing/backfill.md @@ -5,9 +5,9 @@ When you add a new record-type lexicon, HappyView starts indexing new records fr ## When backfill runs - **Automatically** when a record-type lexicon is uploaded with `backfill: true` (the default). See [Lexicons - Backfill flag](lexicons.md#backfill-flag). -- **Manually** via `POST /admin/backfill` or the [dashboard](../getting-started/dashboard.md). You can scope a manual backfill to a specific collection, a specific DID, or both. +- **Manually** via `POST /admin/backfill` or the [dashboard](../../getting-started/dashboard.md). You can scope a manual backfill to a specific collection, a specific DID, or both. -See the [admin API](../reference/admin/backfill.md) for endpoint details. +See the [admin API](../../reference/admin/backfill.md) for endpoint details. ## How it works @@ -34,4 +34,4 @@ Deleting records from HappyView (via the dashboard or API) only removes them fro ## Next steps - [Lexicons](lexicons.md#backfill-flag): Control whether lexicons trigger backfill on upload -- [Admin API — Backfill](../reference/admin/backfill.md): Full reference for backfill endpoints +- [Admin API — Backfill](../../reference/admin/backfill.md): Full reference for backfill endpoints diff --git a/packages/docs/docs/guides/indexing/index-hooks.md b/packages/docs/docs/guides/indexing/index-hooks.md index 50f558c..c00e3b9 100644 --- a/packages/docs/docs/guides/indexing/index-hooks.md +++ b/packages/docs/docs/guides/indexing/index-hooks.md @@ -2,11 +2,11 @@ Index hooks are Lua scripts that run whenever a record in a collection is created, updated, or deleted. They run **before** the record is indexed, giving you the ability to filter out unwanted records, transform record data before storage, or trigger side effects like syncing with external services. -Index hooks fire on **all** record events for the collection — including records created by HappyView procedure endpoints, not just events from the network. Unlike [query and procedure scripts](scripting.md) that run in response to XRPC requests, index hooks are triggered by incoming Jetstream events (which include events caused by HappyView's own PDS writes). +Index hooks fire on **all** record events for the collection — including records created by HappyView procedure endpoints, not just events from the network. Unlike [query and procedure scripts](../scripting.md) that run in response to XRPC requests, index hooks are triggered by incoming Jetstream events (which include events caused by HappyView's own PDS writes). ## Attaching a hook -Each record-type lexicon can have one index hook. You can add it through the [dashboard](../getting-started/dashboard.md) (click "Add Index Hook" on any record lexicon's detail page) or via the [admin API](../reference/admin/lexicons.md#upload--upsert-a-lexicon) by including the `index_hook` field when uploading a lexicon. +Each record-type lexicon can have one index hook. You can add it through the [dashboard](../../getting-started/dashboard.md) (click "Add Index Hook" on any record lexicon's detail page) or via the [admin API](../../reference/admin/lexicons.md#upload--upsert-a-lexicon) by including the `index_hook` field when uploading a lexicon. ## Script structure @@ -57,10 +57,10 @@ Index hooks do **not** have access to `caller_did`, `input`, `params`, `method`, Index hooks have access to: -- **[Database API](../reference/lua/database-api.md)** — `db.query`, `db.get`, `db.search`, `db.backlinks`, `db.count`, `db.raw` -- **[HTTP API](../reference/lua/http-api.md)** — `http.get`, `http.post`, `http.put`, `http.patch`, `http.delete`, `http.head` -- **[JSON API](../reference/lua/json-api.md)** — `json.encode`, `json.decode` -- **[Utility globals](scripting.md#utility-globals)** — `log()`, `now()`, `TID()`, `toarray()` +- **[Database API](../../reference/lua/database-api.md)** — `db.query`, `db.get`, `db.search`, `db.backlinks`, `db.count`, `db.raw` +- **[HTTP API](../../reference/lua/http-api.md)** — `http.get`, `http.post`, `http.put`, `http.patch`, `http.delete`, `http.head` +- **[JSON API](../../reference/lua/json-api.md)** — `json.encode`, `json.decode` +- **[Utility globals](../scripting.md#utility-globals)** — `log()`, `now()`, `TID()`, `toarray()` ## Error handling and retries @@ -70,7 +70,7 @@ Index hooks are designed to be resilient: 2. If all retries are exhausted, the failed event is inserted into the `dead_letter_hooks` table for later inspection. 3. On failure the system **fails open** — the original record is stored as-is so indexing is not permanently blocked. -Failed hooks are logged as errors. Check the [event logs](event-logs.md) or query the `dead_letter_hooks` table directly to find and replay failures. +Failed hooks are logged as errors. Check the [event logs](../admin/event-logs.md) or query the `dead_letter_hooks` table directly to find and replay failures. ### Performance considerations @@ -178,7 +178,7 @@ function handle() end ``` -See the full [Algolia sync reference](../reference/scripts/algolia-sync.md) for more detail. +See the full [Algolia sync reference](../scripting/algolia-sync.md) for more detail. ### Sync to Meilisearch @@ -213,10 +213,10 @@ function handle() end ``` -See the full [Meilisearch sync reference](../reference/scripts/meilisearch-sync.md) for more detail. +See the full [Meilisearch sync reference](../scripting/meilisearch-sync.md) for more detail. ## Next steps -- [Lua Scripting](scripting.md): Full reference for the sandbox, APIs, and debugging +- [Lua Scripting](../scripting.md): Full reference for the sandbox, APIs, and debugging - [Lexicons](lexicons.md): Understand how record, query, and procedure lexicons work together -- [Admin API — Lexicons](../reference/admin/lexicons.md#upload--upsert-a-lexicon): Upload lexicons with index hooks via the API +- [Admin API — Lexicons](../../reference/admin/lexicons.md#upload--upsert-a-lexicon): Upload lexicons with index hooks via the API diff --git a/packages/docs/docs/guides/indexing/lexicons.md b/packages/docs/docs/guides/indexing/lexicons.md index d2ff04b..f5a74ca 100644 --- a/packages/docs/docs/guides/indexing/lexicons.md +++ b/packages/docs/docs/guides/indexing/lexicons.md @@ -2,7 +2,7 @@ Lexicons are the core building block of HappyView. They're [atproto schema definitions](https://atproto.com/specs/lexicon) that describe your data model, and HappyView uses them to decide which records to index from the network and what XRPC endpoints to serve. -You don't write route handlers or database queries; you upload a lexicon and HappyView generates the infrastructure from it. There are two ways to add lexicons: uploading them via the [admin API](../reference/admin/lexicons.md) or [dashboard](../getting-started/dashboard.md), or fetching them directly from the atproto network via [DNS authority resolution](#network-lexicons). +You don't write route handlers or database queries; you upload a lexicon and HappyView generates the infrastructure from it. There are two ways to add lexicons: uploading them via the [admin API](../../reference/admin/lexicons.md) or [dashboard](../../getting-started/dashboard.md), or fetching them directly from the atproto network via [DNS authority resolution](#network-lexicons). ## Supported lexicon types @@ -13,7 +13,7 @@ You don't write route handlers or database queries; you upload a lexicon and Hap | `procedure` | Registers a `POST /xrpc/{nsid}` endpoint that proxies writes to the user's PDS | | `definitions` | Stored but does not generate routes or subscriptions | -A typical setup has three lexicons working together: a **record** lexicon that defines the data and triggers indexing, a **query** lexicon that exposes a read endpoint, and a **procedure** lexicon that exposes a write endpoint. The [Statusphere tutorial](../tutorials/statusphere.md) walks through this pattern end-to-end. +A typical setup has three lexicons working together: a **record** lexicon that defines the data and triggers indexing, a **query** lexicon that exposes a read endpoint, and a **procedure** lexicon that exposes a write endpoint. The [Statusphere tutorial](../../tutorials/statusphere.md) walks through this pattern end-to-end. ## Target collection @@ -21,7 +21,7 @@ Query and procedure lexicons don't store data themselves. They operate on record For example, a query lexicon `xyz.statusphere.listStatuses` would set `target_collection` to `xyz.statusphere.status` to read from that record collection. -See the [admin API](../reference/admin/lexicons.md#upload--upsert-a-lexicon) for how to set `target_collection` when uploading. +See the [admin API](../../reference/admin/lexicons.md#upload--upsert-a-lexicon) for how to set `target_collection` when uploading. :::note The `target_collection` is available in Lua scripts as the `collection` global, but it is not required if your endpoint uses a Lua script. @@ -89,7 +89,7 @@ When a client calls `/xrpc/{method}` and HappyView has a local lexicon for that A few things to note: - HappyView does **not** proxy to the reversed hostname directly. `foo.example.com` is only the DNS host for the TXT record — the actual XRPC request goes to whatever PDS endpoint the authority DID resolves to. -- Proxying applies equally to queries and procedures. For procedures, HappyView uses the caller's OAuth session to attach a DPoP-bound access token (see [Authentication](../getting-started/authentication.md#proxying-procedures-to-the-users-pds)). +- Proxying applies equally to queries and procedures. For procedures, HappyView uses the caller's OAuth session to attach a DPoP-bound access token (see [Authentication](../../getting-started/authentication.md#proxying-procedures-to-the-users-pds)). - If authority resolution fails — no TXT record, unresolvable DID, or the target PDS doesn't support the method — the client gets an error back. HappyView does not fall back to any other routing strategy. - Tracking a network lexicon does **not** make HappyView handle requests for that NSID locally. Network lexicons are only about indexing record collections and keeping the schema up to date. If a client calls a query NSID that you've tracked as a network lexicon but haven't uploaded a local query lexicon for, HappyView still proxies the request out — it won't query your local record table. To serve a method locally, upload a local query or procedure lexicon with a matching `target_collection`. @@ -97,8 +97,8 @@ In short: if you want to serve an XRPC method on your instance, you need a local ## Next steps -- [Lua Scripting](scripting.md): Add custom query and procedure logic to your endpoints +- [Lua Scripting](../scripting.md): Add custom query and procedure logic to your endpoints - [Index Hooks](index-hooks.md): Run Lua scripts when records are indexed from the network -- [XRPC API](../reference/xrpc-api.md): Understand how the generated endpoints behave +- [XRPC API](../../reference/xrpc-api.md): Understand how the generated endpoints behave - [Backfill](backfill.md): Learn how historical records are indexed -- [Admin API](../reference/admin-api.md): Full reference for lexicon management endpoints +- [Admin API](../../reference/admin/admin-api.md): Full reference for lexicon management endpoints diff --git a/packages/docs/docs/guides/scripting.md b/packages/docs/docs/guides/scripting.md index b11c50f..2ea70db 100644 --- a/packages/docs/docs/guides/scripting.md +++ b/packages/docs/docs/guides/scripting.md @@ -10,7 +10,7 @@ Without Lua scripts, HappyView's query endpoints return raw records and procedur Scripts are attached to query and procedure lexicons and run in a sandboxed Lua VM with access to the [Record API](#record-api), a [database API](#database-api), an [HTTP client API](#http-api), a [JSON API](#json-api), and a set of [context globals](#context-globals). -For scripts that react to record changes from the network (rather than XRPC requests), see [Index Hooks](index-hooks.md). +For scripts that react to record changes from the network (rather than XRPC requests), see [Index Hooks](indexing/index-hooks.md). ## Script structure @@ -177,26 +177,26 @@ The **full error message** is logged server-side at error level. Check the serve See the example script references for complete, ready-to-use scripts: **Queries:** -- [Get a record](../reference/scripts/get-record.md) — fetch a single record by AT URI -- [Paginated list](../reference/scripts/paginated-list.md) — list records with cursor-based pagination and DID filtering -- [List or fetch](../reference/scripts/list-or-fetch.md) — combined single-record lookup and paginated listing -- [Expanded query](../reference/scripts/expanded-query.md) — list statuses with user profiles in a single response +- [Get a record](scripting/get-record.md) — fetch a single record by AT URI +- [Paginated list](scripting/paginated-list.md) — list records with cursor-based pagination and DID filtering +- [List or fetch](scripting/list-or-fetch.md) — combined single-record lookup and paginated listing +- [Expanded query](scripting/expanded-query.md) — list statuses with user profiles in a single response **Procedures:** -- [Create a record](../reference/scripts/create-record.md) — simple write that saves input as a record -- [Upsert a record](../reference/scripts/upsert-record.md) — create or update using a deterministic rkey -- [Update or delete](../reference/scripts/update-or-delete.md) — single endpoint handling create, update, and delete -- [Batch save](../reference/scripts/batch-save.md) — create multiple records in parallel with `Record.save_all()` -- [Sidecar records](../reference/scripts/sidecar-records.md) — create linked records across collections with a shared rkey -- [Cascading delete](../reference/scripts/cascading-delete.md) — delete a record and all related records -- [Complex mutations](../reference/scripts/complex-mutations.md) — load, transform, and save a record with multiple field changes +- [Create a record](scripting/create-record.md) — simple write that saves input as a record +- [Upsert a record](scripting/upsert-record.md) — create or update using a deterministic rkey +- [Update or delete](scripting/update-or-delete.md) — single endpoint handling create, update, and delete +- [Batch save](scripting/batch-save.md) — create multiple records in parallel with `Record.save_all()` +- [Sidecar records](scripting/sidecar-records.md) — create linked records across collections with a shared rkey +- [Cascading delete](scripting/cascading-delete.md) — delete a record and all related records +- [Complex mutations](scripting/complex-mutations.md) — load, transform, and save a record with multiple field changes **Index Hooks:** -- [Algolia sync](../reference/scripts/algolia-sync.md) — push records to an Algolia search index on create/update/delete +- [Algolia sync](scripting/algolia-sync.md) — push records to an Algolia search index on create/update/delete ## Next steps -- [Index Hooks](index-hooks.md): React to record changes from the network in real time -- [Lexicons](lexicons.md): Understand how record, query, and procedure lexicons work together +- [Index Hooks](indexing/index-hooks.md): React to record changes from the network in real time +- [Lexicons](indexing/lexicons.md): Understand how record, query, and procedure lexicons work together - [XRPC API](../reference/xrpc-api.md): See how endpoints behave with and without Lua scripts - [Dashboard](../getting-started/dashboard.md#lua-editor): Use the web editor with context-aware completions diff --git a/packages/docs/docs/guides/scripting/algolia-sync.md b/packages/docs/docs/guides/scripting/algolia-sync.md index 80c9d99..30c27d2 100644 --- a/packages/docs/docs/guides/scripting/algolia-sync.md +++ b/packages/docs/docs/guides/scripting/algolia-sync.md @@ -37,7 +37,7 @@ end 1. On **create** or **update**: sends a `PUT` request to Algolia's index API with the record data, using the AT URI as the `objectID`. Algolia upserts the object — if it already exists, it's replaced. 2. On **delete**: sends a `DELETE` request to remove the object from the index by its AT URI. -The `json.encode()` function converts the Lua table into a JSON string for the request body. See [JSON API](../../guides/index-hooks.md#json-api). +The `json.encode()` function converts the Lua table into a JSON string for the request body. See [JSON API](../../reference/lua/json-api.md). ## Configuration diff --git a/packages/docs/docs/guides/scripting/batch-save.md b/packages/docs/docs/guides/scripting/batch-save.md index fdae884..fd363c7 100644 --- a/packages/docs/docs/guides/scripting/batch-save.md +++ b/packages/docs/docs/guides/scripting/batch-save.md @@ -23,8 +23,8 @@ end ## How it works -1. Iterate over `input.items` and create a [`Record`](../lua/record-api.md) instance for each item. -2. Call [`Record.save_all()`](../lua/record-api.md#static-methods) to save all records in parallel, rather than one at a time. +1. Iterate over `input.items` and create a [`Record`](../../reference/lua/record-api.md) instance for each item. +2. Call [`Record.save_all()`](../../reference/lua/record-api.md#static-methods) to save all records in parallel, rather than one at a time. 3. Collect the resulting AT URIs and return them. ## Usage diff --git a/packages/docs/docs/guides/scripting/cascading-delete.md b/packages/docs/docs/guides/scripting/cascading-delete.md index efdd53a..398fbae 100644 --- a/packages/docs/docs/guides/scripting/cascading-delete.md +++ b/packages/docs/docs/guides/scripting/cascading-delete.md @@ -49,7 +49,7 @@ end 1. Load the primary record by URI. Return early if it doesn't exist. 2. Query for related records, in this example comments by the same user that reference the primary record's URI. -3. Load each related record with [`Record.load`](../lua/record-api.md#static-methods) to get a deletable `Record` instance. +3. Load each related record with [`Record.load`](../../reference/lua/record-api.md#static-methods) to get a deletable `Record` instance. 4. Delete everything. Each `r:delete()` removes the record from the user's PDS and the local index. ## Usage diff --git a/packages/docs/docs/guides/scripting/complex-mutations.md b/packages/docs/docs/guides/scripting/complex-mutations.md index df71faf..93fb46a 100644 --- a/packages/docs/docs/guides/scripting/complex-mutations.md +++ b/packages/docs/docs/guides/scripting/complex-mutations.md @@ -56,7 +56,7 @@ end ## How it works -1. Load the existing record with [`Record.load`](../lua/record-api.md#static-methods). This gives you a mutable `Record` instance with all the current field values. +1. Load the existing record with [`Record.load`](../../reference/lua/record-api.md#static-methods). This gives you a mutable `Record` instance with all the current field values. 2. Apply transformations directly on the record's fields: - **Increment a counter**: use `or 0` to handle the field being `nil` on first access. - **Merge tags**: iterate over `input.tags`, skip duplicates already in `r.tags`, append new ones, then trim the list to 10. diff --git a/packages/docs/docs/guides/scripting/create-record.md b/packages/docs/docs/guides/scripting/create-record.md index f7bdf60..f8c0f94 100644 --- a/packages/docs/docs/guides/scripting/create-record.md +++ b/packages/docs/docs/guides/scripting/create-record.md @@ -14,7 +14,7 @@ end ## How it works -1. Create a new [`Record`](../lua/record-api.md) instance from the target collection, populated with the fields from the request body. +1. Create a new [`Record`](../../reference/lua/record-api.md) instance from the target collection, populated with the fields from the request body. 2. Call `r:save()`, which creates the record on the caller's PDS and indexes it locally. 3. Return the AT URI and CID of the newly created record. diff --git a/packages/docs/docs/guides/scripting/expanded-query.md b/packages/docs/docs/guides/scripting/expanded-query.md index 7136c1a..8415038 100644 --- a/packages/docs/docs/guides/scripting/expanded-query.md +++ b/packages/docs/docs/guides/scripting/expanded-query.md @@ -51,7 +51,7 @@ end 1. Query statuses from the target collection with pagination, same as a normal list query. 2. Extract the unique DIDs from the returned status URIs using `string.match`. 3. Build an AT URI for each DID's `app.bsky.actor.profile/self` record (this is where Bluesky profiles live). -4. Load all profiles in parallel with [`Record.load_all`](../lua/record-api.md#static-methods). Profiles that aren't indexed locally return `nil` and are skipped. +4. Load all profiles in parallel with [`Record.load_all`](../../reference/lua/record-api.md#static-methods). Profiles that aren't indexed locally return `nil` and are skipped. 5. Return statuses and profiles as separate keys, with the cursor from the status query. ## Usage diff --git a/packages/docs/docs/guides/scripting/get-record.md b/packages/docs/docs/guides/scripting/get-record.md index e42de61..6ecd7e4 100644 --- a/packages/docs/docs/guides/scripting/get-record.md +++ b/packages/docs/docs/guides/scripting/get-record.md @@ -22,7 +22,7 @@ end ## How it works 1. Check that the `uri` query parameter is present. Return a structured error if missing. -2. Look up the record with [`db.get`](../lua/database-api.md#dbget), which returns the record table or `nil`. +2. Look up the record with [`db.get`](../../reference/lua/database-api.md#dbget), which returns the record table or `nil`. 3. Return the record wrapped in an object. ## Usage diff --git a/packages/docs/docs/guides/scripting/list-or-fetch.md b/packages/docs/docs/guides/scripting/list-or-fetch.md index ae6c8a3..3aa63a2 100644 --- a/packages/docs/docs/guides/scripting/list-or-fetch.md +++ b/packages/docs/docs/guides/scripting/list-or-fetch.md @@ -25,8 +25,8 @@ end ## How it works -1. If a `uri` query parameter is provided, fetch that single record with [`db.get`](../lua/database-api.md#dbget) and return it. If it doesn't exist, return a structured error (using `error()` would trigger a 500 response). -2. Otherwise, list records from the target collection using [`db.query`](../lua/database-api.md#dbquery), with optional filtering by `did` and cursor-based pagination. The `cursor` is an opaque string from a previous response — pass it through directly. Since `limit` arrives as a string, `tonumber()` converts it to a number. +1. If a `uri` query parameter is provided, fetch that single record with [`db.get`](../../reference/lua/database-api.md#dbget) and return it. If it doesn't exist, return a structured error (using `error()` would trigger a 500 response). +2. Otherwise, list records from the target collection using [`db.query`](../../reference/lua/database-api.md#dbquery), with optional filtering by `did` and cursor-based pagination. The `cursor` is an opaque string from a previous response — pass it through directly. Since `limit` arrives as a string, `tonumber()` converts it to a number. ## Usage diff --git a/packages/docs/docs/guides/scripting/meilisearch-sync.md b/packages/docs/docs/guides/scripting/meilisearch-sync.md index 908e3bd..4061776 100644 --- a/packages/docs/docs/guides/scripting/meilisearch-sync.md +++ b/packages/docs/docs/guides/scripting/meilisearch-sync.md @@ -38,11 +38,11 @@ end 1. On **create** or **update**: sends a `POST` request to Meilisearch's document API with the record data wrapped in an array. Meilisearch upserts by `id` — if a document with the same AT URI already exists, it's replaced. 2. On **delete**: sends a `DELETE` request to remove the document from the index by its AT URI. -The `toarray()` function ensures the table is encoded as a JSON array (Meilisearch expects an array of documents). See [JSON API](../../guides/index-hooks.md#json-api). +The `toarray()` function ensures the table is encoded as a JSON array (Meilisearch expects an array of documents). See [JSON API](../../reference/lua/json-api.md). ## Configuration -This script uses [script variables](../../guides/scripting.md) instead of hardcoded values. Set these via the [admin API](../../reference/admin-api.md) or dashboard: +This script uses [script variables](../../guides/scripting.md) instead of hardcoded values. Set these via the [admin API](../../reference/admin/admin-api.md) or dashboard: | Variable | Value | | --------------------- | ------------------------------------------------------------------------------ | diff --git a/packages/docs/docs/guides/scripting/paginated-list.md b/packages/docs/docs/guides/scripting/paginated-list.md index cdf6358..b1aaeed 100644 --- a/packages/docs/docs/guides/scripting/paginated-list.md +++ b/packages/docs/docs/guides/scripting/paginated-list.md @@ -23,7 +23,7 @@ end ## How it works 1. Parse `limit` from the query string, defaulting to 20 and capping at 100. -2. Call [`db.query`](../lua/database-api.md#dbquery) with the target collection, optional DID filter, and cursor for pagination. +2. Call [`db.query`](../../reference/lua/database-api.md#dbquery) with the target collection, optional DID filter, and cursor for pagination. 3. Return the result directly. `db.query` returns `{ records = [...], cursor = "..." }` where `cursor` is an opaque string present when more records exist. ## Usage diff --git a/packages/docs/docs/guides/scripting/sidecar-records.md b/packages/docs/docs/guides/scripting/sidecar-records.md index 567ddeb..1d8d8e1 100644 --- a/packages/docs/docs/guides/scripting/sidecar-records.md +++ b/packages/docs/docs/guides/scripting/sidecar-records.md @@ -34,7 +34,7 @@ end 1. Generate a single [`TID()`](../../guides/scripting.md#utility-globals) to use as the rkey for both records. 2. Create a `Record` for each collection and call `r:set_rkey()` with the shared rkey. -3. Save both records in parallel with [`Record.save_all()`](../lua/record-api.md#static-methods). +3. Save both records in parallel with [`Record.save_all()`](../../reference/lua/record-api.md#static-methods). 4. Return both URIs so the client knows the identity of each record. ## Usage diff --git a/packages/docs/docs/guides/scripting/update-or-delete.md b/packages/docs/docs/guides/scripting/update-or-delete.md index fae642c..981e7aa 100644 --- a/packages/docs/docs/guides/scripting/update-or-delete.md +++ b/packages/docs/docs/guides/scripting/update-or-delete.md @@ -30,8 +30,8 @@ end ## How it works -1. If `input.delete` is truthy and `input.uri` is provided, load the record with [`Record.load`](../lua/record-api.md#static-methods) and delete it. -2. If only `input.uri` is provided, load the existing record with [`Record.load`](../lua/record-api.md#static-methods), update its fields, and save it back. Since `_uri` is already set, `r:save()` calls `putRecord` instead of `createRecord`. +1. If `input.delete` is truthy and `input.uri` is provided, load the record with [`Record.load`](../../reference/lua/record-api.md#static-methods) and delete it. +2. If only `input.uri` is provided, load the existing record with [`Record.load`](../../reference/lua/record-api.md#static-methods), update its fields, and save it back. Since `_uri` is already set, `r:save()` calls `putRecord` instead of `createRecord`. 3. If neither condition matches, create a new record from the input. ## Usage diff --git a/packages/docs/docs/guides/scripting/upsert-record.md b/packages/docs/docs/guides/scripting/upsert-record.md index 5abe3fc..020df36 100644 --- a/packages/docs/docs/guides/scripting/upsert-record.md +++ b/packages/docs/docs/guides/scripting/upsert-record.md @@ -33,7 +33,7 @@ end ## How it works 1. Use the client-provided `input.rkey` if present, otherwise generate a new [`TID()`](../../guides/scripting.md#utility-globals). This means omitting `rkey` always creates, while providing one enables updates. -2. Build the AT URI from the caller's DID, the target collection, and the rkey, then try to load it with [`Record.load`](../lua/record-api.md#static-methods). +2. Build the AT URI from the caller's DID, the target collection, and the rkey, then try to load it with [`Record.load`](../../reference/lua/record-api.md#static-methods). 3. If the record exists, update its fields and save. Since `_uri` is already set, `r:save()` calls `putRecord`. 4. If it doesn't exist, create a new record, set the rkey explicitly with `r:set_rkey()`, and save. This calls `createRecord` with the specified rkey. diff --git a/packages/docs/docs/reference/admin/admin-api.md b/packages/docs/docs/reference/admin/admin-api.md index 426f5f4..b94f655 100644 --- a/packages/docs/docs/reference/admin/admin-api.md +++ b/packages/docs/docs/reference/admin/admin-api.md @@ -1,12 +1,12 @@ # Admin API -The admin API lets you manage lexicons, monitor records, run backfill jobs, and control user access. All endpoints live under `/admin` and require authentication from a DID that exists in the `users` table, with the appropriate [permissions](../guides/permissions.md) for the endpoint being called. You can also manage all of this through the [web dashboard](../getting-started/dashboard.md). +The admin API lets you manage lexicons, monitor records, run backfill jobs, and control user access. All endpoints live under `/admin` and require authentication from a DID that exists in the `users` table, with the appropriate [permissions](../../guides/admin/permissions.md) for the endpoint being called. You can also manage all of this through the [web dashboard](../../getting-started/dashboard.md). ## Auth The admin API supports two authentication methods: -1. **API keys** — read/write tokens starting with `hv_`, passed as `Authorization: Bearer hv_...`. See the [API Keys guide](../guides/api-keys.md) for details. +1. **API keys** — read/write tokens starting with `hv_`, passed as `Authorization: Bearer hv_...`. See the [API Keys guide](../../guides/admin/api-keys.md) for details. 2. **Service auth JWT** — atproto inter-service authentication via signed JWTs. In all cases the resolved DID is checked against the `users` table, and the user's permissions are loaded to authorize the request. @@ -41,22 +41,22 @@ AUTH="Authorization: Bearer $TOKEN" | Group | Description | | ----- | ----------- | -| [Lexicons](admin/lexicons.md) | Upload, list, get, and delete lexicons and network lexicons | -| [Stats](admin/stats.md) | Record counts by collection | -| [Backfill](admin/backfill.md) | Create and monitor historical backfill jobs | -| [Event Logs](admin/events.md) | Query the audit trail of system events | -| [API Keys](admin/api-keys.md) | Create, list, and revoke API keys | -| [Users](admin/users.md) | Create, list, update, and delete admin users | -| [Labelers](admin/labelers.md) | Manage external labeler subscriptions | -| [Instance Settings](admin/settings.md) | Configure app name, logo, and policy URLs | -| [Domains](admin/domains.md) | Manage domains and their OAuth client identities | -| [Script Variables](admin/script-variables.md) | Encrypted key/value pairs for Lua scripts | -| [API Clients](admin/api-clients.md) | Register and manage third-party XRPC clients | -| [Plugins](admin/plugins.md) | Install, configure, and manage WASM plugins | +| [Lexicons](lexicons.md) | Upload, list, get, and delete lexicons and network lexicons | +| [Stats](stats.md) | Record counts by collection | +| [Backfill](backfill.md) | Create and monitor historical backfill jobs | +| [Event Logs](events.md) | Query the audit trail of system events | +| [API Keys](api-keys.md) | Create, list, and revoke API keys | +| [Users](users.md) | Create, list, update, and delete admin users | +| [Labelers](labelers.md) | Manage external labeler subscriptions | +| [Instance Settings](settings.md) | Configure app name, logo, and policy URLs | +| [Domains](domains.md) | Manage domains and their OAuth client identities | +| [Script Variables](script-variables.md) | Encrypted key/value pairs for Lua scripts | +| [API Clients](api-clients.md) | Register and manage third-party XRPC clients | +| [Plugins](plugins.md) | Install, configure, and manage WASM plugins | ## Permissions -Each admin API endpoint requires a specific permission. See the [Permissions guide](../guides/permissions.md) for the full list of permissions and templates. +Each admin API endpoint requires a specific permission. See the [Permissions guide](../../guides/admin/permissions.md) for the full list of permissions and templates. | Endpoint | Required Permission | | ---------------------------------------- | -------------------------- | diff --git a/packages/docs/docs/reference/admin/api-clients.md b/packages/docs/docs/reference/admin/api-clients.md index e1f5f2a..877d5bf 100644 --- a/packages/docs/docs/reference/admin/api-clients.md +++ b/packages/docs/docs/reference/admin/api-clients.md @@ -4,7 +4,7 @@ API clients identify third-party applications that call HappyView's XRPC endpoin A single API client represents your application, not individual users. Create one client for your app and use the same client key across all instances. Users authenticate separately via OAuth — the client key identifies _your app_, not _who is using it_. -Each client has an `hvc_`-prefixed client key and an `hvs_`-prefixed client secret. The secret is only returned at creation and is sha256-hashed in the database. Server-to-server callers pass the secret as `X-Client-Secret`. Browser callers use the `Origin` header, which is matched against the client's `client_uri`. Mismatches currently log warnings rather than rejecting the request, but rate limiting applies either way. See [Authentication — XRPC](../../getting-started/authentication.md#xrpc-api-client-identification) for the client-side view, and the [API Keys guide](../../guides/api-keys.md) for how admin API keys differ from API clients. +Each client has an `hvc_`-prefixed client key and an `hvs_`-prefixed client secret. The secret is only returned at creation and is sha256-hashed in the database. Server-to-server callers pass the secret as `X-Client-Secret`. Browser callers use the `Origin` header, which is matched against the client's `client_uri`. Mismatches currently log warnings rather than rejecting the request, but rate limiting applies either way. See [Authentication — XRPC](../../getting-started/authentication.md#xrpc-api-client-identification) for the client-side view, and the [API Keys guide](../../guides/admin/api-keys.md) for how admin API keys differ from API clients. ```sh # All examples assume $TOKEN is an API key (hv_...) diff --git a/packages/docs/docs/reference/admin/api-keys.md b/packages/docs/docs/reference/admin/api-keys.md index 7da604f..d7544e6 100644 --- a/packages/docs/docs/reference/admin/api-keys.md +++ b/packages/docs/docs/reference/admin/api-keys.md @@ -1,6 +1,6 @@ # Admin API: API Keys -Manage API keys for programmatic access. See the [API Keys guide](../../guides/api-keys.md) for usage details. +Manage API keys for programmatic access. See the [API Keys guide](../../guides/admin/api-keys.md) for usage details. ```sh # All examples assume $TOKEN is an API key (hv_...) diff --git a/packages/docs/docs/reference/admin/backfill.md b/packages/docs/docs/reference/admin/backfill.md index a0369c2..d5bd5f6 100644 --- a/packages/docs/docs/reference/admin/backfill.md +++ b/packages/docs/docs/reference/admin/backfill.md @@ -1,6 +1,6 @@ # Admin API: Backfill -Create and monitor historical backfill jobs. See the [Backfill guide](../../guides/backfill.md) for background. +Create and monitor historical backfill jobs. See the [Backfill guide](../../guides/indexing/backfill.md) for background. ```sh # All examples assume $TOKEN is an API key (hv_...) diff --git a/packages/docs/docs/reference/admin/events.md b/packages/docs/docs/reference/admin/events.md index c3788c4..5dbea1f 100644 --- a/packages/docs/docs/reference/admin/events.md +++ b/packages/docs/docs/reference/admin/events.md @@ -1,6 +1,6 @@ # Admin API: Event Logs -HappyView logs system events — lexicon changes, record operations, script errors, user actions, and more. See the [Event Logs guide](../../guides/event-logs.md) for details on event types and retention. +HappyView logs system events — lexicon changes, record operations, script errors, user actions, and more. See the [Event Logs guide](../../guides/admin/event-logs.md) for details on event types and retention. ```sh # All examples assume $TOKEN is an API key (hv_...) diff --git a/packages/docs/docs/reference/admin/labelers.md b/packages/docs/docs/reference/admin/labelers.md index 4434b2a..f423803 100644 --- a/packages/docs/docs/reference/admin/labelers.md +++ b/packages/docs/docs/reference/admin/labelers.md @@ -1,6 +1,6 @@ # Admin API: Labelers -Manage external labeler subscriptions. See the [Labelers guide](../../guides/labelers.md) for background. +Manage external labeler subscriptions. See the [Labelers guide](../../guides/features/labelers.md) for background. ```sh # All examples assume $TOKEN is an API key (hv_...) diff --git a/packages/docs/docs/reference/admin/lexicons.md b/packages/docs/docs/reference/admin/lexicons.md index 396d7dc..6139c79 100644 --- a/packages/docs/docs/reference/admin/lexicons.md +++ b/packages/docs/docs/reference/admin/lexicons.md @@ -1,6 +1,6 @@ # Admin API: Lexicons -Manage lexicons and network lexicons. See the [Lexicons guide](../../guides/lexicons.md) for background on how lexicons drive indexing and XRPC routing. +Manage lexicons and network lexicons. See the [Lexicons guide](../../guides/indexing/lexicons.md) for background on how lexicons drive indexing and XRPC routing. ```sh # All examples assume $TOKEN is an API key (hv_...) @@ -30,7 +30,7 @@ curl -X POST http://localhost:3000/admin/lexicons \ | `backfill` | boolean | no | Whether uploading triggers historical backfill (default `true`) | | `target_collection` | string | no | For query/procedure lexicons, the record collection they operate on | | `script` | string | no | Lua script for query/procedure endpoints | -| `index_hook` | string | no | [Index hook](../../guides/index-hooks.md) Lua script for record lexicons | +| `index_hook` | string | no | [Index hook](../../guides/indexing/index-hooks.md) Lua script for record lexicons | **Response**: `201 Created` (new) or `200 OK` (upsert) @@ -92,7 +92,7 @@ curl -X DELETE http://localhost:3000/admin/lexicons/xyz.statusphere.status -H "$ ## Network Lexicons -Network lexicons are fetched from the atproto network via DNS TXT resolution and kept updated via the Jetstream subscription. See [Lexicons - Network lexicons](../../guides/lexicons.md#network-lexicons) for background. +Network lexicons are fetched from the atproto network via DNS TXT resolution and kept updated via the Jetstream subscription. See [Lexicons - Network lexicons](../../guides/indexing/lexicons.md#network-lexicons) for background. ### Add a network lexicon diff --git a/packages/docs/docs/reference/admin/plugins.md b/packages/docs/docs/reference/admin/plugins.md index 52f7c44..d126977 100644 --- a/packages/docs/docs/reference/admin/plugins.md +++ b/packages/docs/docs/reference/admin/plugins.md @@ -1,6 +1,6 @@ # Admin API: Plugins -Plugins extend HappyView with WebAssembly modules sourced from the [official plugin registry](../../guides/plugins.md) or any URL serving a `manifest.json`. Most endpoints take a plugin manifest URL and load (or reload) the plugin in place — no restart needed. Encrypted plugin secrets require `TOKEN_ENCRYPTION_KEY` to be configured. +Plugins extend HappyView with WebAssembly modules sourced from the [official plugin registry](../../guides/features/plugins.md) or any URL serving a `manifest.json`. Most endpoints take a plugin manifest URL and load (or reload) the plugin in place — no restart needed. Encrypted plugin secrets require `TOKEN_ENCRYPTION_KEY` to be configured. ```sh # All examples assume $TOKEN is an API key (hv_...) diff --git a/packages/docs/docs/reference/admin/users.md b/packages/docs/docs/reference/admin/users.md index 3e5c667..05eac73 100644 --- a/packages/docs/docs/reference/admin/users.md +++ b/packages/docs/docs/reference/admin/users.md @@ -1,6 +1,6 @@ # Admin API: Users -Manage admin users and their permissions. See the [Permissions guide](../../guides/permissions.md) for available permissions and templates. +Manage admin users and their permissions. See the [Permissions guide](../../guides/admin/permissions.md) for available permissions and templates. ```sh # All examples assume $TOKEN is an API key (hv_...) diff --git a/packages/docs/docs/reference/architecture.md b/packages/docs/docs/reference/architecture.md index 82172c8..766c258 100644 --- a/packages/docs/docs/reference/architecture.md +++ b/packages/docs/docs/reference/architecture.md @@ -31,7 +31,7 @@ graph LR Labeler["Labeler
WebSocket (out-of-band)"] -->|label events| DB ``` -Queries go through the query handler to the database (SQLite by default, or Postgres). Writes go through the procedure handler to the user's PDS, then HappyView indexes the record locally. Real-time record events stream in via [Jetstream](https://github.com/bluesky-social/jetstream); historical records are backfilled in-process by discovering repos via the relay's `listReposByCollection` and fetching records directly from each PDS. [Labelers](../guides/labelers.md) are external services that emit content labels over a direct WebSocket connection — they operate out-of-band, outside the relay/repo system. +Queries go through the query handler to the database (SQLite by default, or Postgres). Writes go through the procedure handler to the user's PDS, then HappyView indexes the record locally. Real-time record events stream in via [Jetstream](https://github.com/bluesky-social/jetstream); historical records are backfilled in-process by discovering repos via the relay's `listReposByCollection` and fetching records directly from each PDS. [Labelers](../guides/features/labelers.md) are external services that emit content labels over a direct WebSocket connection — they operate out-of-band, outside the relay/repo system. ## Request flow diff --git a/packages/docs/docs/reference/glossary.md b/packages/docs/docs/reference/glossary.md index 51b4d5a..f19dd87 100644 --- a/packages/docs/docs/reference/glossary.md +++ b/packages/docs/docs/reference/glossary.md @@ -12,7 +12,7 @@ Key terms used throughout the HappyView documentation. For a broader introductio **Handle** — A human-readable name for an account (e.g. `user.bsky.social`). Handles resolve to a DID via a DNS TXT record or an HTTP `.well-known/atproto-did` lookup. -**Lexicon** — A schema definition for atproto data types and API methods. Lexicons define what records look like, what endpoints exist, and what parameters they accept. See [Lexicons](../guides/lexicons.md). +**Lexicon** — A schema definition for atproto data types and API methods. Lexicons define what records look like, what endpoints exist, and what parameters they accept. See [Lexicons](../guides/indexing/lexicons.md). **NSID** (Namespaced Identifier) — A reverse-DNS identifier for a lexicon (e.g. `xyz.statusphere.status`). The authority is everything except the last segment. @@ -22,7 +22,7 @@ Key terms used throughout the HappyView documentation. For a broader introductio **Record** — A single piece of data in an atproto repository, identified by an AT URI (e.g. `at://did:plc:abc/xyz.statusphere.status/abc123`). -**Relay** — A network service that aggregates repository data from many PDSes. HappyView queries the relay during [backfill](../guides/backfill.md) to discover which repos contain records for a given collection, then fetches each repo's records directly from its PDS. +**Relay** — A network service that aggregates repository data from many PDSes. HappyView queries the relay during [backfill](../guides/indexing/backfill.md) to discover which repos contain records for a given collection, then fetches each repo's records directly from its PDS. **rkey** (Record Key) — The unique key for a record within a collection and repo. These are most commonly TIDs (timestamp-based) or NSIDs. @@ -34,11 +34,11 @@ Key terms used throughout the HappyView documentation. For a broader introductio ## HappyView-specific terms -**Backfill** — The process of bulk-indexing existing records from the network. HappyView discovers repos via the relay and fetches each repo's records directly from its PDS. Runs when a new record-type lexicon is uploaded or triggered manually. See [Backfill](../guides/backfill.md). +**Backfill** — The process of bulk-indexing existing records from the network. HappyView discovers repos via the relay and fetches each repo's records directly from its PDS. Runs when a new record-type lexicon is uploaded or triggered manually. See [Backfill](../guides/indexing/backfill.md). -**Network lexicon** — A lexicon fetched directly from the atproto network via DNS authority resolution, rather than uploaded manually. See [Lexicons - Network lexicons](../guides/lexicons.md#network-lexicons). +**Network lexicon** — A lexicon fetched directly from the atproto network via DNS authority resolution, rather than uploaded manually. See [Lexicons - Network lexicons](../guides/indexing/lexicons.md#network-lexicons). -**Permission** — A granular access control right that authorizes a specific action in the admin API. HappyView defines 20 permissions organized by category (e.g. `lexicons:create`, `users:read`). See [Permissions](../guides/permissions.md). +**Permission** — A granular access control right that authorizes a specific action in the admin API. HappyView defines 20 permissions organized by category (e.g. `lexicons:create`, `users:read`). See [Permissions](../guides/admin/permissions.md). **Permission template** — A predefined set of permissions that can be applied when creating a user. Templates are: **Viewer** (read-only access), **Operator** (viewer + backfill and API key management), **Manager** (operator + lexicon and record management), and **Full Access** (all 20 permissions). diff --git a/packages/docs/docs/reference/lua/atproto-api.md b/packages/docs/docs/reference/lua/atproto-api.md index cad79e5..271e965 100644 --- a/packages/docs/docs/reference/lua/atproto-api.md +++ b/packages/docs/docs/reference/lua/atproto-api.md @@ -1,6 +1,6 @@ # atproto API -The `atproto` table provides atproto utility functions. Available in queries, procedures, and [index hooks](../../guides/index-hooks.md). +The `atproto` table provides atproto utility functions. Available in queries, procedures, and [index hooks](../../guides/indexing/index-hooks.md). ## atproto.resolve_service_endpoint diff --git a/packages/docs/docs/reference/lua/database-api.md b/packages/docs/docs/reference/lua/database-api.md index df2fc78..f04667f 100644 --- a/packages/docs/docs/reference/lua/database-api.md +++ b/packages/docs/docs/reference/lua/database-api.md @@ -1,6 +1,6 @@ # Database API -The `db` table provides access to the database. Available in queries, procedures, and [index hooks](../../guides/index-hooks.md). +The `db` table provides access to the database. Available in queries, procedures, and [index hooks](../../guides/indexing/index-hooks.md). ## db.query @@ -95,7 +95,7 @@ Parameters are passed as an array and bound to `$1`, `$2`, etc. Supported parame ### SQL dialect -Write SQL in **SQLite syntax** — HappyView translates it to Postgres at runtime if you're using Postgres. See [Database Setup](../../guides/database-setup.md) for details on what gets translated. If you need database-specific SQL that can't be translated, check `db.is_postgres()` at runtime. +Write SQL in **SQLite syntax** — HappyView translates it to Postgres at runtime if you're using Postgres. See [Database Setup](../../guides/database/database-setup.md) for details on what gets translated. If you need database-specific SQL that can't be translated, check `db.is_postgres()` at runtime. ### Column type mapping diff --git a/packages/docs/docs/reference/lua/http-api.md b/packages/docs/docs/reference/lua/http-api.md index e1ef264..8d1c935 100644 --- a/packages/docs/docs/reference/lua/http-api.md +++ b/packages/docs/docs/reference/lua/http-api.md @@ -1,6 +1,6 @@ # HTTP API -The `http` table provides async HTTP client functions. Available in queries, procedures, and [index hooks](../../guides/index-hooks.md). +The `http` table provides async HTTP client functions. Available in queries, procedures, and [index hooks](../../guides/indexing/index-hooks.md). ## Methods diff --git a/packages/docs/docs/reference/lua/json-api.md b/packages/docs/docs/reference/lua/json-api.md index ce46d42..7d712d7 100644 --- a/packages/docs/docs/reference/lua/json-api.md +++ b/packages/docs/docs/reference/lua/json-api.md @@ -1,6 +1,6 @@ # JSON API -The `json` global provides JSON serialization and deserialization. Available in queries, procedures, and [index hooks](../../guides/index-hooks.md). +The `json` global provides JSON serialization and deserialization. Available in queries, procedures, and [index hooks](../../guides/indexing/index-hooks.md). ## json.encode diff --git a/packages/docs/docs/reference/lua/utility-globals.md b/packages/docs/docs/reference/lua/utility-globals.md index d5317ce..95da1e5 100644 --- a/packages/docs/docs/reference/lua/utility-globals.md +++ b/packages/docs/docs/reference/lua/utility-globals.md @@ -1,6 +1,6 @@ # Utility Globals -Global functions available in queries, procedures, and [index hooks](../../guides/index-hooks.md). These don't belong to a specific API table — they're available at the top level of any Lua script. +Global functions available in queries, procedures, and [index hooks](../../guides/indexing/index-hooks.md). These don't belong to a specific API table — they're available at the top level of any Lua script. ## now diff --git a/packages/docs/docs/reference/troubleshooting.md b/packages/docs/docs/reference/troubleshooting.md index d3e2645..eae25bf 100644 --- a/packages/docs/docs/reference/troubleshooting.md +++ b/packages/docs/docs/reference/troubleshooting.md @@ -18,9 +18,9 @@ Common issues and how to resolve them. **Causes**: -- The query lexicon is missing a `target_collection`. Without it, the query doesn't know which records to read. See [Lexicons - target_collection](../guides/lexicons.md#target-collection). +- The query lexicon is missing a `target_collection`. Without it, the query doesn't know which records to read. See [Lexicons - target_collection](../guides/indexing/lexicons.md#target-collection). - The record-type lexicon hasn't finished backfilling. Check backfill status with `GET /admin/backfill/status` or the dashboard. -- Records exist on the network but HappyView hasn't indexed them yet. Jetstream only delivers events from after the collection was added to the filter. Use [backfill](../guides/backfill.md) to import historical records. +- Records exist on the network but HappyView hasn't indexed them yet. Jetstream only delivers events from after the collection was added to the filter. Use [backfill](../guides/indexing/backfill.md) to import historical records. ## Procedure returns 401 Unauthorized @@ -48,7 +48,7 @@ Common issues and how to resolve them. **Causes**: -- Your user account doesn't have the specific permission required by the endpoint. Each endpoint requires a specific permission — see the [permissions table](admin-api.md#permissions). +- Your user account doesn't have the specific permission required by the endpoint. Each endpoint requires a specific permission — see the [permissions table](admin/admin-api.md#permissions). - If using an API key, the key's effective permissions are the intersection of the key's permissions and your user permissions. A key can never have more access than the user who created it. - Only the super user can call `POST /admin/users/transfer-super`. This endpoint cannot be accessed with any permission — it requires super user status. @@ -74,7 +74,7 @@ See [Lua Scripting - Debugging](../guides/scripting.md#debugging) for more. - The relay (`RELAY_URL`) may be unreachable or slow to respond. Check connectivity. - Individual PDS fetches can fail silently. The worker logs warnings and continues. Check server logs for details. -See [Backfill](../guides/backfill.md) for how the process works. +See [Backfill](../guides/indexing/backfill.md) for how the process works. ## Records not appearing in real time @@ -102,7 +102,7 @@ See [Backfill](../guides/backfill.md) for how the process works. **Causes**: -- `TOKEN_ENCRYPTION_KEY` is not set. Plugin secrets are encrypted at rest and cannot be read without this key. See [Plugins - Configuration](../guides/plugins.md#plugin-configuration). +- `TOKEN_ENCRYPTION_KEY` is not set. Plugin secrets are encrypted at rest and cannot be read without this key. See [Plugins - Configuration](../guides/features/plugins.md#plugin-configuration). - If `TOKEN_ENCRYPTION_KEY` changed since the secrets were saved, the existing encrypted values are unreadable. Re-enter the secrets via the dashboard or `PUT /admin/plugins/{id}/secrets`. - Environment variable secrets (`PLUGIN__`) are overridden by dashboard-configured secrets. If you've set both, the dashboard values take precedence. @@ -143,7 +143,7 @@ See [Configuration](../getting-started/configuration.md) for environment variabl **Explanation**: Each database is independent. Switching `DATABASE_URL` points HappyView at a fresh database. Your old data is still in the previous database file or Postgres instance. -**Recovery**: Re-upload your lexicons and run backfills to re-index records from the network. Admin settings, users, and API keys need to be re-created manually. See the [SQLite → Postgres](../guides/sqlite-to-postgres-migration.md) or [Postgres → SQLite](../guides/postgres-to-sqlite-migration.md) migration guides. +**Recovery**: Re-upload your lexicons and run backfills to re-index records from the network. Admin settings, users, and API keys need to be re-created manually. See the [SQLite → Postgres](../guides/database/sqlite-to-postgres-migration.md) or [Postgres → SQLite](../guides/database/postgres-to-sqlite-migration.md) migration guides. ## Jetstream disconnects frequently diff --git a/packages/docs/docs/reference/xrpc-api.md b/packages/docs/docs/reference/xrpc-api.md index 7b5f7fa..0253b94 100644 --- a/packages/docs/docs/reference/xrpc-api.md +++ b/packages/docs/docs/reference/xrpc-api.md @@ -1,6 +1,6 @@ # XRPC API -[XRPC](https://atproto.com/specs/xrpc) is the HTTP-based RPC protocol used by the atproto. HappyView dynamically registers XRPC endpoints based on your uploaded [lexicons](../guides/lexicons.md): query lexicons become `GET /xrpc/{nsid}` routes, procedure lexicons become `POST /xrpc/{nsid}` routes. +[XRPC](https://atproto.com/specs/xrpc) is the HTTP-based RPC protocol used by the atproto. HappyView dynamically registers XRPC endpoints based on your uploaded [lexicons](../guides/indexing/lexicons.md): query lexicons become `GET /xrpc/{nsid}` routes, procedure lexicons become `POST /xrpc/{nsid}` routes. If a query or procedure lexicon has a [Lua script](../guides/scripting.md) attached, the script handles the request. Otherwise, HappyView uses built-in default behavior (described below). @@ -210,5 +210,5 @@ When a procedure proxies a write to the user's PDS and the PDS returns an error, ## Next steps - [Lua Scripting](../guides/scripting.md): Override the default query and procedure behavior with custom logic -- [Lexicons](../guides/lexicons.md): Understand how lexicons generate these endpoints -- [Admin API](admin-api.md): Manage lexicons and monitor your instance +- [Lexicons](../guides/indexing/lexicons.md): Understand how lexicons generate these endpoints +- [Admin API](admin/admin-api.md): Manage lexicons and monitor your instance diff --git a/packages/docs/docs/tutorials/statusphere.md b/packages/docs/docs/tutorials/statusphere.md index daba446..0872f25 100644 --- a/packages/docs/docs/tutorials/statusphere.md +++ b/packages/docs/docs/tutorials/statusphere.md @@ -21,7 +21,7 @@ For more background on how the app works, see the [ATProto Statusphere guide](ht ## Step 1: Add the record lexicon -First, tell HappyView to start indexing Statusphere records. Since `xyz.statusphere.status` is [published on the atproto network](../guides/lexicons.md#network-lexicons), you can add it directly from the dashboard: +First, tell HappyView to start indexing Statusphere records. Since `xyz.statusphere.status` is [published on the atproto network](../guides/indexing/lexicons.md#network-lexicons), you can add it directly from the dashboard: 1. Go to **Lexicons > Add Lexicon > Network** 2. Enter `xyz.statusphere.status` @@ -207,13 +207,13 @@ With three lexicons and a few lines of Lua, you have a complete Statusphere AppV - **A query endpoint** (`xyz.statusphere.listStatuses`) with filtering, pagination, and single-record lookups - **A write endpoint** (`xyz.statusphere.setStatus`) that creates records on the user's PDS and indexes them locally -Everything was done through the dashboard — no server restarts, no config files, no deploys. For automation and CI/CD, the same operations are available via the [admin API](../reference/admin-api.md). +Everything was done through the dashboard — no server restarts, no config files, no deploys. For automation and CI/CD, the same operations are available via the [admin API](../reference/admin/admin-api.md). ## Next steps - [Lua Scripting](../guides/scripting.md): Explore the full Record and database APIs to build more complex queries -- [Lexicons](../guides/lexicons.md): Learn about network lexicons, the backfill flag, and target collections +- [Lexicons](../guides/indexing/lexicons.md): Learn about network lexicons, the backfill flag, and target collections - [XRPC API](../reference/xrpc-api.md): Understand how the generated endpoints behave -- [Admin API](../reference/admin-api.md): Automate lexicon management via the API +- [Admin API](../reference/admin/admin-api.md): Automate lexicon management via the API - [Statusphere example app](https://github.com/bluesky-social/statusphere-example-app): See the full Statusphere frontend - [ATProto Statusphere guide](https://atproto.com/guides/applications): How the app works at the protocol level diff --git a/packages/docs/sidebars.ts b/packages/docs/sidebars.ts index 99da384..0b90bc7 100644 --- a/packages/docs/sidebars.ts +++ b/packages/docs/sidebars.ts @@ -74,6 +74,32 @@ const sidebars: SidebarsConfig = { type: "category", label: "Guides", items: [ + { + type: "category", + label: "Features", + items: [ + { + type: "doc", + id: "guides/features/api-clients", + label: "API Clients", + }, + { + type: "doc", + id: "guides/features/labelers", + label: "Labelers", + }, + { + type: "doc", + id: "guides/features/plugins", + label: "Plugins", + }, + { + type: "doc", + id: "guides/features/developing-plugins", + label: "Developing Plugins", + }, + ], + }, { type: "category", label: "Indexing", @@ -177,32 +203,6 @@ const sidebars: SidebarsConfig = { }, ], }, - { - type: "category", - label: "Features", - items: [ - { - type: "doc", - id: "guides/features/api-clients", - label: "API Clients", - }, - { - type: "doc", - id: "guides/features/labelers", - label: "Labelers", - }, - { - type: "doc", - id: "guides/features/plugins", - label: "Plugins", - }, - { - type: "doc", - id: "guides/features/developing-plugins", - label: "Developing Plugins", - }, - ], - }, { type: "category", label: "Administration", -- 2.51.2