Highly ambitious ATProtocol AppView service and sdks
1# Getting Started
2
3Build your first AT Protocol app in minutes with the Slices CLI.
4
5## Quick Start
6
7### Install the CLI
8
9You'll need Deno installed first. Get it at [deno.com](https://deno.com/).
10
11```bash
12# Install from JSR
13deno install -g -A jsr:@slices/cli --name slices
14```
15
16### Login to Slices
17
18Before creating a project, authenticate with your AT Protocol account:
19
20```bash
21slices login
22```
23
24This will open a browser window where you can authorize the CLI with your AT
25Protocol handle.
26
27### Create Your Project
28
29```bash
30# Create a new project with automatic setup
31slices init my-vinyl-app
32
33# Or let us generate a name/domain for you
34slices init
35```
36
37The `slices init` command does everything for you:
38
39- Creates a full-stack Deno app with OAuth authentication
40- Automatically creates a slice on the network
41- Sets up OAuth credentials
42- Pulls standard lexicons (including Bluesky profiles)
43- Generates a TypeScript SDK
44- Initializes a git repository
45
46### Start Developing
47
48```bash
49cd my-vinyl-app
50deno task dev
51```
52
53Visit http://localhost:8080 and you're live!
54
55## What You Get
56
57The `slices init` command creates a production-ready app with:
58
59> More templates/examples coming soon (i.e. React, Expo, Astro, etc)
60
61### Full-Stack Deno Application
62
63- **Server-side rendering** with Preact and JSX
64- **OAuth authentication** with PKCE flow and automatic token refresh
65- **HTMX integration** for dynamic UI without complex JavaScript
66- **Tailwind CSS** for beautiful, responsive styling
67- **SQLite sessions** for secure session management
68- **Feature-based architecture** for scalable code organization
69
70### AT Protocol Integration
71
72- **Configured slice** with your own namespace
73- **Generated TypeScript SDK** from your lexicons
74- **Automatic sync** capabilities
75- **Real-time updates** via Jetstream
76
77### Development Experience
78
79- **Hot reload** in development
80- **Type safety** throughout
81- **Environment variables** pre-configured
82- **Git repository** initialized
83
84## Project Structure
85
86Here's what the generated project structure looks like:
87
88```
89my-vinyl-app/
90├── slices.json # Slice configuration
91├── .env # Your credentials (auto-generated)
92├── deno.json # Deno configuration
93├── lexicons/ # AT Protocol schemas
94│ ├── com/
95│ │ └── recordcollector/
96│ │ └── album.json
97│ └── app/
98│ └── bsky/
99│ └── actor/
100│ └── profile.json
101└── src/
102 ├── main.ts # Server entry point
103 ├── config.ts # App configuration
104 ├── generated_client.ts # Your TypeScript SDK
105 ├── routes/ # HTTP routes
106 ├── features/ # Feature modules
107 │ ├── auth/ # OAuth implementation
108 │ └── dashboard/ # Main app UI
109 ├── shared/ # Reusable components
110 └── utils/ # Helper functions
111```
112
113## CLI Commands
114
115The Slices CLI is your command center:
116
117### Project Management
118
119```bash
120# Create a new project
121slices init my-app
122
123# Check your authentication status
124slices status
125
126# Authenticate with Slices network
127slices login
128```
129
130### Lexicon Management
131
132```bash
133# Pull lexicons from your slice
134slices lexicon pull
135
136# Push local lexicons to your slice
137slices lexicon push
138
139# List lexicons in your slice
140slices lexicon list
141```
142
143### Code Generation
144
145```bash
146# Generate TypeScript SDK from lexicons
147slices codegen
148
149# The SDK is created at src/generated_client.ts
150```
151
152### Monitoring
153
154```bash
155# View real-time Jetstream logs
156slices logs
157
158# See sync activity and data flow
159slices logs --verbose
160```
161
162## Working with Lexicons
163
164Lexicons define your data structure. The init command includes Bluesky profile
165lexicons to get you started, but you'll want to add your own custom lexicons for
166your app.
167
168### Modify an Existing Lexicon
169
170Edit `lexicons/com/recordcollector/album.json`:
171
172```json
173{
174 "lexicon": 1,
175 "id": "com.recordcollector.album",
176 "defs": {
177 "main": {
178 "type": "record",
179 "description": "A vinyl album in my collection",
180 "record": {
181 "type": "object",
182 "required": ["title", "artist", "releaseDate"],
183 "properties": {
184 "title": { "type": "string" },
185 "artist": { "type": "string" },
186 "releaseDate": {
187 "type": "string",
188 "format": "datetime"
189 },
190 "genre": {
191 "type": "array",
192 "items": { "type": "string" }
193 },
194 "condition": {
195 "type": "string",
196 "enum": [
197 "Mint",
198 "Near Mint",
199 "Very Good Plus",
200 "Very Good",
201 "Good",
202 "Fair",
203 "Poor"
204 ]
205 },
206 "notes": { "type": "string" }
207 }
208 }
209 }
210 }
211}
212```
213
214### Create a New Lexicon
215
216Create `lexicons/com/recordcollector/review.json`:
217
218```json
219{
220 "lexicon": 1,
221 "id": "com.recordcollector.review",
222 "defs": {
223 "main": {
224 "type": "record",
225 "description": "Album review",
226 "record": {
227 "type": "object",
228 "required": ["albumUri", "rating", "content"],
229 "properties": {
230 "albumUri": {
231 "type": "string",
232 "format": "at-uri"
233 },
234 "rating": {
235 "type": "integer",
236 "minimum": 1,
237 "maximum": 5
238 },
239 "content": { "type": "string" },
240 "createdAt": {
241 "type": "string",
242 "format": "datetime"
243 }
244 }
245 }
246 }
247 }
248}
249```
250
251### Update Your Slice
252
253After modifying lexicons:
254
255```bash
256# Push changes to your slice
257slices lexicon push
258
259# Regenerate the TypeScript SDK
260slices codegen
261```
262
263Your SDK at `src/generated_client.ts` now includes the new types and methods!
264
265**Important:** You must push your lexicons to the slice before you can create
266records. The slice needs to know about your schema in order to validate and
267store records.
268
269## Using the Generated SDK
270
271The generated SDK provides a type-safe client for your slice:
272
273```typescript
274import { AtprotoClient } from "./generated_client.ts";
275
276// Initialize the client
277const client = new AtprotoClient({
278 baseUrl: "https://api.slices.network",
279 sliceUri: Deno.env.get("SLICE_URI")!,
280});
281
282// List albums with filtering and sorting
283const albums = await client.com.recordcollector.album.getRecords({
284 where: {
285 genre: { contains: "jazz" },
286 },
287 sortBy: [{ field: "releaseDate", direction: "desc" }],
288 limit: 20,
289});
290
291// Add a new album
292const newAlbum = await client.com.recordcollector.album.createRecord({
293 title: "Kind of Blue",
294 artist: "Miles Davis",
295 releaseDate: "1959-08-17T00:00:00Z",
296 genre: ["jazz", "modal jazz"],
297 condition: "Near Mint",
298 notes: "Original Columbia pressing",
299});
300
301// Get a specific album
302const album = await client.com.recordcollector.album.getRecord({
303 uri: newAlbum.uri,
304});
305
306// Update an album
307await client.com.recordcollector.album.updateRecord({
308 uri: album.uri,
309 record: {
310 ...album.value,
311 notes: "Verified as first pressing!",
312 },
313});
314
315// Delete an album
316await client.com.recordcollector.album.deleteRecord({
317 uri: album.uri,
318});
319```
320
321### External Collections
322
323Since the init command included Bluesky profile lexicons, your SDK has methods
324for querying them:
325
326```typescript
327// Query users by display name (from included Bluesky lexicons)
328const profiles = await client.app.bsky.actor.profile.getRecords({
329 where: {
330 displayName: { contains: "vinyl collector" },
331 },
332});
333```
334
335Any record-type lexicon you add to your slice will generate corresponding SDK
336methods when you run `slices codegen`.
337
338## Syncing Data
339
340Once your app is running, you can sync data from the AT Protocol network.
341
342### User Authentication Sync
343
344When users log in via OAuth, you can sync their data using the
345`syncUserCollections` method. This discovers and imports their external
346collections (like Bluesky profiles and posts).
347
348```typescript
349// After user logs in
350await client.network.slices.slice.syncUserCollections();
351```
352
353### Manual Bulk Sync
354
355Use the web interface at https://slices.network to start a bulk sync job.
356Navigate to your slice's Sync tab to configure which collections and
357repositories to sync.
358
359**Note:** If you created new lexicons, you'll be the only one with records
360initially. As more users adopt your app and write records to their own PDSs, you
361can sync from their repositories to grow your network.
362
363### Real-time Updates
364
365Jetstream automatically tracks creates, updates, and deletes across the network:
366
367```bash
368# Monitor real-time sync
369slices logs --slice $SLICE_URI
370```
371
372## Deployment
373
374Your app is ready for production deployment.
375
376### Deno Deploy
377
378Create a free account at [deno.com/deploy](https://deno.com/deploy). Push your
379code to GitHub, then connect your repository through the Deno Deploy dashboard
380to deploy your app.
381
382For production use with Deno Deploy, switch from SQLite to Deno KV for OAuth and
383session storage:
384
385```typescript
386import { DenoKVOAuthStorage } from "@slices/oauth";
387import { DenoKVAdapter } from "@slices/session";
388
389// Configure OAuth with Deno KV storage
390const oauthClient = new OAuthClient({
391 clientId: Deno.env.get("OAUTH_CLIENT_ID")!,
392 clientSecret: Deno.env.get("OAUTH_CLIENT_SECRET")!,
393 authBaseUrl: Deno.env.get("OAUTH_AIP_BASE_URL")!,
394 redirectUri: Deno.env.get("OAUTH_REDIRECT_URI")!,
395 storage: new DenoKVOAuthStorage(), // Uses Deno KV
396});
397
398// Configure sessions with Deno KV adapter
399const sessionStore = new SessionStore({
400 adapter: new DenoKVAdapter(), // Uses Deno KV
401 cookieOptions: {
402 secure: true,
403 httpOnly: true,
404 },
405});
406```
407
408Deno KV provides serverless-compatible storage that scales automatically with
409your deployment.
410
411## Manual Setup (Advanced)
412
413If you prefer to set things up manually or need custom configuration:
414
415### 1. Create a Slice via Web UI
416
417Visit https://slices.network and:
418
4191. Log in with your AT Protocol account
4202. Click "Create Slice"
4213. Choose your namespace (e.g., `com.recordcollector`)
422
423### 2. Create OAuth Credentials
424
425In your slice dashboard:
426
4271. Go to Settings → OAuth Clients
4282. Create a new client
4293. Set redirect URI: `http://localhost:8080/oauth/callback`
4304. Copy the Client ID and Secret
431
432### 3. Set Up Your Project
433
434Use any framework you prefer. You can use the generated TypeScript SDK (works
435with any JavaScript/TypeScript environment) or call the XRPC endpoints directly
436from any language:
437
438```bash
439# Configure environment
440cp .env.example .env
441# Edit .env with your credentials
442
443# Start your project
444# (commands depend on your framework choice)
445```
446
447## Next Steps
448
449- [Core Concepts](./concepts.md): Understand slices, lexicons, sync, and code
450 generation
451- [API Reference](./api-reference.md): Detailed endpoint documentation
452- [SDK Usage](./sdk-usage.md): Advanced SDK patterns and examples
453- [Examples](./examples/): Sample applications and use cases
454
455## Need Help?
456
457- Join our [Discord community](https://discord.gg/slices)
458- Check out [example apps](https://github.com/slices/examples)
459- Read the [AT Protocol docs](https://atproto.com/)
460- Report issues on [Tangled](https://tangled.sh/slices.network/slices/issues)