Private AI-powered maps with trustworthy on-chain reviews.
Google Maps tracks everything you do ($7.1B+ in fines). Review platforms can't stop fakes (240M removed by Google in 2024, 2,000+ FTC complaints against Yelp). Ghost Maps is a private maps app with AI-powered search, on-chain reviews guarded by an autonomous agent, and real navigation — all without tracking you.
Live at ghostmaps.app · Demo Video
The map defaults to Loveland, CO. Search for these places to see on-chain reviews with AI quality scoring, GPS verification, and community summaries:
- "Avery's Modern Teahouse" — search "tea in Loveland"
- "Slice House" — search "pizza in Loveland"
- "Verboten Brewing" — search "brewing in Loveland"
- Search privately — Type "best tacos near me" and Venice AI (zero data retention) interprets your query, finds places via Google Places (server-side, no user data sent), and ranks results with explanations
- See real details — Tap a place to see hours, photos, ratings, price level, and an AI-generated briefing
- Read trustworthy reviews — Reviews are on-chain attestations (EAS on Base) that no business can pay to remove and no platform can filter
- Write verified reviews — Sign up with email (invisible wallet created on Base), write a review with photo proof-of-visit, Venice AI scores quality, review goes on-chain — user never sees crypto
- Navigate privately — Turn-by-turn directions with traffic-aware ETA, speed limits, lane guidance, and live rerouting — without storing your route
An autonomous AI agent that monitors the Base blockchain for new Ghost Maps review attestations, investigates patterns, and publishes transparent verification verdicts on-chain.
The agent IS the LLM. It reasons natively about review patterns — no hardcoded rules. Given guidelines (not checklists), it decides what to investigate, how deep to go, and what action to take. Every situation is different, and the agent's response is different.
- Agent runs every hour on the Express server (or on-demand with
npx tsx agent/guardian.ts --once) - Agent reasons about patterns: wallet ages, timing, rating distributions, content similarity
- Agent uses tools to investigate: query wallet history, query place reviews, cross-reference
- Agent publishes verification attestations on-chain with verdict, confidence, and reasoning
Verdicts: legitimate | suspicious | sybil | spam
Verification Schema: string verdict, uint8 confidence, string reasoningSummary
Schema UID: 0x351ed5d597414cc66a0835da8614ac4d37af6213dc4deeee898912695a9bd635
Each verification attestation uses EAS refUID to reference the original review — native EAS composability. Anyone can read the verdicts, audit the reasoning, or deploy their own auditor agent against the same schema.
Why EAS instead of the ERC-8004 Validation Registry?
The Validation Registry validates agent work quality (agent-to-agent trust). Our attestations validate user-generated content (content trust). We chose EAS because: (1) any app can read our verifications without integrating ERC-8004, (2) attestations include human-readable reasoning, not just a numeric score, (3) reviews are already EAS attestations so refUID creates a native linked chain, and (4) verifications are useful regardless of who published them — full composability.
The Guardian is registered on the ERC-8004 Identity Registry on Base Sepolia. This gives it a verifiable on-chain identity (agentId NFT) and discoverable metadata about its capabilities and verification schema.
Guardian wallet: 0x2efeEd3097978664731ffe6EC0FaFa5CFD58b08D
GHOST token: 0x98d2ccd1d02F396A4a6FDE996381297c655BB198 (ERC-20 on Base Sepolia)
Verified reviews earn GHOST tokens on a quadratic reward curve — higher quality reviews earn exponentially more:
| Quality Score | GHOST Reward |
|---|---|
| 100 (Exceptional) | 100 GHOST |
| 75 (Detailed) | 56.25 GHOST |
| 50 (Decent) | 25 GHOST |
| 25 (Generic) | 6.25 GHOST |
| 10 (Minimal) | 1 GHOST |
Formula: GHOST = (quality²) / 100
The reward flow is fully on-chain and trustless:
- Reviewer submits review → on-chain attestation with quality score
- Guardian verifies review → on-chain verification attestation
- If verdict is
legitimatewith confidence ≥ 60% → GHOST tokens released to reviewer based on quality
Why this matters: Every previous token-incentivized review system failed because paying for reviews creates an incentive to fake them, and no one solved the filtering problem. The Guardian agent solves this — token rewards become viable because fraud is caught before rewards are distributed. The quadratic curve further incentivizes quality: a detailed review (quality 75) earns 9x more than a generic one (quality 25).
Reviews are Ethereum Attestation Service attestations — immutable, composable, and verifiable.
Schema: uint8 rating, string text, string placeId, string placeName, bytes32 photoHash, int256 lat, int256 lng, uint8 qualityScore
Schema UID: 0x968e91f0274b78a31037839b55e59b942dd1521daebf9190268137e450b7d69f
Why on-chain reviews matter:
- Businesses can't pay to remove negative reviews (unlike Yelp — 2,000+ FTC complaints alleging extortion)
- Platforms can't filter reviews to favor advertisers
- Reviews are composable — any app can read and build on them
- Quality scoring by Venice AI creates a trust signal without centralized moderation
- Gas is sponsored via CDP Paymaster — users pay $0
Review quality tiers: Generic (0-25) → Decent (26-50) → Detailed (51-75) → Exceptional (76-100)
Immutable reviews solve real problems (Yelp pay-to-play, platform censorship), but they create new ones. We've thought about this:
What about fake or harmful reviews? Current defenses:
- Venice AI content moderation — reviews are scored and checked for threats, hate speech, adult content, doxxing, spam, and sentiment-rating mismatches. 7 blocking flags prevent harmful content from reaching the chain.
- Server-side pre-check — pattern matching catches obvious threats and spam that LLMs may miss (death threats, URLs, all-caps spam)
- Minimum quality threshold — reviews must be at least 25 characters
- Fail closed — if Venice scoring fails, the review is rejected (not defaulted to "acceptable")
- EXIF GPS proof-of-visit — optional photo verification confirms the reviewer was physically at the location
- Account age and review count — credibility signals displayed on each review
- Review Guardian agent — autonomous post-publication verification (see above)
What about harassment or defamatory content? Reviews with threats, hate speech, adult content, or doxxing are blocked before they reach the chain — they never become attestations. For edge cases that pass automated checks, the client can filter reviews below a quality threshold.
What about sybil attacks (mass fake accounts)? The Review Guardian agent catches coordinated attacks by analyzing wallet behavior, timing patterns, and content similarity across reviews. Flagged reviews are publicly marked with on-chain verdicts.
Our position: Centralized moderation is a solved problem — and it's been solved badly (Yelp extortion, Google's 240M removed fakes in 2024). We'd rather build robust decentralized quality signals than recreate the system we're replacing.
Venice is central to the app, not a utility:
- Conversational search — Parse natural language queries ("late night tacos with outdoor seating"), extract intent (categories, attributes, radius), rank results with explanations
- Place intelligence briefing — Synthesize all POI data into a 2-3 sentence natural language summary per place
- Review quality scoring — Analyze specificity, sentiment-rating consistency, flag suspicious patterns (1-100 score)
- Review summarization — Aggregate all on-chain reviews for a place into a community briefing
- Photo verification — Metadata analysis (file size, GPS, dimensions) to support proof-of-visit
- Comparative recommendations — Compare 2-5 places using reviews + data, explain tradeoffs
Browser (React + MapLibre GL JS)
│
├── Venice AI ──── Natural language search parsing + ranking
│ Review quality scoring + summarization
│ Place intelligence briefings
│ Zero data retention
│
├── Google Places ── POI search, hours, ratings, photos
│ (server-side, no user identity sent)
│
├── TomTom ──────── Route calculation with live traffic
│ (anonymous origin/destination only)
│
├── EAS on Base ──── On-chain review attestations
│ Immutable, composable, sub-cent cost
│
└── Coinbase CDP ─── Email OTP signup → invisible wallet
Gas sponsored via Paymaster ($0 for users)
| What Google Maps Collects | What Ghost Maps Does |
|---|---|
| Location tracked constantly | No location storage. Venice = zero retention |
| Every search query saved | Venice = zero data retention |
| Navigation routes + speed + stops | TomTom calculates route, we don't store it |
| Every business view, click, call | No interaction tracking |
| Reviews tied to real identity | Pseudonymous (wallet address only) |
| Cross-app profiling (YouTube, Search, Ads) | No other services, no ad network |
| 11,500+ geofence warrants/year | Nothing to hand over |
| Tracked 98M users who opted out | No opt-out needed — data never exists |
Transparency: We disclose exactly what each service sees:
- TomTom sees anonymous origin/destination coordinates for route calculation. No user identity.
- Google Places sees place lookups and location coordinates (needed to find nearby places). All requests come from our server — Google never sees individual users, sessions, devices, or IP addresses. Google sees "a server looked up pizza near 40.15, -105.10" — not who searched or why. Google can observe aggregate query patterns from our server (what types of places are searched, in which regions). This is a deliberate tradeoff: Google's business data is the best available (~95% coverage for hours/ratings), and the alternative is empty place panels. Long-term, community-contributed attestations reduce this dependency.
- MapTiler serves map tiles directly to the browser. Tile requests reveal approximate area (city/neighborhood level, not precise location) via standard HTTP. This is the same as loading any map — no more identifying than browsing a weather site. No user identity is sent.
- Coinbase CDP handles wallet creation via email OTP. Coinbase holds the email-to-wallet mapping — but we don't store emails ourselves, and email-based auth is standard across every app. The alternative (asking users to manage seed phrases) would make the app unusable. CDP is a bridge to invisible crypto UX, not a surveillance vector.
- Server logs contain only errors and startup messages. No search queries, locations, or user data are logged.
| Layer | Technology |
|---|---|
| Frontend | React 19 + Vite + Tailwind CSS v4 + MapLibre GL JS |
| Map Tiles | MapTiler Streets v2 (vector tiles, 100K/month free) |
| State | Zustand (client state) + TanStack Query (server state) |
| Backend | Node.js + Express 5 + TypeScript (tsx) |
| AI | Venice API (OpenAI-compatible, zero data retention) |
| POI Data | Google Places API (search + enrichment, server-side, no user data sent) |
| Navigation | TomTom Routing API (traffic, speed limits, lane guidance) |
| On-Chain | EAS on Base via ethers.js + EAS SDK |
| Guardian Agent | MiniMax M2.7 via Venice API (autonomous review verification) |
| Agent Identity | ERC-8004 Identity Registry on Base |
| Token | GHOST ERC-20 on Base Sepolia (review rewards) |
| Auth | Coinbase CDP Embedded Wallets (email OTP, invisible wallet) |
| Streaming | Server-Sent Events (SSE) |
| Testing | Vitest (unit + integration) + Playwright (E2E) |
| Deployment | Railway (single service) |
Base URL: https://ghostmaps.app/api (production) or http://localhost:3001/api (development)
Full API documentation with request/response schemas: API.md
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/search?q=&lat=&lng= |
Basic search via Google Places |
GET |
/api/ai-search?q=&lat=&lng= |
AI-powered search (non-streaming) |
GET |
/api/ai-search/stream?q=&lat=&lng= |
AI-powered search with SSE streaming |
GET |
/api/places/:id |
Place details with Google Places enrichment |
GET |
/api/places/:id/briefing |
Venice AI place intelligence briefing |
POST |
/api/reviews/score |
Score review quality via Venice AI |
GET |
/api/reviews/:placeId |
Fetch on-chain reviews + identities + AI summary |
POST |
/api/photos |
Upload review photo (returns SHA-256 hash) |
GET |
/api/photos/:hash |
Serve review photo by hash |
POST |
/api/route |
Calculate route via TomTom (traffic-aware) |
POST |
/api/compare |
Compare 2-5 places via Venice AI |
GET |
/api/ghost-balance/:address |
GHOST token balance for a wallet address |
GET |
/api/server-ip |
Server outbound IP (for API key whitelisting) |
ghostmaps/
├── client/ # React frontend
│ └── src/
│ ├── components/ # UI components (Map, SearchBar, PlacePanel, NavigationPanel, etc.)
│ ├── hooks/ # Custom hooks (useAISearch, usePlaceDetails, useNavigationTracking, etc.)
│ ├── lib/ # Utilities (CDP wallet, EAS SDK, geo math, nav helpers)
│ └── assets/
├── server/ # Express API backend
│ ├── index.ts # Route definitions
│ ├── venice.ts # Venice AI (parse, rank, briefing, score, summarize, compare)
│ ├── search.ts # Distance calculations + coordinate parsing
│ ├── google-places.ts # Google Places search + enrichment + geocoding
│ ├── tomtom.ts # TomTom routing
│ ├── eas-reader.ts # EAS on-chain review fetching
│ ├── photos.ts # Photo upload/storage (SHA-256 keyed)
│ └── types.ts # TypeScript type definitions
├── agent/ # Review Guardian agent
│ ├── guardian.ts # Agent core — LLM loop with tool use
│ ├── guidelines.ts # Agent mandate and investigation principles
│ ├── tools.ts # EAS query + publish tools
│ ├── schema.ts # ReviewVerification schema definition
│ ├── test-harness.ts # Generate test scenarios (sybil, spam, organic, legitimate)
│ └── contracts/ # GHOST token + RewardDistributor
├── e2e/ # Playwright E2E tests
├── plans/ # Architecture docs, research, build plan
├── conversation-logs/ # Raw human-agent collaboration logs (24 sessions)
├── agent.json # JSON Agents PAM manifest (DevSpot/ERC-8004)
├── agent_log.json # Latest Guardian investigation log
├── API.md # Full API documentation
└── CLAUDE.md # Development guidelines
- Node.js 20+
- API keys: Venice, MapTiler, Google Places, TomTom, Coinbase CDP
git clone https://github.com/jeremylanger/ghostmaps.git
cd ghostmaps
# Create .env with required keys
cp .env.example .env
# Install dependencies
npm install
cd client && npm install --legacy-peer-deps && cd ..
cd server && npm install && cd ..# Required
VENICE_API_KEY= # Venice AI (zero data retention)
VITE_MAPTILER_KEY= # MapTiler Streets v2 tiles
GOOGLE_PLACES_API_KEY= # Place enrichment (hours, ratings, photos)
TOMTOM_API_KEY= # Route calculation
VITE_CDP_PROJECT_ID= # Coinbase CDP embedded wallets
# Guardian agent (in agent/.env)
GUARDIAN_PRIVATE_KEY= # Guardian wallet private key
VENICE_API_KEY= # Venice API key (for Guardian LLM)
GHOST_TOKEN_ADDRESS= # Deployed GHOST ERC-20 address
# Optional
PORT=3001 # Server port (default: 3001)# Terminal 1 — Backend
cd server && npm run dev # Express on :3001 (tsx watch)
# Terminal 2 — Frontend
cd client && npx vite --port 5174 # Vite on :5174, proxies /api to :3001# Server tests
cd server && npm test # All (unit + integration)
cd server && npm run test:unit # Unit only
cd server && npm run test:integration # Integration only
# E2E tests (requires both servers running)
npx playwright test --config e2e/playwright.config.tsDeployed on Railway as a single service (Express serves API + Vite static build).
# Deploy
railway up
# Check logs
railway logs --lines 20
# Set environment variables
railway vars set KEY=valueDNS: Porkbun (ALIAS record → Railway edge). SSL auto-provisioned by Railway.
Built for The Synthesis (March 13-22, 2026) — a 10-day hackathon judged by AI agents + humans.
Tracks: Synthesis Open Track, Venice Private Agents, Agents With Receipts — ERC-8004
Scoring criteria: Confidentiality as design requirement, agent architecture and trust design, problem legitimacy, scope and demo quality.
MIT



