···11-# teal-demo
11+# slices-teal-demo
2233-A Deno SSR web application with AT Protocol integration, built with Preact,
44-HTMX, and OAuth authentication.
33+This is a demo app made with [Slices](https://slices.network/). It ingests [teal.fm](https://teal.fm/) records and displays the latest played tracks across the Atmosphere:
5466-## Quick Start
55+
7688-```bash
99-# Start the development server
1010-deno task dev
1111-```
77+(Note teal.fm doesn't have an official hosted app yet so you'd have to get [piper](https://github.com/teal-fm/piper) running to connect it to your Spotify or whatever.)
1281313-Visit your app at http://localhost:8080
99+## Prerequisites
14101515-> **Note:** Your slice and OAuth credentials were automatically configured
1616-> during project creation. The `.env` file is already set up with your
1717-> credentials.
1111+This is using Deno because the official Slices starter is using it, and I'm too lazy to change it. I'm not thrilled with that part, but installing it is [pretty easy](https://slices.network/docs/getting-started#install-the-cli). You can also install the Deno VS Code extension to fix squiggly lines in VS Code.
18121919-## Features
1313+To run the project, do `deno task dev`.
20142121-- 🔐 **OAuth Authentication** with PKCE flow
2222-- ⚡ **Server-Side Rendering** with Preact
2323-- 🎯 **Interactive UI** with HTMX
2424-- 🎨 **Styling** with Tailwind CSS
2525-- 🗄️ **Session Management** with SQLite
2626-- 🔄 **Auto Token Refresh**
2727-- 🏗️ **Feature-Based Architecture**
1515+## The Process
28162929-## Development
1717+1. I created the app with Slices CLI as described [here](https://slices.network/docs/getting-started)
1818+2. It [made a slice](https://slices.network/profile/danabra.mov/slice/3m257yljpbg2a) for me, I set `fm.teal` as its primary namespace
1919+3. I've manually added the `fm.teal` [lexicons](https://github.com/teal-fm/piper/tree/main/lexicons/teal/feed) to it via web UI
2020+4. I've pressed Sync in the web UI to backfill records
2121+5. I've downloaded updated codegen from web UI and pasted it into `src/generated_client.ts`.
30223131-```bash
3232-# Start development server with hot reload
3333-deno task dev
2323+This is all the code I've needed to add (second commit):
34243535-# Start production server
3636-deno task start
3737-3838-# Format code
3939-deno fmt
4040-4141-# Check types
4242-deno check src/**/*.ts src/**/*.tsx
4343-```
4444-4545-## Project Structure
4646-4747-```
4848-slices.json # Slices configuration file
4949-lexicons/ # AT Protocol lexicon definitions
5050-src/
5151-├── main.ts # Server entry point
5252-├── config.ts # OAuth & session configuration
5353-├── generated_client.ts # Generated TypeScript client from lexicons
5454-├── routes/ # Route definitions
5555-├── features/ # Feature modules
5656-│ └── auth/ # Authentication
5757-├── shared/fragments/ # Reusable UI components
5858-└── utils/ # Utility functions
2525+```js
2626+const plays = await publicClient.fm.teal.alpha.feed.play.getRecords({
2727+ sortBy: [{
2828+ direction: 'desc',
2929+ field: 'playedTime'
3030+ }]
3131+});
3232+const authorProfiles = await publicClient.app.bsky.actor.profile.getRecords({
3333+ where: {
3434+ did: {
3535+ in: Array.from(new Set(plays.records.map(rec => rec.did)))
3636+ }
3737+ },
3838+})
5939```
60406161-## OAuth Setup
4141+These are passed to the component that displays them.
62426363-Your OAuth application was automatically created during project initialization
6464-with:
4343+Very cool!
65446666-- **Client ID & Secret**: Already configured in `.env`
6767-- **Redirect URI**: `http://localhost:8080/oauth/callback`
6868-- **Slice**: Automatically created and linked
6969-7070-To manage your OAuth clients or create additional ones:
7171-7272-1. Visit [Slices Network](https://slices.network)
7373-2. Use the `slices login` CLI command
7474-7575-## Documentation
7676-7777-- `CLAUDE.md` - Architecture guide for AI assistance
7878-- Feature directories contain handlers and templates
7979-- Components use Preact with server-side rendering
8080-- HTMX provides interactive behavior without page reloads
8181-8282-## License
8383-8484-MIT
4545+Note that ingesting records in realtime is borked for some reason for my slice but hopefully this should be fixed upstream soon.