···11-# Following Feed Example
22-33-A simple HTML example demonstrating how to view Bluesky profile posts using Quickslice's GraphQL API.
44-55-## Features
66-77-- OAuth login with PKCE flow
88-- Client-side routing (`/profile/{handle}`)
99-- View any user's posts (excluding replies)
1010-- Display post text and embedded images
1111-1212-## Setup
1313-1414-1. Start the Quickslice server on `localhost:8080`
1515-2. Open `index.html` in a browser
1616-3. Enter your OAuth Client ID and Bluesky handle
1717-4. After login, you'll be redirected to your profile page
1818-1919-## Routes
2020-2121-- `/` - Home page (redirects to profile when logged in)
2222-- `/profile/{handle}` - View posts from a specific user
2323-2424-## GraphQL Query Used
2525-2626-```graphql
2727-query GetPosts($handle: String!) {
2828- appBskyFeedPost(
2929- sortBy: [{direction: DESC, field: createdAt}]
3030- where: {
3131- and: [
3232- {actorHandle: {eq: $handle}},
3333- {reply: {isNull: true}}
3434- ]
3535- }
3636- ) {
3737- edges {
3838- node {
3939- text
4040- createdAt
4141- appBskyActorProfileByDid {
4242- displayName
4343- actorHandle
4444- avatar { url }
4545- }
4646- embed {
4747- ... on AppBskyEmbedImages {
4848- images {
4949- image { url }
5050- }
5151- }
5252- }
5353- }
5454- }
5555- }
5656-}
5757-```
5858-5959-## Notes
6060-6161-- Requires authentication to view profiles
6262-- Posts are sorted by creation date (newest first)
6363-- Replies are filtered out to show only original posts
···11-{
22- "lexicon": 1,
33- "id": "app.bsky.feed.postgate",
44- "defs": {
55- "main": {
66- "key": "tid",
77- "type": "record",
88- "record": {
99- "type": "object",
1010- "required": [
1111- "post",
1212- "createdAt"
1313- ],
1414- "properties": {
1515- "post": {
1616- "type": "string",
1717- "format": "at-uri",
1818- "description": "Reference (AT-URI) to the post record."
1919- },
2020- "createdAt": {
2121- "type": "string",
2222- "format": "datetime"
2323- },
2424- "embeddingRules": {
2525- "type": "array",
2626- "items": {
2727- "refs": [
2828- "#disableRule"
2929- ],
3030- "type": "union"
3131- },
3232- "maxLength": 5,
3333- "description": "List of rules defining who can embed this post. If value is an empty array or is undefined, no particular rules apply and anyone can embed."
3434- },
3535- "detachedEmbeddingUris": {
3636- "type": "array",
3737- "items": {
3838- "type": "string",
3939- "format": "at-uri"
4040- },
4141- "maxLength": 50,
4242- "description": "List of AT-URIs embedding this post that the author has detached from."
4343- }
4444- }
4545- },
4646- "description": "Record defining interaction rules for a post. The record key (rkey) of the postgate record must match the record key of the post, and that record must be in the same repository."
4747- },
4848- "disableRule": {
4949- "type": "object",
5050- "properties": {},
5151- "description": "Disables embedding of this post."
5252- }
5353- }
5454-}
···11-{
22- "lexicon": 1,
33- "id": "com.atproto.label.defs",
44- "defs": {
55- "label": {
66- "type": "object",
77- "required": [
88- "src",
99- "uri",
1010- "val",
1111- "cts"
1212- ],
1313- "properties": {
1414- "cid": {
1515- "type": "string",
1616- "format": "cid",
1717- "description": "Optionally, CID specifying the specific version of 'uri' resource this label applies to."
1818- },
1919- "cts": {
2020- "type": "string",
2121- "format": "datetime",
2222- "description": "Timestamp when this label was created."
2323- },
2424- "exp": {
2525- "type": "string",
2626- "format": "datetime",
2727- "description": "Timestamp at which this label expires (no longer applies)."
2828- },
2929- "neg": {
3030- "type": "boolean",
3131- "description": "If true, this is a negation label, overwriting a previous label."
3232- },
3333- "sig": {
3434- "type": "bytes",
3535- "description": "Signature of dag-cbor encoded label."
3636- },
3737- "src": {
3838- "type": "string",
3939- "format": "did",
4040- "description": "DID of the actor who created this label."
4141- },
4242- "uri": {
4343- "type": "string",
4444- "format": "uri",
4545- "description": "AT URI of the record, repository (account), or other resource that this label applies to."
4646- },
4747- "val": {
4848- "type": "string",
4949- "maxLength": 128,
5050- "description": "The short string name of the value or type of this label."
5151- },
5252- "ver": {
5353- "type": "integer",
5454- "description": "The AT Protocol version of the label object."
5555- }
5656- },
5757- "description": "Metadata tag on an atproto resource (eg, repo or record)."
5858- },
5959- "selfLabel": {
6060- "type": "object",
6161- "required": [
6262- "val"
6363- ],
6464- "properties": {
6565- "val": {
6666- "type": "string",
6767- "maxLength": 128,
6868- "description": "The short string name of the value or type of this label."
6969- }
7070- },
7171- "description": "Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel."
7272- },
7373- "labelValue": {
7474- "type": "string",
7575- "knownValues": [
7676- "!hide",
7777- "!no-promote",
7878- "!warn",
7979- "!no-unauthenticated",
8080- "dmca-violation",
8181- "doxxing",
8282- "porn",
8383- "sexual",
8484- "nudity",
8585- "nsfl",
8686- "gore"
8787- ]
8888- },
8989- "selfLabels": {
9090- "type": "object",
9191- "required": [
9292- "values"
9393- ],
9494- "properties": {
9595- "values": {
9696- "type": "array",
9797- "items": {
9898- "ref": "#selfLabel",
9999- "type": "ref"
100100- },
101101- "maxLength": 10
102102- }
103103- },
104104- "description": "Metadata tags on an atproto record, published by the author within the record."
105105- },
106106- "labelValueDefinition": {
107107- "type": "object",
108108- "required": [
109109- "identifier",
110110- "severity",
111111- "blurs",
112112- "locales"
113113- ],
114114- "properties": {
115115- "blurs": {
116116- "type": "string",
117117- "description": "What should this label hide in the UI, if applied? 'content' hides all of the target; 'media' hides the images/video/audio; 'none' hides nothing.",
118118- "knownValues": [
119119- "content",
120120- "media",
121121- "none"
122122- ]
123123- },
124124- "locales": {
125125- "type": "array",
126126- "items": {
127127- "ref": "#labelValueDefinitionStrings",
128128- "type": "ref"
129129- }
130130- },
131131- "severity": {
132132- "type": "string",
133133- "description": "How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing.",
134134- "knownValues": [
135135- "inform",
136136- "alert",
137137- "none"
138138- ]
139139- },
140140- "adultOnly": {
141141- "type": "boolean",
142142- "description": "Does the user need to have adult content enabled in order to configure this label?"
143143- },
144144- "identifier": {
145145- "type": "string",
146146- "maxLength": 100,
147147- "description": "The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+).",
148148- "maxGraphemes": 100
149149- },
150150- "defaultSetting": {
151151- "type": "string",
152152- "default": "warn",
153153- "description": "The default setting for this label.",
154154- "knownValues": [
155155- "ignore",
156156- "warn",
157157- "hide"
158158- ]
159159- }
160160- },
161161- "description": "Declares a label value and its expected interpretations and behaviors."
162162- },
163163- "labelValueDefinitionStrings": {
164164- "type": "object",
165165- "required": [
166166- "lang",
167167- "name",
168168- "description"
169169- ],
170170- "properties": {
171171- "lang": {
172172- "type": "string",
173173- "format": "language",
174174- "description": "The code of the language these strings are written in."
175175- },
176176- "name": {
177177- "type": "string",
178178- "maxLength": 640,
179179- "description": "A short human-readable name for the label.",
180180- "maxGraphemes": 64
181181- },
182182- "description": {
183183- "type": "string",
184184- "maxLength": 100000,
185185- "description": "A longer description of what the label means and why it might be applied.",
186186- "maxGraphemes": 10000
187187- }
188188- },
189189- "description": "Strings which describe the label in the UI, localized into a specific language."
190190- }
191191- }
192192-}