A lexicon-driven AppView for ATProto. happyview.dev
backfill firehose jetstream atproto appview oauth lexicon
8
fork

Configure Feed

Select the types of activity you want to include in your feed.

docs: refer to `atproto`

Trezy dfc662d4 0941aa37

+108 -194
+3 -3
packages/docs/docs/README.md
··· 1 1 # HappyView 2 2 3 - 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#at-protocol-terms) schemas and get a fully functional AppView, complete with [XRPC](reference/glossary.md#at-protocol-terms) endpoints, OAuth, real-time network sync, and historical [backfill](guides/backfill.md), without writing a single line of server code. 3 + 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. 4 4 5 5 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. 6 6 ··· 8 8 9 9 - **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. 10 10 11 - - **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 AT Protocol OAuth with DPoP-bound proxy writes back to the PDS. 11 + - **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. 12 12 13 13 - **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. 14 14 ··· 24 24 25 25 - **Runtime-configurable**: Lexicons can be added, updated, and removed without restarting the server. New endpoints and sync rules take effect immediately, so you can iterate on your data model in real time. 26 26 27 - - **Protocol-native**: HappyView works with _any_ PDS, resolves DIDs through the directory, and follows AT Protocol conventions. It's a first-class citizen of the network, not a wrapper around it. 27 + - **Protocol-native**: HappyView works with _any_ PDS, resolves DIDs through the directory, and follows atproto conventions. It's a first-class citizen of the network, not a wrapper around it. 28 28 29 29 ## Next Steps 30 30
+4 -4
packages/docs/docs/getting-started/authentication.md
··· 2 2 3 3 HappyView has two distinct authentication surfaces: 4 4 5 - - **XRPC** (`/xrpc/*`) — client-level identification via an **API client key** on every request, plus optional user-level AT Protocol OAuth for endpoints that need a specific user's identity (e.g. procedures that write to a PDS). 5 + - **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). 6 6 - **Admin API** (`/admin/*`) — user-level authentication via admin API keys or service auth JWTs, gated by [permissions](../guides/permissions.md). 7 7 8 8 ## Which endpoints require what? ··· 49 49 50 50 ### Authenticating users for procedures 51 51 52 - Queries that don't care who is calling need nothing more than the client key. Procedures — and queries whose Lua scripts read the caller's DID — need a real AT Protocol OAuth session. 52 + Queries that don't care who is calling need nothing more than the client key. Procedures — and queries whose Lua scripts read the caller's DID — need a real atproto OAuth session. 53 53 54 54 XRPC routes only accept **DPoP auth** (`Authorization: DPoP <token>` + `DPoP` proof header + `X-Client-Key`). Bearer tokens and service auth JWTs are not accepted on XRPC endpoints. 55 55 ··· 103 103 104 104 ### Service auth JWT 105 105 106 - HappyView also accepts standard AT Protocol inter-service auth JWTs in the `Authorization` header. Another AppView, relay, or PDS can sign a short-lived ES256 or ES256K JWT with its DID's signing key; HappyView resolves the issuer's DID document, verifies the signature against the `#atproto` verification method, and treats the issuer DID as the caller identity. 106 + HappyView also accepts standard atproto inter-service auth JWTs in the `Authorization` header. Another AppView, relay, or PDS can sign a short-lived ES256 or ES256K JWT with its DID's signing key; HappyView resolves the issuer's DID document, verifies the signature against the `#atproto` verification method, and treats the issuer DID as the caller identity. 107 107 108 108 For a service auth JWT to validate: 109 109 ··· 186 186 187 187 #### 2. Run OAuth with the user's PDS 188 188 189 - Use the provisioned DPoP key as your DPoP keypair in a standard AT Protocol OAuth flow with the user's PDS. HappyView is not involved in this step — the app talks directly to the PDS authorization server. 189 + Use the provisioned DPoP key as your DPoP keypair in a standard atproto OAuth flow with the user's PDS. HappyView is not involved in this step — the app talks directly to the PDS authorization server. 190 190 191 191 #### 3. Register the session 192 192
+5 -5
packages/docs/docs/getting-started/dashboard.md
··· 1 1 # Dashboard 2 2 3 - 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 AT Protocol OAuth. 3 + 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. 4 4 5 5 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. 6 6 ··· 23 23 24 24 Toggle **Enable backfill** to index historical records when uploading a record-type lexicon. 25 25 26 - **Network** lexicons are fetched from the AT Protocol 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. 26 + **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. 27 27 28 28 ### JSON editor 29 29 30 - The JSON editor provides real-time validation against the AT Protocol Lexicon v1 schema: 30 + The JSON editor provides real-time validation against the atproto Lexicon v1 schema: 31 31 32 32 - Validation for Lexicon format 33 33 - Auto-complete for definition types (`record`, `query`, `procedure`, `subscription`), property types (`string`, `integer`, `boolean`, `ref`, `union`, `blob`, `cid-link`, etc.), and schema structure (`defs`, `main`, `properties`, `required`) ··· 41 41 42 42 ## Records 43 43 44 - Navigate to **Records** to browse all indexed AT Protocol records. Records are grouped by collection and searchable. Each record shows its AT URI, author DID, and the raw record JSON. 44 + Navigate to **Records** to browse all indexed atproto records. Records are grouped by collection and searchable. Each record shows its AT URI, author DID, and the raw record JSON. 45 45 46 46 ## Backfill 47 47 ··· 89 89 90 90 ### Accounts 91 91 92 - Manage connected AT Protocol accounts used by the instance. 92 + Manage connected atproto accounts used by the instance. 93 93 94 94 ## Next steps 95 95
+2 -2
packages/docs/docs/getting-started/quickstart.md
··· 1 1 # Quickstart 2 2 3 - This page walks you through the fastest path to a working HappyView instance. By the end, you'll have an AppView that indexes records from the AT Protocol network and serves XRPC endpoints. 3 + This page walks you through the fastest path to a working HappyView instance. By the end, you'll have an AppView that indexes records from the atproto network and serves XRPC endpoints. 4 4 5 5 ## 1. Deploy HappyView 6 6 ··· 16 16 17 17 ## 2. Log in to the dashboard 18 18 19 - The built-in [dashboard](dashboard.md) is served at your instance's root URL. Log in with your AT Protocol identity — on a fresh deployment, the first handle to authenticate is automatically bootstrapped as the **super user** with all permissions, so use the handle you want to own the instance. 19 + The built-in [dashboard](dashboard.md) is served at your instance's root URL. Log in with your atproto identity — on a fresh deployment, the first handle to authenticate is automatically bootstrapped as the **super user** with all permissions, so use the handle you want to own the instance. 20 20 21 21 ## 3. Add your first lexicon 22 22
+1 -1
packages/docs/docs/guides/backfill.md
··· 29 29 30 30 ## Restoring deleted records 31 31 32 - Deleting records from HappyView (via the dashboard or API) only removes them from the local database — the records still exist on the AT Protocol network. To restore deleted records, create a backfill job for the affected collection. The backfill will re-discover the repos and re-fetch all records from each PDS, restoring any that were previously deleted. 32 + Deleting records from HappyView (via the dashboard or API) only removes them from the local database — the records still exist on the atproto network. To restore deleted records, create a backfill job for the affected collection. The backfill will re-discover the repos and re-fetch all records from each PDS, restoring any that were previously deleted. 33 33 34 34 ## Next steps 35 35
+1 -1
packages/docs/docs/guides/labelers.md
··· 78 78 ## Next steps 79 79 80 80 - [Admin API — Labelers](../reference/admin/labelers.md) — full endpoint documentation 81 - - [AT Protocol API](../reference/lua/atproto-api.md) — access labels in Lua scripts with `get_labels` and `get_labels_batch` 81 + - [atproto API](../reference/lua/atproto-api.md) — access labels in Lua scripts with `get_labels` and `get_labels_batch` 82 82 - [Permissions](permissions.md) — manage user access to labeler operations
+2 -2
packages/docs/docs/guides/lexicons.md
··· 1 1 # Lexicons 2 2 3 - Lexicons are the core building block of HappyView. They're [AT Protocol 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. 3 + 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. 4 4 5 - 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 AT Protocol network via [DNS authority resolution](#network-lexicons). 5 + 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). 6 6 7 7 ## Supported lexicon types 8 8
+1 -1
packages/docs/docs/guides/plugins.md
··· 1 1 # Plugins 2 2 3 - HappyView uses WASM plugins to extend its functionality. Plugins can integrate with external platforms, sync data to users' AT Protocol identities, and more. Auth plugins — the first supported plugin type — enable users to link accounts from platforms like Steam, Xbox, itch.io, and others, then sync data like game libraries. 3 + HappyView uses WASM plugins to extend its functionality. Plugins can integrate with external platforms, sync data to users' atproto identities, and more. Auth plugins — the first supported plugin type — enable users to link accounts from platforms like Steam, Xbox, itch.io, and others, then sync data like game libraries. 4 4 5 5 Official plugins for Steam, Xbox, itch.io, and other platforms are available in the [happyview-plugins](https://github.com/gamesgamesgamesgamesgames/happyview-plugins) repository. 6 6
+5 -5
packages/docs/docs/guides/scripting.md
··· 68 68 | ---------------- | ------- | ------------------------------------------------------------------- | 69 69 | `now()` | string | Current UTC timestamp in ISO 8601 format | 70 70 | `log(message)` | — | Log a message (appears in server logs at debug level) | 71 - | `TID()` | string | Generate a fresh AT Protocol TID (13-character sortable identifier) | 71 + | `TID()` | string | Generate a fresh atproto TID (13-character sortable identifier) | 72 72 | `toarray(table)` | table | Mark a table as a JSON array for serialization (see [below](#toarray)) | 73 73 74 74 ### toarray ··· 85 85 86 86 ## Record API 87 87 88 - The `Record` API is only available in **procedure** scripts. It handles creating, updating, loading, and deleting AT Protocol records. Writes are proxied to the caller's PDS and indexed locally. 88 + The `Record` API is only available in **procedure** scripts. It handles creating, updating, loading, and deleting atproto records. Writes are proxied to the caller's PDS and indexed locally. 89 89 90 90 See the full [Record API reference](../reference/lua/record-api.md) for constructor, static methods, instance methods, fields, schema validation, and save behavior. 91 91 ··· 127 127 local data = json.decode(resp.body) 128 128 ``` 129 129 130 - ## AT Protocol API 130 + ## atproto API 131 131 132 - The `atproto` table provides AT Protocol utility functions like DID resolution and label queries. 132 + The `atproto` table provides atproto utility functions like DID resolution and label queries. 133 133 134 - See the full [AT Protocol API reference](../reference/lua/atproto-api.md) for `atproto.resolve_service_endpoint`, `atproto.get_labels`, and `atproto.get_labels_batch`. 134 + See the full [atproto API reference](../reference/lua/atproto-api.md) for `atproto.resolve_service_endpoint`, `atproto.get_labels`, and `atproto.get_labels_batch`. 135 135 136 136 ## JSON API 137 137
+1 -1
packages/docs/docs/guides/sqlite-to-postgres-migration.md
··· 50 50 51 51 ## Step 5: Re-index your data 52 52 53 - Since HappyView indexes records from the AT Protocol network, the simplest way to populate your new Postgres database is to re-run the backfill: 53 + Since HappyView indexes records from the atproto network, the simplest way to populate your new Postgres database is to re-run the backfill: 54 54 55 55 1. Upload your lexicons via the dashboard or admin API (or they will already be there if you exported and re-imported them) 56 56 2. Run a backfill for each collection (dashboard or `POST /admin/backfill`)
+1 -1
packages/docs/docs/reference/admin-api.md
··· 7 7 The admin API supports two authentication methods: 8 8 9 9 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. 10 - 2. **Service auth JWT** — AT Protocol inter-service authentication via signed JWTs. 10 + 2. **Service auth JWT** — atproto inter-service authentication via signed JWTs. 11 11 12 12 In all cases the resolved DID is checked against the `users` table, and the user's permissions are loaded to authorize the request. 13 13
+1 -1
packages/docs/docs/reference/admin/domains.md
··· 1 1 # Admin API: Domains 2 2 3 - Manage the domains a HappyView instance serves. Each domain gets its own AT Protocol OAuth client identity. The primary domain is set from `PUBLIC_URL` on first boot. All endpoints require the `settings:manage` permission. 3 + Manage the domains a HappyView instance serves. Each domain gets its own atproto OAuth client identity. The primary domain is set from `PUBLIC_URL` on first boot. All endpoints require the `settings:manage` permission. 4 4 5 5 ```sh 6 6 # All examples assume $TOKEN is an API key (hv_...)
+1 -1
packages/docs/docs/reference/admin/labelers.md
··· 24 24 25 25 | Field | Type | Required | Description | 26 26 | ----- | ------ | -------- | ----------------------------- | 27 - | `did` | string | yes | The labeler's AT Protocol DID | 27 + | `did` | string | yes | The labeler's atproto DID | 28 28 29 29 **Response**: `201 Created` (empty body) 30 30
+1 -1
packages/docs/docs/reference/admin/lexicons.md
··· 92 92 93 93 ## Network Lexicons 94 94 95 - Network lexicons are fetched from the AT Protocol network via DNS TXT resolution and kept updated via the Jetstream subscription. See [Lexicons - Network lexicons](../../guides/lexicons.md#network-lexicons) for background. 95 + 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. 96 96 97 97 ### Add a network lexicon 98 98
+1 -1
packages/docs/docs/reference/admin/users.md
··· 27 27 28 28 | Field | Type | Required | Description | 29 29 | ------------- | -------- | -------- | ---------------------------------------------------------------------------------- | 30 - | `did` | string | yes | The AT Protocol DID of the user to add | 30 + | `did` | string | yes | The atproto DID of the user to add | 31 31 | `template` | string | no | Permission template: `viewer`, `operator`, `manager`, or `full_access` | 32 32 | `permissions` | string[] | no | Explicit list of permissions to grant (used instead of or in addition to `template`) | 33 33
+2 -2
packages/docs/docs/reference/architecture.md
··· 195 195 | Column | Type | Description | 196 196 | -------------- | ------------- | ------------------------------------------------ | 197 197 | `id` | uuid (PK) | | 198 - | `did` | text (unique) | User's AT Protocol DID | 198 + | `did` | text (unique) | User's atproto DID | 199 199 | `is_super` | boolean | Whether this is the super user (only one allowed)| 200 200 | `created_at` | timestamptz | | 201 201 | `last_used_at` | timestamptz | Updated on each authenticated request | ··· 226 226 227 227 | Column | Type | Description | 228 228 | -------------- | ----------- | -------------------------------------------- | 229 - | `did` | text (PK) | User's AT Protocol DID | 229 + | `did` | text (PK) | User's atproto DID | 230 230 | `session_data` | text | Serialized OAuth session (managed by atrium) | 231 231 | `created_at` | timestamptz | | 232 232 | `updated_at` | timestamptz | |
+9 -9
packages/docs/docs/reference/glossary.md
··· 1 1 # Glossary 2 2 3 - Key terms used throughout the HappyView documentation. For a broader introduction to the AT Protocol, see the [official ATProto glossary](https://atproto.com/guides/glossary). 3 + Key terms used throughout the HappyView documentation. For a broader introduction to the atproto, see the [official ATProto glossary](https://atproto.com/guides/glossary). 4 4 5 - ## AT Protocol terms 5 + ## atproto terms 6 6 7 - **AppView** — A backend service that indexes AT Protocol records and serves them through an API. HappyView is an AppView. See the [ATProto docs](https://atproto.com/guides/glossary#app-view) for more. 7 + **AppView** — A backend service that indexes atproto records and serves them through an API. HappyView is an AppView. See the [ATProto docs](https://atproto.com/guides/glossary#app-view) for more. 8 8 9 9 **DID** (Decentralized Identifier) — A persistent, globally unique identifier for an account (e.g. `did:plc:abc123`). 10 10 11 - **Firehose** — A real-time stream of all record events (creates, updates, deletes) across the AT Protocol network. HappyView consumes a filtered slice of this via [Jetstream](https://github.com/bluesky-social/jetstream). 11 + **Firehose** — A real-time stream of all record events (creates, updates, deletes) across the atproto network. HappyView consumes a filtered slice of this via [Jetstream](https://github.com/bluesky-social/jetstream). 12 12 13 13 **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. 14 14 15 - **Lexicon** — A schema definition for AT Protocol data types and API methods. Lexicons define what records look like, what endpoints exist, and what parameters they accept. See [Lexicons](../guides/lexicons.md). 15 + **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). 16 16 17 17 **NSID** (Namespaced Identifier) — A reverse-DNS identifier for a lexicon (e.g. `xyz.statusphere.status`). The authority is everything except the last segment. 18 18 ··· 20 20 21 21 **PLC directory** — A public service (e.g. `plc.directory`) that maps DIDs to their DID documents, which contain the user's PDS endpoint and other metadata. 22 22 23 - **Record** — A single piece of data in an AT Protocol repository, identified by an AT URI (e.g. `at://did:plc:abc/xyz.statusphere.status/abc123`). 23 + **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`). 24 24 25 25 **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. 26 26 ··· 28 28 29 29 **TID** (Timestamp Identifier) — A 13-character sortable identifier used as a record key. Generated from the current timestamp. 30 30 31 - **XRPC** — The HTTP-based RPC protocol used by the AT Protocol. Query methods map to GET requests, procedure methods map to POST requests. See [XRPC API](xrpc-api.md). 31 + **XRPC** — The HTTP-based RPC protocol used by the atproto. Query methods map to GET requests, procedure methods map to POST requests. See [XRPC API](xrpc-api.md). 32 32 33 - **Jetstream** — A [filtered firehose](https://github.com/bluesky-social/jetstream) that delivers atproto record commit events as JSON over WebSocket. Not part of the core AT Protocol spec, but widely used. HappyView subscribes to Jetstream with a collection filter built from its indexed record lexicons, and persists a cursor for resume on reconnect. 33 + **Jetstream** — A [filtered firehose](https://github.com/bluesky-social/jetstream) that delivers atproto record commit events as JSON over WebSocket. Not part of the core atproto spec, but widely used. HappyView subscribes to Jetstream with a collection filter built from its indexed record lexicons, and persists a cursor for resume on reconnect. 34 34 35 35 ## HappyView-specific terms 36 36 37 37 **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). 38 38 39 - **Network lexicon** — A lexicon fetched directly from the AT Protocol network via DNS authority resolution, rather than uploaded manually. See [Lexicons - Network lexicons](../guides/lexicons.md#network-lexicons). 39 + **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). 40 40 41 41 **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). 42 42
+3 -3
packages/docs/docs/reference/lua/atproto-api.md
··· 1 - # AT Protocol API 1 + # atproto API 2 2 3 - The `atproto` table provides AT Protocol utility functions. Available in queries, procedures, and [index hooks](../../guides/index-hooks.md). 3 + The `atproto` table provides atproto utility functions. Available in queries, procedures, and [index hooks](../../guides/index-hooks.md). 4 4 5 5 ## atproto.resolve_service_endpoint 6 6 ··· 8 8 local endpoint = atproto.resolve_service_endpoint(did) 9 9 ``` 10 10 11 - Resolves a DID to its AT Protocol service endpoint URL by fetching the DID document. Supports both `did:plc:*` (via the PLC directory) and `did:web:*` (via `.well-known/did.json`). 11 + Resolves a DID to its atproto service endpoint URL by fetching the DID document. Supports both `did:plc:*` (via the PLC directory) and `did:web:*` (via `.well-known/did.json`). 12 12 13 13 | Parameter | Type | Description | 14 14 | --------- | ------ | ------------------------ |
+1 -1
packages/docs/docs/reference/lua/record-api.md
··· 1 1 # Record API 2 2 3 - The `Record` API is only available in **procedure** scripts. It handles creating, updating, loading, and deleting AT Protocol records. Writes are proxied to the caller's PDS and indexed locally. 3 + The `Record` API is only available in **procedure** scripts. It handles creating, updating, loading, and deleting atproto records. Writes are proxied to the caller's PDS and indexed locally. 4 4 5 5 ## Constructor 6 6
+1 -1
packages/docs/docs/reference/scripts/cascading-delete.md
··· 72 72 73 73 Cascading deletes are useful when your data model has parent-child relationships across collections. For example, deleting a post should also clean up its comments, reactions, or metadata records. This keeps the user's repo and the local index consistent. 74 74 75 - Note that this only deletes records owned by `caller_did`. AT Protocol records can only be deleted by their owner. If the related records could have more than 100 matches, paginate through all of them before deleting. 75 + Note that this only deletes records owned by `caller_did`. atproto records can only be deleted by their owner. If the related records could have more than 100 matches, paginate through all of them before deleting.
+1 -1
packages/docs/docs/reference/scripts/sidecar-records.md
··· 72 72 ^^^^^^^ same rkey 73 73 ``` 74 74 75 - This is a common AT Protocol pattern for keeping a primary record lean while storing auxiliary data (metadata, reactions, settings) in a companion collection. 75 + This is a common atproto pattern for keeping a primary record lean while storing auxiliary data (metadata, reactions, settings) in a companion collection.
+1 -1
packages/docs/docs/reference/troubleshooting.md
··· 108 108 109 109 ## OAuth or login issues 110 110 111 - HappyView handles AT Protocol OAuth internally via the `atrium-oauth` library. If users can't log in: 111 + HappyView handles atproto OAuth internally via the `atrium-oauth` library. If users can't log in: 112 112 113 113 1. Verify `PUBLIC_URL` is set correctly and the URL is publicly accessible (required for OAuth callbacks). 114 114 2. Check that the user's PDS authorization server is reachable.
+1 -1
packages/docs/docs/reference/xrpc-api.md
··· 1 1 # XRPC API 2 2 3 - [XRPC](https://atproto.com/specs/xrpc) is the HTTP-based RPC protocol used by the AT Protocol. 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. 3 + [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. 4 4 5 5 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). 6 6
+1 -1
packages/docs/docs/sdk/lex-agent.md
··· 1 1 # Lex Agent 2 2 3 - The Lex agent adapter is the recommended way to interact with HappyView from JavaScript. It creates an [`@atproto/lex`](https://www.npmjs.com/package/@atproto/lex) `Agent` from a `HappyViewSession`, so you can use `@atproto/lex`'s type-safe `Client` to make XRPC calls with HappyView's DPoP authentication. All requests are routed to your HappyView instance, which handles its own lexicons locally and proxies standard AT Protocol methods (e.g., `com.atproto.repo.createRecord`) to the user's PDS. 3 + The Lex agent adapter is the recommended way to interact with HappyView from JavaScript. It creates an [`@atproto/lex`](https://www.npmjs.com/package/@atproto/lex) `Agent` from a `HappyViewSession`, so you can use `@atproto/lex`'s type-safe `Client` to make XRPC calls with HappyView's DPoP authentication. All requests are routed to your HappyView instance, which handles its own lexicons locally and proxies standard atproto methods (e.g., `com.atproto.repo.createRecord`) to the user's PDS. 4 4 5 5 The adapter gives you lexicon-level type checking on parameters, input bodies, and responses, and works with any library or tool that accepts an `@atproto/lex` `Agent`. 6 6
+1 -1
packages/docs/docs/sdk/oauth-client-browser.md
··· 1 1 # Browser Client 2 2 3 - The browser client handles the full OAuth redirect flow for browser apps authenticating with a HappyView instance. It wraps the [OAuth Client](./oauth-client.md) with Web Crypto, localStorage, and AT Protocol handle/DID resolution. 3 + The browser client handles the full OAuth redirect flow for browser apps authenticating with a HappyView instance. It wraps the [OAuth Client](./oauth-client.md) with Web Crypto, localStorage, and atproto handle/DID resolution. 4 4 5 5 If you're starting a new app, consider using [`@happyview/lex-agent`](./lex-agent.md) with `@atproto/lex` instead — it provides type-safe XRPC calls and is the recommended way to interact with HappyView. This package is primarily useful if your app already uses `@atproto/oauth-client-browser` and you want to add HappyView authentication alongside it. 6 6
+1 -1
packages/docs/docs/sdk/oauth-client.md
··· 37 37 38 38 For public clients, `pkceVerifier` is included and must be passed back when registering the session. For confidential clients it will be `undefined`. 39 39 40 - Use the returned `dpopKey` (a private JWK) as your DPoP keypair during your AT Protocol OAuth flow with the user's PDS. 40 + Use the returned `dpopKey` (a private JWK) as your DPoP keypair during your atproto OAuth flow with the user's PDS. 41 41 42 42 ## Session registration 43 43
+3 -3
packages/docs/docs/sdk/overview.md
··· 12 12 13 13 **Starting a new app?** Use `@happyview/lex-agent` with `@atproto/lex`. It gives you type-safe XRPC calls through a `Client` that routes requests to your HappyView instance with DPoP authentication. This is the recommended way to interact with HappyView from JavaScript. 14 14 15 - **Already using `@atproto/oauth-client-browser`?** Add `@happyview/oauth-client-browser` to get a `HappyViewBrowserClient` that handles the HappyView-specific DPoP key provisioning and session registration on top of the standard AT Protocol OAuth flow. 15 + **Already using `@atproto/oauth-client-browser`?** Add `@happyview/oauth-client-browser` to get a `HappyViewBrowserClient` that handles the HappyView-specific DPoP key provisioning and session registration on top of the standard atproto OAuth flow. 16 16 17 17 **Building a server-side app or something more custom?** Use `@happyview/oauth-client` directly and provide your own `CryptoAdapter` and `StorageAdapter`. 18 18 ··· 21 21 Third-party apps authenticate using HappyView's [DPoP key provisioning](../getting-started/authentication.md#dpop-key-provisioning-for-third-party-apps) flow: 22 22 23 23 1. The SDK requests a DPoP keypair from the HappyView instance. 24 - 2. Your app runs a standard AT Protocol OAuth flow with the user's PDS using that keypair. 24 + 2. Your app runs a standard atproto OAuth flow with the user's PDS using that keypair. 25 25 3. The SDK registers the resulting tokens with HappyView. 26 - 4. All subsequent XRPC requests are authenticated with DPoP proofs — HappyView handles its own lexicons locally and proxies standard AT Protocol writes to the user's PDS. 26 + 4. All subsequent XRPC requests are authenticated with DPoP proofs — HappyView handles its own lexicons locally and proxies standard atproto writes to the user's PDS. 27 27 28 28 ## Quick start 29 29
+52 -138
packages/docs/docs/tutorials/statusphere.md
··· 1 1 # Tutorial: Statusphere with HappyView 2 2 3 - [Statusphere](https://github.com/bluesky-social/statusphere-example-app) is an example AT Protocol application where users set their current status as a single emoji. It's a great way to learn how HappyView works because the data model is simple but the queries are interesting. 3 + [Statusphere](https://github.com/bluesky-social/statusphere-example-app) is an example atproto application where users set their current status as a single emoji. It's a great way to learn how HappyView works because the data model is simple but the queries are interesting. 4 4 5 5 In this tutorial, you'll set up HappyView to act as the AppView for Statusphere. By the end, you'll have indexed records and working XRPC endpoints. 6 6 ··· 19 19 20 20 For more background on how the app works, see the [ATProto Statusphere guide](https://atproto.com/guides/applications). 21 21 22 - ## Step 1: Upload the record lexicon 22 + ## Step 1: Add the record lexicon 23 23 24 - First, upload the `xyz.statusphere.status` lexicon to HappyView. This tells HappyView to start indexing Statusphere records from across the network as they're created, updated, or deleted. 24 + 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: 25 25 26 - The examples below use `$TOKEN` as a placeholder for an API key. See [Authentication](../getting-started/authentication.md) and the [API Keys guide](../guides/api-keys.md) for how to get one. 26 + 1. Go to **Lexicons > Add Lexicon > Network** 27 + 2. Enter `xyz.statusphere.status` 28 + 3. HappyView resolves the schema from its authority domain records and shows a preview 29 + 4. Enable the **Backfill** toggle so HappyView fetches existing records from the network 30 + 5. Click **Add** 31 + 32 + HappyView now subscribes to `xyz.statusphere.status` via Jetstream and kicks off a backfill job to index historical records. 33 + 34 + :::tip 35 + You can also add lexicons via the [admin API](../reference/admin/lexicons.md). This is useful for automation or CI/CD workflows: 27 36 28 37 ```sh 29 38 curl -X POST http://localhost:3000/admin/lexicons \ ··· 52 61 }' 53 62 ``` 54 63 55 - HappyView now subscribes to `xyz.statusphere.status` via Jetstream. The `backfill` flag tells HappyView to also index existing status records from the network. You can monitor progress with `GET /admin/backfill/status` or the [dashboard](../getting-started/dashboard.md). 56 - 57 - :::tip 58 - Since the `xyz.statusphere.status` lexicon is [published on the AT Protocol network](../guides/lexicons.md#network-lexicons), you can also add it as a network lexicon instead of uploading the JSON manually: 59 - 60 - ```sh 61 - curl -X POST http://localhost:3000/admin/network-lexicons \ 62 - -H "Authorization: Bearer $TOKEN" \ 63 - -H "Content-Type: application/json" \ 64 - -d '{ "nsid": "xyz.statusphere.status" }' 65 - ``` 66 - 67 64 ::: 68 65 69 66 ## Step 2: Verify records are being indexed 70 67 71 - Once the backfill starts processing, you should see records appearing. Check the stats: 72 - 73 - ```sh 74 - curl http://localhost:3000/admin/stats \ 75 - -H "Authorization: Bearer $TOKEN" 76 - ``` 68 + Once the backfill starts, you should see records appearing in the dashboard: 77 69 78 - ```json 79 - { 80 - "total_records": 1234, 81 - "collections": [{ "collection": "xyz.statusphere.status", "count": 1234 }] 82 - } 83 - ``` 70 + 1. The **home page** shows a live record count and per-collection breakdown 71 + 2. Go to **Records** to browse individual indexed statuses 72 + 3. Go to **Backfill** to watch the backfill job progress — you'll see the number of repos processed and records fetched 84 73 85 74 ## Step 3: Add a query lexicon for listing statuses 86 75 87 - Now add a query endpoint to read the indexed data. Upload a query lexicon with `target_collection` pointing at the record collection from Step 1: 76 + Now add a query endpoint to read the indexed data: 88 77 89 - ```sh 90 - curl -X POST http://localhost:3000/admin/lexicons \ 91 - -H "Authorization: Bearer $TOKEN" \ 92 - -H "Content-Type: application/json" \ 93 - -d '{ 94 - "lexicon_json": { 95 - "lexicon": 1, 96 - "id": "xyz.statusphere.listStatuses", 97 - "defs": { 98 - "main": { 99 - "type": "query", 100 - "output": { "encoding": "application/json" } 101 - } 102 - } 103 - }, 104 - "target_collection": "xyz.statusphere.status" 105 - }' 106 - ``` 78 + 1. Go to **Lexicons > Add Lexicon > Local** 79 + 2. Set the NSID to `xyz.statusphere.listStatuses` 80 + 3. Set the type to **Query** 81 + 4. Set `target_collection` to `xyz.statusphere.status` — this tells the query which record collection it operates on (`target_collection` is a HappyView-specific field, not part of the lexicon spec) 82 + 5. Click **Add** 107 83 108 84 This creates a `GET /xrpc/xyz.statusphere.listStatuses` endpoint. Without a Lua script, it uses HappyView's built-in default behavior: listing records with `limit`, `cursor`, and `did` parameters, or fetching a single record by `uri`. Try it: 109 85 110 86 ```sh 111 - curl "http://localhost:3000/xrpc/xyz.statusphere.listStatuses?limit=5" 87 + curl "http://localhost:3000/xrpc/xyz.statusphere.listStatuses?limit=5" \ 88 + -H "X-Client-Key: $CLIENT_KEY" 112 89 ``` 113 90 114 91 ```json ··· 133 110 134 111 ## Step 4: Enhance the query with a Lua script 135 112 136 - The default query behavior works, but let's customize it with a [Lua script](../guides/scripting.md). Here's a script that handles single-record lookups by URI and paginated listing with an optional DID filter: 113 + The default query behavior works, but let's customize it with a [Lua script](../guides/scripting.md). The script will handle single-record lookups by URI and paginated listing with an optional DID filter. 114 + 115 + 1. Click on **xyz.statusphere.listStatuses** in the lexicon list to open its detail page 116 + 2. The Lua script editor is at the bottom of the page 117 + 3. Paste in the following script: 137 118 138 119 ```lua 139 120 function handle() ··· 154 135 end 155 136 ``` 156 137 157 - Re-upload the lexicon with parameters defined in the schema and the script attached: 158 - 159 - ```sh 160 - LEXICON='{ 161 - "lexicon": 1, 162 - "id": "xyz.statusphere.listStatuses", 163 - "defs": { 164 - "main": { 165 - "type": "query", 166 - "parameters": { 167 - "type": "params", 168 - "properties": { 169 - "uri": { "type": "string" }, 170 - "did": { "type": "string" }, 171 - "limit": { "type": "integer" }, 172 - "cursor": { "type": "string" } 173 - } 174 - }, 175 - "output": { "encoding": "application/json" } 176 - } 177 - } 178 - }' 179 - 180 - SCRIPT='function handle() 181 - if params.uri then 182 - local record = db.get(params.uri) 183 - if not record then 184 - return { error = "not found" } 185 - end 186 - return { record = record } 187 - end 188 - 189 - return db.query({ 190 - collection = collection, 191 - did = params.did, 192 - limit = tonumber(params.limit) or 20, 193 - cursor = params.cursor, 194 - }) 195 - end' 196 - 197 - curl -X POST http://localhost:3000/admin/lexicons \ 198 - -H "Authorization: Bearer $TOKEN" \ 199 - -H "Content-Type: application/json" \ 200 - -d "{ 201 - \"lexicon_json\": $LEXICON, 202 - \"target_collection\": \"xyz.statusphere.status\", 203 - \"script\": \"$SCRIPT\" 204 - }" 205 - ``` 138 + 4. Click **Save** 206 139 207 140 The endpoint now uses your custom logic. Filter by a specific user: 208 141 209 142 ```sh 210 - curl "http://localhost:3000/xrpc/xyz.statusphere.listStatuses?did=did:plc:abc&limit=1" 143 + curl "http://localhost:3000/xrpc/xyz.statusphere.listStatuses?did=did:plc:abc&limit=1" \ 144 + -H "X-Client-Key: $CLIENT_KEY" 211 145 ``` 212 146 213 147 Fetch a single record by URI: 214 148 215 149 ```sh 216 - curl "http://localhost:3000/xrpc/xyz.statusphere.listStatuses?uri=at://did:plc:abc/xyz.statusphere.status/3abc123" 150 + curl "http://localhost:3000/xrpc/xyz.statusphere.listStatuses?uri=at://did:plc:abc/xyz.statusphere.status/3abc123" \ 151 + -H "X-Client-Key: $CLIENT_KEY" 217 152 ``` 218 153 219 154 ## Step 5: Add a procedure lexicon for setting status 220 155 221 - Add a write endpoint so users can set their status through your AppView. This creates a `POST /xrpc/xyz.statusphere.setStatus` endpoint that proxies writes to the user's PDS. 156 + Add a write endpoint so users can set their status through your AppView: 222 157 223 - The Lua script auto-fills `createdAt` and uses the authenticated user's DID: 158 + 1. Go to **Lexicons > Add Lexicon > Local** 159 + 2. Set the NSID to `xyz.statusphere.setStatus` 160 + 3. Set the type to **Procedure** 161 + 4. Set `target_collection` to `xyz.statusphere.status` 162 + 5. A default Lua script is generated — replace it with: 224 163 225 164 ```lua 226 165 function handle() ··· 233 172 end 234 173 ``` 235 174 236 - Upload the procedure lexicon with this script: 237 - 238 - ```sh 239 - LEXICON='{ 240 - "lexicon": 1, 241 - "id": "xyz.statusphere.setStatus", 242 - "defs": { 243 - "main": { 244 - "type": "procedure", 245 - "input": { "encoding": "application/json" }, 246 - "output": { "encoding": "application/json" } 247 - } 248 - } 249 - }' 175 + 6. Click **Add** 250 176 251 - SCRIPT='function handle() 252 - local r = Record(collection, { 253 - status = input.status, 254 - createdAt = now(), 255 - }) 256 - r:save() 257 - return { uri = r._uri, cid = r._cid } 258 - end' 259 - 260 - curl -X POST http://localhost:3000/admin/lexicons \ 261 - -H "Authorization: Bearer $TOKEN" \ 262 - -H "Content-Type: application/json" \ 263 - -d "{ 264 - \"lexicon_json\": $LEXICON, 265 - \"target_collection\": \"xyz.statusphere.status\", 266 - \"script\": \"$SCRIPT\" 267 - }" 268 - ``` 177 + This creates a `POST /xrpc/xyz.statusphere.setStatus` endpoint that creates records on the user's PDS and indexes them locally. 269 178 270 179 ## Step 6: Test the procedure endpoint 271 180 272 - Set a status (requires authentication): 181 + Set a status. This requires DPoP authentication — the [JavaScript SDK](../sdk/overview.md) handles this for you, but you can test with curl if you have a token: 273 182 274 183 ```sh 275 184 curl -X POST http://localhost:3000/xrpc/xyz.statusphere.setStatus \ 276 - -H "Authorization: Bearer $TOKEN" \ 185 + -H "X-Client-Key: $CLIENT_KEY" \ 186 + -H "Authorization: DPoP $TOKEN" \ 187 + -H "DPoP: $DPOP_PROOF" \ 277 188 -H "Content-Type: application/json" \ 278 189 -d '{ "status": "\ud83d\ude80" }' 279 190 ``` ··· 289 200 290 201 ## What you've built 291 202 292 - With three lexicon uploads and a few lines of Lua, you have a complete Statusphere AppView: 203 + With three lexicons and a few lines of Lua, you have a complete Statusphere AppView: 293 204 294 - - **Real-time indexing** of `xyz.statusphere.status` records from the entire AT Protocol network 205 + - **Real-time indexing** of `xyz.statusphere.status` records from the entire atproto network 295 206 - **Historical backfill** of existing status records 296 207 - **A query endpoint** (`xyz.statusphere.listStatuses`) with filtering, pagination, and single-record lookups 297 208 - **A write endpoint** (`xyz.statusphere.setStatus`) that creates records on the user's PDS and indexes them locally 298 209 210 + 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). 211 + 299 212 ## Next steps 300 213 301 214 - [Lua Scripting](../guides/scripting.md): Explore the full Record and database APIs to build more complex queries 302 215 - [Lexicons](../guides/lexicons.md): Learn about network lexicons, the backfill flag, and target collections 303 216 - [XRPC API](../reference/xrpc-api.md): Understand how the generated endpoints behave 217 + - [Admin API](../reference/admin-api.md): Automate lexicon management via the API 304 218 - [Statusphere example app](https://github.com/bluesky-social/statusphere-example-app): See the full Statusphere frontend 305 219 - [ATProto Statusphere guide](https://atproto.com/guides/applications): Deep dive into how the app works at the protocol level
+1 -1
packages/docs/sidebars.ts
··· 370 370 { 371 371 type: "doc", 372 372 id: "reference/lua/atproto-api", 373 - label: "AT Protocol API", 373 + label: "atproto API", 374 374 }, 375 375 { 376 376 type: "doc",