an attempt to make a lightweight, easily self-hostable, scoped bluesky appview
TypeScript 99.8%
HTML 0.1%
Other 0.1%
17 1 0

Clone this repository

https://tangled.org/whey.party/skylite
git@tangled.org:whey.party/skylite

For self-hosted knots, clone URLs may differ based on your setup.

readme.md

skylite (pre alpha)#

an attempt to make a lightweight, easily self-hostable, scoped Bluesky appview

this project uses:

Status#

(as of 26 aug 2025) currently the state of the project is:

Index Server#

  • Database:
    • Works, though it still needs some more tuning and iteration
  • Registration:
    • not there yet. currently manually adding users
    • onboarding backfill is probably next maybe
  • Indexing:
    • Jetstream:
      • its there, i just need to actually handle each and every record type and insert it to the db (like currently 2 out of 12 or so record collections are being inserted into the db)
    • Spacedust:
      • its a backlink index so i only needed one table, and so it is complete
  • Server:
    • Initial implementation is done
    • uses per-user instantiation thing so it can add or remove users as needed
    • pagination is not a thing yet :(
    • does not implement the Ref / Partial routes yet (currently strips undefineds) (fixing this soon)
    • also implements the entirety of the Constellation API routes as a bonus (under /links/)
  • Lexicon:
    • unsure about PostViewRef's optional fields
    • theres 3 remaining profile-related routes thats still not defined yet
    • some routes need more tweaks
    • considering adding optional query params to request either skeleton only, partials, or full hydrated (might not be respected by the server though lol)
    • considering making all of the api routes custom instead of the current situation of having some of the Index server routes be the original unmodified bsky.app routes

View Server#

  • pratically unimplemented
  • currently mostly just proxies api.bsky.app
  • i havent split the DB between the Index server and View server yet
  • hydration (resolving Refs, handling partials) will be implemented soon i think
  • it should (but not yet) have a ranking system to decide which index server to be prioritized if multiple index servers indexes the same user account. (and also should support both api sets (Bluesky AppView API (legacy/fallback) and Bluesky Index Server API ))

Running#

this project is pre-alpha and not intended for general use yet. you are welcome to experiment if you dont mind errors or breaking changes.

the project is split into two, the "Index Server" and the "View Server". despite both living in this repo, they run different http servers with different configs

example configuration is in the config.jsonc.example file

Index Server#

start it by running

deno task index

it should just work actually implemented xrpc routes for #skylite_index are:

const indexServerRoutes = new Set([
  "/xrpc/app.bsky.actor.getProfile",
  "/xrpc/app.bsky.actor.getProfiles",
  "/xrpc/app.bsky.feed.getActorFeeds",
  "/xrpc/app.bsky.feed.getFeedGenerator",
  "/xrpc/app.bsky.feed.getFeedGenerators",
  "/xrpc/app.bsky.feed.getPosts",
  "/xrpc/party.whey.app.bsky.feed.getActorLikesPartial",
  "/xrpc/party.whey.app.bsky.feed.getAuthorFeedPartial",
  "/xrpc/party.whey.app.bsky.feed.getLikesPartial",
  "/xrpc/party.whey.app.bsky.feed.getPostThreadPartial",
  "/xrpc/party.whey.app.bsky.feed.getQuotesPartial",
  "/xrpc/party.whey.app.bsky.feed.getRepostedByPartial",
  // i havent implemented these three yet
  /*
    app.bsky.graph.getLists // doesnt need to because theres no items[], and its self ProfileViewBasic
    app.bsky.graph.getList // needs to be Partial-ed (items[] union with ProfileViewRef)
    app.bsky.graph.getActorStarterPacks // maybe doesnt need to be Partial-ed because its self ProfileViewBasic
  */

  // and the last one is a stub because its pretty hard to do
  "/xrpc/party.whey.app.bsky.feed.getListFeedPartial",
]);

there is no way to register users to be indexed by the server yet (either Index nor View servers) so you can just manually add your account to the system.db file for now

View Server#

start it by running

deno task view

expose your localhost to the web using a tunnel or something and use that url as the custom appview url

this should work on any bluesky client that supports changing the appview URL (im using an unreleased custom fork for development) as the view server implements the #bsky_appview routes for compatibility with existing clients

the view server has extra configurations that you need to understand. the view server hydrates content by calling other servers (either an #skylite_index or #bsky_appview) and so you need to write the order of which servers are prioritized first for resolving the hydration endpoints

// In order of which skylite index servers or bsky appviews to use first
"indexPriority": [
  "user#skylite_index",                      // user resolved skylite index server
  "did:web:backupindexserver.your.site#skylite_index", // a specific skylite index server
  "user#bsky_appview",                       // user resolved bsky appview
  "did:web:api.bsky.app#bsky_appview"        // a specific bsky appview
]

id say this project is like uhh ~20% done so not a lot of things you can do with this right now