A complete location-based social feed generator and web interface built on the AT Protocol for decentralized social networking. Provides both API endpoints for mobile clients and a web interface for viewing and sharing check-ins.
The system consists of 4 main components:
- Ingestion - Real-time check-in data ingestion from AT Protocol Jetstream
- API - RESTful APIs for global, nearby, user, and following feeds
- Web Interface - React-based web frontend for viewing feeds and shareable checkin detail pages
- Social - Social graph sync from Bluesky for following feeds
src/
āāā ingestion/ # Data ingestion from AT Protocol
ā āāā jetstream-poller.ts
āāā api/ # HTTP API endpoints
ā āāā anchor-api.ts
āāā social/ # Social graph management
ā āāā social-graph-sync.ts
āāā utils/ # Shared utilities
āāā handle-resolver.ts
āāā address-resolver.ts
āāā address-cache.ts # Val Town blob storage cache
āāā profile-resolver.ts # Profile caching and resolution
āāā profile-refresh-job.ts # Background profile refresh
frontend/
āāā main.tsx # React app entry point and routing
āāā components/ # React components
ā āāā CheckinDetail.tsx # Individual checkin detail view with map
ā āāā Feed.tsx # Global feed component
ā āāā Layout.tsx # App layout and navigation
āāā types/
āāā index.ts # TypeScript type definitions
database/
āāā database-schema.sql # SQLite schema and indexes
āāā add-profile-cache.sql # Profile cache migration
docs/
āāā api-documentation.md # Complete API reference for client development
āāā deployment-guide.md # Deployment instructions
scripts/
āāā deploy.sh # One-click deployment script
āāā test.sh # Run complete test suite
āāā debug.ts # Debug data availability and API status
āāā monitor-api.sh # Monitor deployed API status
tests/
āāā unit/ # Unit tests for individual functions
ā āāā handle-resolver.test.ts
ā āāā profile-resolver.test.ts # Profile caching and resolution
ā āāā address-cache.test.ts
ā āāā database.test.ts
ā āāā spatial.test.ts
āāā integration/ # Integration tests for API endpoints
ā āāā api.test.ts
ā āāā api-profiles.test.ts # API endpoints with profile data
āāā fixtures/ # Test data and fixtures
āāā test-data.ts
# Install Val Town CLI npm install -g @valtown/cli # Login to Val Town vt login # Run tests first ./scripts/test.sh # Deploy all functions ./scripts/deploy.sh # Monitor the deployment ./scripts/monitor-api.sh
# Deploy individual functions vt create cron jetstreamPoller --file src/ingestion/jetstream-poller.ts --schedule "*/5 * * * *" vt create http anchorAPI --file src/api/anchor-api.ts vt create cron socialGraphSync --file src/social/social-graph-sync.ts --schedule "0 2 * * *"
Note: No manual database setup required! Tables are created automatically when functions first run.
Base URL: https://dropanchor.app
GET https://dropanchor.app/api/global?limit=50&cursor=2025-06-29T15:00:00Z
Recent check-ins from all users with pagination.
GET https://dropanchor.app/api/nearby?lat=52.0705&lng=4.3007&radius=5&limit=50
Spatial query for check-ins within specified radius (km).
GET https://dropanchor.app/api/user?did=did:plc:abc123&limit=50
All check-ins from a specific user.
GET https://dropanchor.app/api/following?user=did:plc:abc123&limit=50&cursor=2025-06-29T15:00:00Z
Check-ins from people the specified user follows on Bluesky.
GET https://dropanchor.app/api/checkin/{rkey}
Individual checkin data by record key for detail views and sharing.
GET https://dropanchor.app/api/stats
AppView health metrics and processing statistics.
https://dropanchor.app/
Web interface showing the global feed of check-ins.
https://dropanchor.app/checkin/{rkey}
Individual checkin detail page with interactive map, optimized for sharing on social media with Open Graph meta tags.
For complete API documentation including examples, data models, and SDK code samples, see:
The system uses 5 main SQLite tables:
checkins_v1
- Main check-ins with coordinates and cached address dataaddress_cache_v1
- Resolved venue/address information from strongrefsprofile_cache_v1
- Cached user profile data (display names, avatars)user_follows_v1
- Social graph data for following-based feedsprocessing_log_v1
- Monitoring and operational logging
- Real-time Ingestion: WebSocket polling every 5 minutes from Jetstream
- Address Resolution: Automatic strongref resolution with caching
- Profile Resolution: Automatic profile data fetching and caching
- Spatial Queries: Nearby check-ins using Haversine distance calculations
- Social Integration: Following feeds leveraging Bluesky's social graph
- Performance: SQLite with proper indexing for fast queries
- Error Handling: Comprehensive error tracking and retry logic
- Global Feed View: Browse all check-ins with author profiles and timestamps
- Shareable Checkin Pages: Individual checkin detail pages with interactive maps
- Interactive Maps: OpenStreetMap integration via Leaflet with CartoDB tiles
- Social Sharing: Optimized sharing with Web Share API and copy functionality
- Responsive Design: Mobile-friendly interface using system fonts
- Open Graph Tags: Rich social media previews for shared checkin URLs
- Share URL Collisions: Currently using AT Protocol rkeys as unique
identifiers in share URLs (
/checkin/{rkey}
). While collision risk is negligible at current scale (~32 simultaneous checkins per microsecond for 50% collision probability), rkeys only provide 10 bits of entropy and are not cryptographically guaranteed to be globally unique. Consider migrating to composite identifiers (DID+rkey) or backend-generated UUIDs if collision issues emerge at scale.
The project includes comprehensive tests for all components:
Unit Tests:
profile-resolver.test.ts
- Profile caching, resolution, and refresh logichandle-resolver.test.ts
- Handle resolution from DIDsaddress-cache.test.ts
- Address caching and resolutiondatabase.test.ts
- Database operationsspatial.test.ts
- Spatial calculationsjetstream-ingestion.test.ts
- Event ingestion
Integration Tests:
api-profiles.test.ts
- API endpoints with profile data includedapi.test.ts
- Core API functionality
# Run all tests ./scripts/test.sh # Run specific test suites deno test --allow-all tests/unit/ # Unit tests only deno test --allow-all tests/integration/ # Integration tests only # Run tests in watch mode ./scripts/test.sh --watch # Run with coverage ./scripts/test.sh --coverage
- Use TypeScript for all functions
- Import SQLite:
import { sqlite } from "https://esm.town/v/std/sqlite"
- Import blob storage:
import { blob } from "https://esm.town/v/std/blob"
- Use
https://esm.sh
for external dependencies - Never hardcode secrets - use
Deno.env.get('keyname')
- Let errors bubble up with full context rather than catching and logging
- SQLite: Primary data (checkins, social graph, processing logs)
- Blob Storage: Caching layer for address resolution with automatic expiry
- Schema Changes: Increment table versions (e.g.,
checkins_v1
ācheckins_v2
) - Always create tables with
IF NOT EXISTS
on function startup
- Monitor
/stats
endpoint for system health - Check
processing_log_v1
for ingestion metrics - Use built-in logging and debugging tools
- Monitor SQLite performance as data grows
- All API endpoints include proper CORS headers
- Public APIs only - no authentication required
- Rate limiting built into external service calls
- No sensitive data logged or stored
The AppView is fully compatible with the AT Protocol ecosystem:
- Ingests from Jetstream (official AT Protocol firehose)
- Resolves DIDs using PLC directory
- Fetches records via
com.atproto.repo.getRecord
- Integrates with Bluesky social graph APIs
This implementation is part of the Anchor project for location-based social networking on the AT Protocol.