This repository contains a "sample" of an ATproto lexicon that defines everything needed to build a guestbook program.
The structure is as follows:
lexicons/contains the lexicons definitions.lexicons/com/fujocodedcontains our own definitionslexicons/com/atprotocontains the ATproto base definitions which are necessary for the program to work
client/contains sample client applications that allow you to create a guestbook, list submissions on one, or post your own commentsclient/clicontains a sample application using a command line interfaceclient/iframecontains a sample application using a html page with an iframeclient/astrocontains a sample application using an astro site
appview/contains the guestbook AppView. It collects guestbook-related events as they happen on the network, and offers a shared interface for guestbook applications to use.appview/ingester.tslistens to the stream of ATproto events on the network, grabs anything guestbook-related, and adds it to the AppView's databaseappview/index.tsimplements the query portion of the guestbook lexicon, offering applications a way to fetch guestbook-related informations
Right now, this is mostly a sample and teaching repo. You can watch us build this live (or recorded) by following Ms Boba on Twitch.
⊹₊ ˚‧︵‿₊୨ ᰔ ୧₊‿︵‧ ˚ ₊⊹
Support FujoCoded on Patreon for More of
This™!
⊹₊ ˚‧︵‿₊୨ ᰔ ୧₊‿︵‧ ˚ ₊⊹
The CLI client allows you to create, edit, delete and submit to guestbooks through a terminal.
The first step to use the client is to generate the lexicon API using the
definitions in the lexicons/ folder. You can do this using the
@atproto/lex-cli package. This
creates all the code we need to safely and more easily handle guestbook
operations.
npx @atproto/lex-cli gen-api ./client/generated/api ./lexicons/**/*.jsonRemember: you need to
npm installthe dependencies first!
- Open
client/cli/create-guestbook.tsand change things around to your desired data. - ENTER THE CLI DIRECTORY (
cd client/cli) - Run
npm run guestbook:create
- Open
client/cli/create-submission.tsand change things around to your desired data. - ENTER THE CLI DIRECTORY (
cd client/cli) - Run
npm run submission:create
The CLI provides several commands to view guestbooks and their submissions:
- List guestbook records from your PDS (unauthenticated):
npm run records:list - List guestbook records from your PDS (authenticated):
npm run records:list-auth
It also provides methods that require an AppView (the next step)
- List all guestbooks from the AppView (unauthenticated):
npm run guestbooks:get-all - List all guestbooks from the AppView (authenticated):
npm run guestbooks:get-all-auth
You can also see all the submissions as they happen with the following code:
websocat wss://jetstream2.us-east.bsky.network/subscribe\?wantedCollections=com.fujocoded.guestbook.submission | jq 'select(.kind == "commit")'
The AppView listens to guestbook-related events in the network and aggregates data for consumption by applications and other clients.
The first step to creating an AppView the client is to generate the endpoint
definitions for our server by using the definitions in the lexicons/ folder.
You can do this with the
@atproto/lex-cli package. This
creates all the code we need to provide applications with server endpoints that
respect the ATproto specifications and match the definitions in our lexicon.
npx @atproto/lex-cli gen-server ./client/generated/server ./lexicons/**/*.jsonThe DID document for your AppView will need a public/private key pair to ensure applications know you are who you say you are. Here's how you can generate one:
- Enter the AppView directory with
cd appview/ - Generate the public/private keys with
npm run keys:generate
To save the guestbook events in the network and all details about existing guestbooks we need a database with the right tables! You can create such a database by:
- Add a
DB_FILE_NAMEproperty in your.envfile (e.g.DB_FILE_NAME=appview.db) - Run
npx drizzle-kit push
To aggregate events on the network our AppView needs to listen to events on the
network, which it does through appview/ingestor.ts.
- Enter the AppView directory with
cd appview/ - Run the ingestor with
npm run dev:ingestor
Now we run the actual AppView server so applications can ask for the data they need.
- Enter the appview directory
cd appview/ - Run
npm run devto start serving the AppView
IMPORTANT: To make the AppView work, it needs to be reachable from the external internet at a specific address. If you have tailscale, you can use serve/funnel to create this address. You can also use ngrok, or cloudflare tunnels.
- Run
tailscale serve --bg http://localhost:3003 - Run
tailscale funnel --bg 3003 - Run
tailscale serve statusand use the address from the funnel
- Save the public address of your AppView server in the
.envfile underappview/(e.g.APPVIEW_DOMAIN=worktop.tail2ad46.ts.net)
Right now, you can't (unless you want to implement the whole thing from scratch)! Come to the streams and stay tuned for more functionality around this.
Experimented too much and hate leaving a mess around? Delete everything with
npm run dangerously-delete-everything, which will (again) DELETE
EVERYTHING.
To use it you should:
- Take the above steps to install the
clicommands - Enter the client directory with
cd client/cli/ - Run
npm run dangerously-delete-everything
If you want to be more targeted with what you delete and to set the right values
for your user, you can modify client/cli/delete-everything.ts. Good luck!
- Get someone else to write in the lexicon!
- Display other lexicons
- Turn the submission type returns into a union
- Deploy the AppView
- Allow hiding guestbook submissions
- Return information on submissions visibility in queries
- Return information on submissions visibility in guestbooks list
- Allow blocking users
- Allow restricting which URLs a guestbook is displayable on
- Return handles of users
- Return avatars of users
- Improve HTML generation
- Allow creating guestbooks
- Handle deletions of submissions
- Handle deletions of guestbooks
- Return information on submissions visibility in queries
- Return information on submissions visibility in guestbooks list
- Return hidden submissions ONLY if you're logged in
- Handle edits of guestbook
- Handle edits of submissions
NICE TO HAVES:
- DO NOT SWALLOW ERRORS and log them instead
- Save user profile info to database
- Periodically refresh user profile info in database
- Figure out if we can accept guestbook submissions from HTML iframes
- Try out CORS, maybe?
- Catch up with cursor
- Change timing of cursor save to consider all operations
- Handle deletions of submissions
- Handle deletions of guestbooks
- Handle edits of guestbook
- Handle edits of submissions
- Handle blocking of users
- Push new database schema for hidden submissions
- Make sure hiding submissions work
- Handle deletion of gates
NICE TO HAVES:
- Handle identity/account events
- Get rid of app passwords
- Test that it's still working
NICE TO HAVES:
- Allow global configuration
- Create initialization script
- Style the guestbook page
- Make the write submission form nicer
- Make overall styles decent
- Make our login look nice
- Inform user that they are logged in
- Allow users to use their handle and not just DID
- Allow users to log out
- Redirect to right port on login
- Figure out how to configure where it goes on logout
- Allow creating guestbooks
- Allow listing guestbooks of a user
- Move Astro-based client to client directory
- Re-add authentication to the client
- Allow deletions of submissions
- Allow deletions of your submissions on other people's guestbooks
- Allow deletions of guestbooks
- Do Astro trick to redirect after submission
- Hide hidden submissions when logged out
- Show which submissions are hidden to a logged in user on guestbook
- Show information on submissions visibility in guestbooks list
NICE TO HAVES:
- Figure out if we can allow submission via form
- Create Astro plugin to show guestbook
- Allow Astro plugin to set up guestbook
- Create webcomponent to display guestbook