Note: I'm archiving this experiment and consider the ideas herein outdated after some solid feedback on Bluesky, an alternative approach based on the community feedback is in the works. Feel free to poke at what's here i will leave it up as a failed research experiment but it is no longer going to be maintained.
A specialized ATProto server for check-in records, providing location-based social features for the Anchor ecosystem.
This PDS powers the backend infrastructure for Drop Anchor - an experimental location-based social network built on the AT Protocol. While Drop Anchor provides the user interface and client experience, this PDS handles the storage, federation, and API endpoints for check-in records.
Production URL: https://anchorpds.val.run/
- Check-in Records: Create and store location-based check-ins using ATProto standard
- Authentication: Token validation via home PDS integration
- Federation: Full AT Protocol compliance for external client support
- Global Feed: View recent check-ins from all users (max 100 records)
- User Feed: View your own check-in history with pagination
POST /xrpc/com.atproto.repo.createRecord- Create check-in recordsGET /xrpc/com.atproto.sync.getRecord- Retrieve individual records
GET /xrpc/app.dropanchor.listCheckins- List user's check-ins (authenticated)GET /xrpc/app.dropanchor.getGlobalFeed- Global feed of recent check-insGET /health- Service health check
Each check-in follows the AT Protocol lexicon standard with structured location data:
{
"$type": "app.dropanchor.checkin",
"text": "Great coffee and climbing session!",
"createdAt": "2025-06-27T10:30:00Z",
"locations": [
{
"$type": "community.lexicon.location.geo",
"latitude": "40.7128",
"longitude": "-74.0060"
},
{
"$type": "community.lexicon.location.address",
"name": "Brooklyn Boulders",
"street": "123 Main St",
"locality": "New York",
"region": "NY",
"country": "US",
"postalCode": "10001"
}
],
"category": "climbing",
"categoryGroup": "Sports & Fitness",
"categoryIcon": "π§ββοΈ"
}- text: Message or venue name (required)
- createdAt: ISO timestamp (required)
- locations: Array of community.lexicon.location.* objects (optional)
- geo: GPS coordinates with latitude/longitude as strings
- address: Structured address with name, street, locality, region, country, postalCode
- category: OpenStreetMap category value
- categoryGroup: Human-readable group name
- categoryIcon: Unicode emoji representing the category
The PDS supports rich categorization based on OpenStreetMap standards with 11 custom category groups:
- π½οΈ Food & Drink - Restaurants, cafes, bars, food courts
- π Entertainment - Cinemas, theaters, nightlife, gaming
- πββοΈ Sports & Fitness - Gyms, climbing, swimming, sports venues
- ποΈ Shopping - Retail stores, markets, malls, specialty shops
- π¨ Accommodation - Hotels, hostels, guesthouses, camping
- π Transportation - Stations, airports, public transport
- ποΈ Services - Banks, government, professional services
- π³ Nature & Parks - Parks, gardens, nature reserves, outdoor recreation
- π¨ Culture - Museums, galleries, historic sites, libraries
- π₯ Health - Hospitals, clinics, pharmacies, healthcare
- π Education - Schools, universities, educational facilities
Categories map to OSM tags and values from these primary keys:
- amenity - Community facilities (66+ categories)
- leisure - Recreation and sports (40+ categories)
- shop - Retail and commercial (88+ categories)
- tourism - Tourist attractions and services (27+ categories)
For detailed category mappings, see OSM Map Features.
- SQLite database with proper indexing for performance
- Optimized for queries by author, timestamp, location, and categories
- User settings for feed preferences
Uses ATProto token validation:
- Accepts Bearer tokens from any compatible PDS
- Validates tokens against home PDS (bsky.social, staging.bsky.dev)
- In-memory caching for performance (1-hour TTL)
- Runtime: Deno on Val Town platform
- Framework: Hono web framework
- Database: Val Town hosted SQLite
- Protocol: AT Protocol (ATProto) compliant
- Language: TypeScript with full type safety
curl -X POST https://anchorpds.val.run/xrpc/com.atproto.repo.createRecord \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"collection": "app.dropanchor.checkin",
"record": {
"text": "Great coffee at the local cafΓ©!",
"createdAt": "2024-01-15T10:30:00Z",
"locations": [
{
"$type": "community.lexicon.location.geo",
"latitude": "40.7128",
"longitude": "-74.0060"
},
{
"$type": "community.lexicon.location.address",
"name": "Central Perk CafΓ©",
"street": "199 Lafayette St",
"locality": "New York",
"region": "NY",
"country": "US"
}
],
"category": "cafe",
"categoryGroup": "Food & Drink",
"categoryIcon": "β"
}
}'curl https://anchorpds.val.run/xrpc/app.dropanchor.getGlobalFeed?limit=10curl https://anchorpds.val.run/xrpc/app.dropanchor.listCheckins \
-H "Authorization: Bearer YOUR_TOKEN"All feed endpoints support cursor-based pagination:
limit: Number of records to return (default: 50, max: 100)cursor: Timestamp for pagination (optional)
Comprehensive test suite covering validation, database operations, and integration:
deno test test/Tests include validation of the v3 schema with categories, community lexicon location formats, and API endpoint functionality.
- Deno runtime
- Val Town CLI (
vt) - TypeScript knowledge
# Type checking
deno check --allow-import backend/index.ts
# Linting
deno lint
# Testing
deno test tests/
# Formatting
deno fmtUses Val Town platform for hosting:
vt push- Geospatial "nearby" queries with radius search
- Optional feed cross-posting to home PDS
- Advanced location filtering
- Likes support via Bluesky API proxy
- Direct check-in comments
- Social interaction feeds
MIT License - See LICENSE file for details
This is a specialized PDS implementation. For contributions:
- Follow Val Town development guidelines
- Maintain ATProto compliance
- Include comprehensive tests
- Use TypeScript with proper types
For issues or questions about the Anchor PDS implementation, please file an issue in the repository.