Cairns help you find your way in a trail.
Go 96%
Dockerfile 2%
HTML 2%

README.md

Park Passport #

Mobile-first PWA for GPS-verified National Park stamps. Identity and data live on AT Protocol.

Stack #

Layer Technology
Frontend React Native / mobile-first PWA
Backend Go
Identity AT Protocol / Bluesky OAuth
User data User's own AT Protocol PDS
Park data NPS Public API + bundled GeoJSON
Credentials W3C Verifiable Credentials 2.0

Architecture #

The backend issues signed W3C VCs but stores nothing. All stamp records and VC blobs live on the user's PDS.

Client                    Verification Service           User PDS
  │                               │                          │
  ├─ { did, parkId, coords } ────►│                          │
  │                               ├─ check GeoJSON boundary  │
  │                               ├─ sign VC (EdDSA)         │
  │                               ├─ write VC blob ─────────►│
  │◄─ vcRef (CID) ────────────────│                          │
  │                                                          │
  ├─ write app.parkpassport.stamp record ───────────────────►│

Stamp Record (app.parkpassport.stamp) #

parkId              string
visitedAt           datetime
verificationMethod  "gps" | "exif" | "passport-import"
vcRef               blob ref (CID of VC blob in PDS blob store)
photoRef            blob ref (optional)

Verifiable Credential Structure #

{
  "@context": ["https://www.w3.org/ns/credentials/v2"],
  "type": ["VerifiableCredential", "NationalParkStamp"],
  "issuer": "did:web:verify.parkpassport.app",
  "validFrom": "2026-03-22T14:30:00Z",
  "credentialSubject": {
    "id": "did:plc:abc123",
    "parkId": "acadia",
    "parkName": "Acadia National Park",
    "visitedAt": "2026-03-22T14:30:00Z",
    "verificationMethod": "gps"
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "eddsa-rdfc-2022",
    "verificationMethod": "did:web:verify.parkpassport.app#key-1",
    "proofValue": "..."
  }
}

Stamps are independently verifiable: fetch the VC blob from the user's PDS, fetch the issuer public key from https://verify.parkpassport.app/.well-known/did.json, verify the EdDSA signature.

Stamp Issuance Flow (GPS) #

  1. Client requests device GPS coordinates
  2. Client sends { did, parkId, coords, authToken } to verification service
  3. Service checks coords against bundled park GeoJSON boundary
  4. Service signs a W3C VC 2.0 and writes it as a blob to the user's PDS
  5. Service returns vcRef (blob CID)
  6. Client writes app.parkpassport.stamp record to PDS repo with vcRef

Key Endpoints #

Endpoint Purpose
POST /stamp Issue a signed VC for a GPS-verified park visit
GET /.well-known/did.json Issuer DID document with public key

Data Sources #

  • NPS Public API — park metadata (requires free API key from nps.gov/subjects/developer)
  • NPS GeoJSON — park boundary polygons from services1.arcgis.com/fBc8EJBxQRMcHlei/arcgis/rest/services/; bundled at build time for the MVP park

Infrastructure #

  • Verification service: Cloudflare Workers
  • Issuer DID: did:web:verify.parkpassport.app
  • User data: user's existing Bluesky PDS