EVE Frontier is a social game—alliances coordinate territory control, corporations run joint mining operations, and explorer squads scout wormhole chains together. But spatial coordination is hard when everyone has their own mental map.
Tribe Marks solve this by letting groups share lightweight tactical annotations directly on the star map—no standing up servers, no complex permissions, no user accounts. Just pick a tribe name, start marking systems, and your squadmates see the same notes.
This post explains how Tribe Marks work, the privacy/concurrency safeguards we built, and how EVE Frontier communities are using them for real-time tactical coordination.
The Problem: Coordination Without Shared Context
Scenario 1: Explorer Squad Wormhole Chain Mapping
Your 5-person explorer squad is scanning a J-space wormhole chain. You discover:
- System A: 3 data sites (valuable)
 - System B: Hostile PvP corp active
 - System C: Connects back to k-space (exit route)
 
You want to share this intel instantly with your squad, but:
- Discord messages get buried in chat
 - Spreadsheets require manual updates and don't show spatial context
 - Voice comms are ephemeral—new members miss the context
 
Result: Squad members duplicate scanning (wasting time) or miss critical intel (walking into danger).
Scenario 2: Alliance Territory Markers
Your alliance controls 12 systems. You want to mark:
- System X: Primary staging (keep stocked)
 - System Y: Mining hub (need haulers)
 - System Z: Border patrol (watch for hostiles)
 
Without shared markers, every pilot maintains their own notes—inconsistent, out-of-date, and incomplete.
The Solution: Tribe Marks
Tribe Marks are shared tactical annotations on the star map. Each mark consists of:
- System: Which star system is marked
 - Title: Short label (≤60 chars) like "Safe mining" or "Hostile spotted"
 - Note: Longer description (≤160 chars) with details
 - Color: Visual indicator (8 preset colors + custom hex)
 - Verified: Optional checkmark indicating "confirmed by multiple sources"
 
Marks are grouped by tribe—any EF-Map user can create or join a tribe just by choosing a tribe name. No signup, no permissions, no admin overhead.
How It Works: Cloudflare KV + Optimistic Concurrency
Backend: Serverless Key-Value Storage
Tribe marks are stored in Cloudflare Workers KV—a globally distributed key-value store.
Key format:
tribe:<tribe_name>:marks
Value: JSON document with all marks for that tribe:
{
  "version": 1,
  "tribe": "wormhole-scouts",
  "marks": [
    {
      "id": "mark_1729000001",
      "system_id": "30000142",
      "title": "Safe mining",
      "note": "Veldspar belt A - no hostiles",
      "color": "#00ff00",
      "verified": true
    },
    {
      "id": "mark_1729000002",
      "system_id": "30000144",
      "title": "PvP danger",
      "note": "Hostile corp active - avoid",
      "color": "#ff0000",
      "verified": false
    }
  ],
  "etag": "abc123def456"
}
ETag: Version identifier for optimistic concurrency control (explained below).
Fetching Marks
When you join a tribe, the web app fetches its marks:
async function fetchTribeMarks(tribeName: string): Promise<TribeMark[]> {
  const response = await fetch(`/api/tribe-marks?tribe=${encodeURIComponent(tribeName)}`);
  
  if (!response.ok) return [];
  
  const data = await response.json();
  return data.marks;
}
The Cloudflare Worker queries KV:
export default {
  async fetch(req, env) {
    const url = new URL(req.url);
    const tribeName = url.searchParams.get('tribe');
    
    const key = `tribe:${tribeName}:marks`;
    const doc = await env.TRIBE_MARKS.get(key, { type: 'json' });
    
    if (!doc) {
      return new Response(JSON.stringify({ marks: [] }), {
        headers: { 'Content-Type': 'application/json' }
      });
    }
    
    return new Response(JSON.stringify(doc), {
      headers: { 
        'Content-Type': 'application/json',
        'ETag': doc.etag
      }
    });
  }
}
Marks appear on the map as colored icons next to system names.
Adding/Editing Marks: Optimistic Concurrency
When you add or edit a mark, the app uses optimistic concurrency control to prevent conflicts:
- Fetch current tribe document (includes 
etag) - Make local changes (add/edit mark)
 - Send mutation request with 
