Monorepo for wisp.place. A static site hosting service built on top of the AT Protocol. wisp.place
1The project is wisp.place. It is a static site hoster built on top of the AT Protocol. The overall basis of the project is that users upload site assets to their PDS as blobs, and creates a manifest record listing every blob as well as site name. The hosting service then catches events relating to the site (create, read, upload, delete) and handles them appropriately. 2 3The lexicons look like this: 4```typescript 5//place.wisp.fs 6interface Main { 7 $type: 'place.wisp.fs' 8 site: string 9 root: Directory 10 fileCount?: number 11 createdAt: string 12} 13 14interface File { 15 $type?: 'place.wisp.fs#file' 16 type: 'file' 17 blob: BlobRef 18 encoding?: 'gzip' 19 mimeType?: string 20 base64?: boolean 21} 22 23interface Directory { 24 $type?: 'place.wisp.fs#directory' 25 type: 'directory' 26 entries: Entry[] 27} 28 29interface Entry { 30 $type?: 'place.wisp.fs#entry' 31 name: string 32 node: $Typed<File> | $Typed<Directory> | $Typed<Subfs> | { $type: string } 33} 34 35interface Subfs { 36 $type?: 'place.wisp.fs#subfs' 37 type: 'subfs' 38 subject: string // AT-URI pointing to a place.wisp.subfs record 39 flat?: boolean 40} 41 42//place.wisp.subfs 43interface Main { 44 $type: 'place.wisp.subfs' 45 root: Directory 46 fileCount?: number 47 createdAt: string 48} 49 50interface File { 51 $type?: 'place.wisp.subfs#file' 52 type: 'file' 53 blob: BlobRef 54 encoding?: 'gzip' 55 mimeType?: string 56 base64?: boolean 57} 58 59interface Directory { 60 $type?: 'place.wisp.subfs#directory' 61 type: 'directory' 62 entries: Entry[] 63} 64 65interface Entry { 66 $type?: 'place.wisp.subfs#entry' 67 name: string 68 node: $Typed<File> | $Typed<Directory> | $Typed<Subfs> | { $type: string } 69} 70 71interface Subfs { 72 $type?: 'place.wisp.subfs#subfs' 73 type: 'subfs' 74 subject: string // AT-URI pointing to another place.wisp.subfs record 75} 76 77//place.wisp.settings 78interface Main { 79 $type: 'place.wisp.settings' 80 directoryListing: boolean 81 spaMode?: string 82 custom404?: string 83 indexFiles?: string[] 84 cleanUrls: boolean 85 headers?: CustomHeader[] 86} 87 88interface CustomHeader { 89 $type?: 'place.wisp.settings#customHeader' 90 name: string 91 value: string 92 path?: string // Optional glob pattern 93} 94``` 95 96The main differences between place.wisp.fs and place.wisp.subfs: 97 - place.wisp.fs has a required site field 98 - place.wisp.fs#subfs has an optional flat field that place.wisp.subfs#subfs doesn't have 99 100The project is a monorepo. The package handler it uses for the typescript side is Bun. For the Rust cli, it is cargo. 101 102### Typescript Bun Workspace Layout 103 104Bun workspaces: `packages/@wisp/*`, `apps/main-app`, `apps/hosting-service` 105 106There are two typescript apps 107**`apps/main-app`** - Main backend (Bun + Elysia) 108 109- OAuth authentication and session management 110- Site CRUD operations via PDS 111- Custom domain management 112- Admin database view in /admin 113- React frontend in public/ 114 115**`apps/hosting-service`** - CDN static file server (Node + Hono) 116 117- Watches AT Protocol firehose for `place.wisp.fs` record changes 118- Downloads and caches site files to disk 119- Serves sites at `https://sites.wisp.place/{did}/{site-name}` and custom domains 120- Handles redirects (`_redirects` file support) and routing logic 121- Backfill mode for syncing existing sites 122 123### Shared Packages (`packages/@wisp/*`) 124 125- **`lexicons`** - AT Protocol lexicons (`place.wisp.fs`, `place.wisp.subfs`, `place.wisp.settings`) with 126 generated TypeScript types 127- **`fs-utils`** - Filesystem tree building, manifest creation, subfs splitting logic 128- **`atproto-utils`** - AT Protocol helpers (blob upload, record operations, CID handling) 129- **`database`** - PostgreSQL schema and queries 130- **`constants`** - Shared constants (limits, file patterns, default settings) 131- **`observability`** - OpenTelemetry instrumentation 132- **`safe-fetch`** - Wrapped fetch with timeout/retry logic 133 134### CLI 135 136**`cli/`** - Rust CLI using Jacquard (AT Protocol library) 137- Direct PDS uploads without interacting with main-app 138- Can also do the same firehose watching, caching, and serving hosting-service does, just without domain management 139 140### Other Directories 141 142- **`docs/`** - Astro documentation site 143- **`binaries/`** - Compiled CLI binaries for distribution