Core Concepts#
Slices is built on four fundamental concepts that work together to create a powerful AT Protocol development platform.
Slices → Lexicons → Sync → APIs
(Container) → (Schema) → (Data) → (Access)
Slices: Your Data Universe#
What is a Slice?#
A slice is your own independent data space within the AT Protocol network. Think of it as a database with built-in APIs, authentication, and real-time sync, all isolated from other slices.
Why Slices Matter#
In the AT Protocol ecosystem, data lives on Personal Data Servers (PDS) scattered across the network. Slices acts as an AppView that:
- Aggregates data from across the network
- Applies your custom schemas
- Provides instant APIs for your data
- Maintains complete data isolation
Creating Your Slice#
When you create a slice for com.recordcollector:
Slice Name: My Vinyl Collection
Domain: com.recordcollector
URI: at://did:plc:abc123/network.slices.slice/xyz789
This slice becomes the container for all your vinyl collection data, completely isolated from other slices.
Key Properties#
- URI: Unique AT Protocol identifier
- Domain: Your namespace (e.g.,
com.recordcollector) - Isolation: Complete data separation between slices
- Multi-tenancy: Multiple users can have data in the same slice
Example: Record Collector Slice#
{
"uri": "at://did:plc:abc123/network.slices.slice/xyz789",
"name": "Vinyl Collection Manager",
"domain": "com.recordcollector",
"createdAt": "2024-01-15T10:00:00Z"
}
Lexicons: Data Schemas#
What are Lexicons?#
Lexicons are JSON schemas that define the structure of your data in AT Protocol. They're like database tables with built-in validation. In Slices, these lexicons automatically generate APIs for you.
Defining Your Data#
For a record collector app, you might define an album lexicon:
{
"lexicon": 1,
"id": "com.recordcollector.album",
"defs": {
"main": {
"type": "record",
"description": "A vinyl album in the collection",
"record": {
"type": "object",
"required": ["title", "artist", "releaseDate"],
"properties": {
"title": {
"type": "string",
"description": "Album title"
},
"artist": {
"type": "string",
"description": "Artist or band name"
},
"releaseDate": {
"type": "string",
"format": "datetime",
"description": "Original release date"
},
"genre": {
"type": "array",
"items": { "type": "string" },
"description": "Musical genres"
},
"condition": {
"type": "string",
"enum": [
"Mint",
"Near Mint",
"Very Good Plus",
"Very Good",
"Good",
"Fair",
"Poor"
],
"description": "Vinyl condition grading"
},
"notes": {
"type": "string",
"maxLength": 1000,
"description": "Collector's notes"
}
}
}
}
}
}
Primary vs External Lexicons#
Primary Lexicons: Match your slice domain:
com.recordcollector.albumcom.recordcollector.reviewcom.recordcollector.wishlist
External Lexicons: From other namespaces:
app.bsky.actor.profile(Bluesky profiles)sh.tangled.repo(Tangled Repo)social.grain.photo(Grain Photos)com.cassettecollector.tape(Cassette Collector)
Automatic API Generation#
Each lexicon with type: "record" automatically creates endpoints. Record types
are the only lexicons that generate CRUD APIs:
com.recordcollector.album (type: "record") →
/xrpc/com.recordcollector.album.getRecords
/xrpc/com.recordcollector.album.createRecord
/xrpc/com.recordcollector.album.updateRecord
/xrpc/com.recordcollector.album.deleteRecord
Note: Other lexicon types (like query, procedure, or subscription) serve
different purposes and don't create these standard CRUD endpoints.
Sync: Data Flow#
How Data Enters Your Slice#
The sync engine manages how data flows into your slice from the AT Protocol network.
Three Sync Strategies#
1. Bulk Sync: Historical Import#
Perfect for initial data loading or periodic updates. When you're first starting out, you might only be syncing your own records from your PDS. But as more people adopt your app and write records to their own PDSs, you can sync from their repositories too, growing your network.
Specify:
- Collections to sync (e.g.,
com.recordcollector.album) - External collections (e.g.,
app.bsky.actor.profilefor user profiles) - Specific repositories (DIDs) to import from
2. User Sync: On-Demand#
Automatically syncs when users log in. This is primarily for discovering and syncing external collections. When a new user authenticates for the first time, they become an actor in your slice, allowing you to discover what external collections they have (like Bluesky profiles or posts) and sync that data from their PDS.
3. Jetstream: Real-Time Updates#
Connects to the AT Protocol firehose for live updates. This tracks create, update, and delete events as they happen across the network.
Firehose Event → Filter by Collection → Validate → Store in Slice
Syncing External Data#
Import Bluesky profiles to show who owns each album and their Bluesky avatar.
You can sync external collections like app.bsky.actor.profile to enrich your
slice with user information from the broader AT Protocol network.
Performance Features#
- CID Deduplication: Skips unchanged records
- Bulk Operations: Processes thousands of records efficiently
- Actor Caching: Reduces database lookups
- Auto-Recovery: Handles network interruptions
Example: Syncing a Vinyl Community#
To sync all albums from a vinyl collecting community, you would:
- List primary collections (
com.recordcollector.album,com.recordcollector.review) - Include external collections (
app.bsky.actor.profile) to show collector information
Code Generation & XRPC Endpoints: APIs & SDKs#
Dynamic API Creation#
Every record-type lexicon automatically generates REST-like XRPC endpoints.
Generated Endpoints#
For com.recordcollector.album:
List Albums#
POST /xrpc/com.recordcollector.album.getRecords
{
"slice": "at://your-slice-uri",
"where": { "genre": { "contains": "jazz" } },
"sortBy": [{ "field": "releaseDate", "direction": "desc" }],
"limit": 20
}
Add Album#
POST /xrpc/com.recordcollector.album.createRecord
Authorization: Bearer YOUR_TOKEN
{
"slice": "at://your-slice-uri",
"record": {
"title": "Kind of Blue",
"artist": "Miles Davis",
"releaseDate": "1959-08-17T00:00:00Z",
"genre": ["jazz", "modal jazz"],
"condition": "Very Good Plus"
}
}
TypeScript SDK Generation#
Slices generates a fully-typed TypeScript client:
// Generated SDK with full type safety
import { AtprotoClient } from "./generated_client.ts";
const client = new AtprotoClient({
baseUrl: "https://api.slices.network",
sliceUri: "at://your-slice-uri",
auth: oauthClient,
});
// Fully typed operations
const albums = await client.com.recordcollector.album.getRecords({
where: {
condition: { in: ["Mint", "Near Mint"] },
genre: { contains: "jazz" },
},
sortBy: [{ field: "artist", direction: "asc" }],
limit: 50,
});
// Type-safe record creation
const newAlbum = await client.com.recordcollector.album.createRecord({
title: "Blue Train",
artist: "John Coltrane",
releaseDate: "1958-01-01T00:00:00Z",
genre: ["jazz", "hard bop"],
condition: "Near Mint",
notes: "Original Blue Note pressing",
});
OAuth Integration#
Built-in OAuth 2.0 with PKCE:
- Read operations: Public by default
- Write operations: Require authentication
- Automatic token refresh
- Secure session management
SDK Features#
- Type Safety: Full TypeScript types from lexicons
- Nested APIs:
client.com.recordcollector.album.* - Error Handling: Automatic retries and graceful failures
- Blob Support: Handle images and media files
How It All Works Together#
1. Create Slice → Define namespace (com.recordcollector)
↓
2. Add Lexicons → Define data structure (album, review, wishlist)
↓
3. Sync Data → Import existing vinyl collections
→ Subscribe to real-time updates
↓
4. Use APIs → Generated endpoints for all operations
→ Type-safe SDK for your app
Practical Example: Building a Vinyl Collector App#
Step 1: Create Your Slice#
Create a slice using the Slices CLI or web interface:
- Name: "Vintage Vinyl Collectors"
- Domain: "com.recordcollector"
Step 2: Define Lexicons#
Upload your lexicon definitions through the web UI or CLI:
- Album schema (
com.recordcollector.album) - Review schema (
com.recordcollector.review) - Wishlist schema (
com.recordcollector.wishlist)
Step 3: Sync Existing Data#
Start a sync job to import your existing collection:
- Use the Sync tab in the web UI
- Select collections to sync
- Specify repositories (or leave empty for all)
Step 4: Build Your App#
// Use the generated SDK
const client = new AtprotoClient(slice.uri);
// List all jazz albums in mint condition
const jazzMint = await client.com.recordcollector.album.getRecords({
where: {
genre: { contains: "jazz" },
condition: { eq: "Mint" },
},
});
// Add a new album to the collection
await client.com.recordcollector.album.createRecord({
title: "A Love Supreme",
artist: "John Coltrane",
releaseDate: "1965-02-01T00:00:00Z",
genre: ["jazz", "spiritual jazz"],
condition: "Near Mint",
});
Summary#
| Concept | Purpose | Record Collector Example |
|---|---|---|
| Slices | Isolated data container | com.recordcollector namespace with all your vinyl data |
| Lexicons | Schema definitions | album, review, wishlist record types |
| Sync | Data import & real-time updates | Import collections from network, live updates via Jetstream |
| Code Gen | Auto-generated APIs & SDKs | TypeScript client with getRecords, createRecord, etc. |
Next Steps#
- Getting Started: Create your first slice
- API Reference: Detailed endpoint documentation
- SDK Usage: Advanced SDK patterns