If-Match:header - Server checks if 
etagmatches current version 
   - Match: Apply changes, generate new etag, save
   - Mismatch: Reject with 409 Conflict, return latest etag
- On conflict, client auto-retries with latest data
 
Code (client):
async function addTribeMark(tribeName: string, mark: TribeMark): Promise<void> {
  const currentDoc = await fetchTribeMarks(tribeName);
  const currentEtag = currentDoc.etag;
  
  const newDoc = {
    ...currentDoc,
    marks: [...currentDoc.marks, mark]
  };
  
  const response = await fetch('/api/tribe-marks/mutate', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'If-Match': currentEtag
    },
    body: JSON.stringify({
      tribe: tribeName,
      ops: [{ type: 'add', mark }]
    })
  });
  
  if (response.status === 409) {
    // Conflict - retry with latest data
    return addTribeMark(tribeName, mark);
  }
  
  if (!response.ok) throw new Error('Failed to add mark');
}
Code (server):
async function handleMutation(req, env) {
  const { tribe, ops } = await req.json();
  const ifMatch = req.headers.get('If-Match');
  
  const key = `tribe:${tribe}:marks`;
  const currentDoc = await env.TRIBE_MARKS.get(key, { type: 'json' }) || { marks: [], etag: '' };
  
  // Check ETag
  if (ifMatch && ifMatch !== currentDoc.etag) {
    return new Response(JSON.stringify({ error: 'etag_mismatch', latest: currentDoc }), {
      status: 409,
      headers: { 'Content-Type': 'application/json', 'ETag': currentDoc.etag }
    });
  }
  
  // Apply mutations
  let marks = currentDoc.marks;
  for (const op of ops) {
    if (op.type === 'add') {
      marks.push(op.mark);
    } else if (op.type === 'edit') {
      marks = marks.map(m => m.id === op.mark.id ? op.mark : m);
    } else if (op.type === 'delete') {
      marks = marks.filter(m => m.id !== op.markId);
    }
  }
  
  // Generate new ETag
  const newEtag = generateEtag(marks);
  const newDoc = { version: 1, tribe, marks, etag: newEtag };
  
  await env.TRIBE_MARKS.put(key, JSON.stringify(newDoc));
  
  return new Response(JSON.stringify(newDoc), {
    headers: { 'Content-Type': 'application/json', 'ETag': newEtag }
  });
}
Why optimistic concurrency?
Without it, if two pilots add marks simultaneously:
Pilot A: Fetches tribe doc (10 marks)
Pilot B: Fetches tribe doc (10 marks)
Pilot A: Adds mark #11, saves (11 marks)
Pilot B: Adds mark #12, saves (11 marks) ← Pilot A's mark is LOST!
With ETag concurrency:
Pilot A: Fetches (etag: "v1")
Pilot B: Fetches (etag: "v1")
Pilot A: Adds mark #11, saves with If-Match: "v1" → SUCCESS (etag: "v2")
Pilot B: Adds mark #12, saves with If-Match: "v1" → CONFLICT (etag is now "v2")
Pilot B: Retries with latest doc (includes mark #11), adds mark #12 → SUCCESS
Both marks are preserved.
Tribe Name as Access Key
No user accounts. You join a tribe just by typing its name:
Enter tribe name: wormhole-scouts
Anyone who knows the name can read and write marks. This is intentional—tribes are lightweight coordination tools, not secure vaults.
Security model:
- Public-ish: Treat tribe names like "unlisted document links"—share them only with trusted groups
 - No delete protection: Anyone in the tribe can delete marks (use "verified" flags for important ones)
 - Rate limits: 10 mutations/minute per IP to prevent abuse
 
Why no authentication?
Adding auth (login, roles, permissions) would:
- Require user accounts (friction)
 - Require account linking (more friction)
 - Add permission management UI (complexity)
 
For ad-hoc tactical coordination, the trade-off isn't worth it. Tribes are ephemeral by design.
Content Sanitization
All mark text is sanitized to prevent XSS and keep annotations signal-focused:
Blocked Content
- Control characters: Newlines, tabs, ANSI codes (stripped)
 - Over-length: Titles >60 chars, notes >160 chars (truncated)
 - HTTP(S) links: Replaced with 
[link]placeholder (prevents phishing) - Discord invite links: Replaced with 
[invite](prevents spam) 
Example:
Input:  "Join our Discord: https://discord.gg/abc123"
Output: "Join our Discord: [link]"
Why block links?
Tribes are for tactical notes, not advertising. If you need to share a link, use a separate communication channel (Discord, forum post, etc.).
Allowed Content
- Plain text: Letters, numbers, punctuation
 - Symbols: 
!@#$%&*()-_=+[]{}|;:'",.<>?/ - Emoji: ✅ (rendered correctly)
 
Example valid marks:
Title: "⚠️ PvP Zone"
Note:  "Hostile corp spotted @ 14:30 UTC. 3 battleships patrolling."
Limits and Quotas
To keep tribes lightweight and prevent abuse:
- Max marks per tribe: 300
 - Max folders per tribe: 100
 - Title length: ≤60 characters
 - Note length: ≤160 characters
 - Mutations per minute: 10 per IP
 
If you hit limits, consider splitting into multiple tribes (e.g., tribe-alpha-mining, tribe-alpha-pvp).
Verified Flag: Crowd-Sourced Intel
Any tribe member can toggle the verified flag on a mark:
✓ Safe mining (verified by 3 pilots)
✗ Hostile spotted (unverified report)
Use case: An explorer reports "Hostile spotted" (unverified). Two squadmates jump to the system, confirm the hostile is still there, and mark it verified. Now everyone trusts the intel.
Implementation:
The verified flag is just a boolean—no vote counting (yet). Future versions might track "verified by X pilots" counts.
Color Coding: Visual Shortcuts
Marks support 8 preset colors + custom hex:
- 🔴 Red: Danger, hostiles
 - 🟢 Green: Safe, profitable
 - 🟡 Yellow: Caution, unverified
 - 🔵 Blue: Info, notes
 - 🟣 Purple: Exploration targets
 - 🟠 Orange: Mining sites
 - ⚪ White: Neutral
 - ⚫ Gray: Deprecated/old
 
Custom hex: For tribe-specific color schemes (e.g., alliance branding).
Rendering: Marks appear as colored dots next to system names on the map. Hover to see title/note.
Folders: Organizing Marks
Tribes can create folders to group related marks:
📁 Mining Sites
  ├─ System A: Veldspar belt
  ├─ System B: Scordite rich
  └─ System C: Gas cloud
📁 PvP Hotspots
  ├─ System X: Border patrol
  └─ System Y: Chokepoint
📁 Wormhole Exits
  └─ System Z: K-space connection
Limit: 100 folders per tribe.
Use case: An alliance creates folders for each region they control, organizing marks by territory.
Privacy and Transparency
No PII Stored
Marks contain only:
- System ID
 - Title (sanitized text)
 - Note (sanitized text)
 - Color
 - Verified flag
 
Never stored:
- Who created the mark
 - When it was created
 - User IP addresses
 - Session IDs
 
Public Read Access
Anyone can read any tribe's marks if they know the tribe name:
GET /api/tribe-marks?tribe=wormhole-scouts
Returns all marks (no auth required).
Why public?
This enables:
- Cross-tribe intel sharing ("Check tribe X's marks for this region")
 - Transparency (no hidden data)
 - Ease of use (zero friction to view)
 
If you need private notes, use personal browser bookmarks or a separate tool.
Use Cases
Use Case 1: Wormhole Explorer Squad
Tribe: wh-scouts-oct25
Marks:
- System A: "Safe mining" (green)
 - System B: "Hostile PvP corp" (red, verified)
 - System C: "Exit to k-space" (blue)
 
Workflow:
- Scout jumps to System A, scans down sites
 - Creates mark: "Safe mining - 3 data sites"
 - Squadmates see mark instantly on their maps
 - Everyone avoids System B (red flag)
 - When done, everyone uses System C exit
 
Result: Zero duplicate scanning, instant intel propagation.
Use Case 2: Alliance Territory Management
Tribe: alliance-alpha-territory
Marks:
- System X: "Staging hub - keep stocked" (blue)
 - System Y: "Mining ops - haulers needed" (orange)
 - System Z: "Border patrol - watch for reds" (red, verified)
 
Workflow:
- FCs create marks for strategic systems
 - New members join tribe, see all marks
 - Haulers prioritize orange-marked systems
 - Patrols focus on red-marked borders
 
Result: Coordinated operations without complex spreadsheets.
Use Case 3: Event Organizers
Tribe: pvp-tournament-oct25
Marks:
- Arena System: "Tournament arena - no mining" (yellow)
 - Staging Systems (3): "Participant staging" (green)
 - Banned Systems (5): "Off-limits" (red)
 
Workflow:
- Organizers create marks before event
 - Participants join tribe week before
 - Everyone knows where to stage, where to avoid
 - Day of event, marks guide participants to arena
 
Result: Smooth event execution, clear boundaries.
Troubleshooting
"My mark isn't appearing for others"
Cause: Network lag or cache staleness.
Fix: Wait 30 seconds (marks propagate globally within 60s). If still missing, ask squadmate to refresh the page.
"Someone deleted my mark"
Cause: Any tribe member can delete marks.
Fix: Use verified marks for critical intel (less likely to be deleted). For permanent notes, consider a separate tool (Discord pins, Google Doc, etc.).
"I can't add more marks"
Cause: Tribe hit the 300-mark limit.
Fix: Delete old/outdated marks, or create a new tribe (tribe-name-v2).
Future Enhancements
Planned Features
- Mark history: See who created/edited marks (opt-in per tribe)
 - Vote-based verification: "3 pilots verified this" instead of single boolean
 - Expiration dates: Auto-delete marks after X days (for temporary intel)
 - Mark templates: Pre-fill common mark types ("Mining site", "PvP danger", etc.)
 
Community Requests
- Private tribes: Require password to join (balances ease-of-use vs security)
 - Mark comments: Thread of replies under each mark (for discussion)
 - Export/import: Backup tribe marks as JSON file
 
Content Policy
Tribe marks must comply with our content policy:
- Allowed: Tactical notes, system status, resource info, warnings
 - Prohibited: Harassment, spam, phishing, illegal content, PII
 
Report violations: email [email protected] with tribe name and mark excerpt.
Enforcement: Offending marks are removed within 72 hours. Repeated violations may lead to tribe suspension.
Full policy: https://ef-map.com/POLICY.md
Getting Started (2 Minutes)
Step 1: Pick a Tribe Name
Choose a unique, memorable name:
wormhole-scouts
alliance-alpha-mining
pvp-fleet-bravo
Share it with your squadmates via Discord/voice.
Step 2: Join the Tribe
In EF-Map, open the Tribe Marks panel → Enter tribe name → "Join Tribe".
Step 3: Add Your First Mark
- Right-click a system on the map
 - Select "Add Tribe Mark"
 - Fill in title, note, color
 - Save
 
Squadmates see the mark within 30 seconds.
Step 4: Verify Important Intel
For critical marks (e.g., "Hostile spotted"), toggle the verified flag after confirming the info.
You're now coordinating!
Related Posts
- Route Sharing: Building a URL Shortener for Spatial Navigation - Similar serverless architecture for route sharing
 - Privacy-First Analytics: Learning Without Tracking - How we track feature usage without violating privacy
 - Cloudflare KV Optimization: Reducing Costs by 93% - How we optimized KV usage for marks and shares
 
Tribe Marks bring real-time tactical coordination to EVE Frontier without the overhead of complex permission systems or user accounts—just pick a name, start marking, and fly together!