ProjectsJuly 13, 2026

Traceo — Offline-First Geofenced Field Operations & Route Management Platform

image
Core Mission: Bridge the field-to-office gap by enforcing physical proof-of-presence, eliminating ghost visits, and providing uninterrupted offline reliability.
Managing mobile sales representatives, medical delegates (délégués médicaux), and field inspectors across distributed geographic territories is inherently prone to operational blind spots. Companies face substantial revenue leakage and lost productivity when field validation relies on trust-based paper logs, phone check-ins, or unverifiable chat messages. Traceo is an enterprise-grade field operations platform engineered to solve these challenges. Built with a NestJS + Prisma + PostgreSQL backend and a React + RTK Query + Tailwind CSS frontend, Traceo provides:
  • A real-time supervisory web portal for route scheduling, point-of-interest sequencing, and live monitoring.
  • An offline-first Progressive Web App (PWA) for field reps that enforces physical proximity (default 30-meter geofence) before unlocking visit check-ins.
  • A local IndexedDB queue with idempotent background sync that guarantees zero data loss in low-connectivity or dead-zone environments.
100%Verified check-in authenticity via hardware GPS
0Visits lost in remote offline territories
< 30mConfigurable geofence radius threshold
3xFaster route creation and stop reordering
Traceo Field Operations Platform Overview
Without cryptographic or hardware-verified location tracking, representatives can mark client visits from cafés, transit, or home. Supervisors have no verifiable mechanism to validate whether a pharmaceutical clinic, retail outlet, or industrial site was actually visited. Field teams operate on complex cyclical schedules (e.g., visiting specific pharmacies every Tuesday and Thursday). Manual spreadsheet-based planning creates overlapping itineraries, duplicate visits, and unassigned territories when representatives change. In regional distribution corridors and rural areas, 3G/4G connectivity drops constantly. Traditional SaaS platforms fail, throw timeout errors, and lose form data, forcing reps to resort back to manual paper reporting. Without system-level concurrency locks, representatives could be assigned multiple conflicting routes simultaneously, creating data contamination and skewed performance metrics.
Traceo was architected around three non-negotiable principles:
  1. Hardware-Enforced Proximity: The client UI physically disables check-in submission until GPS telemetry confirms the agent is within the geofence radius. The backend repeats the exact mathematical verification upon ingestion.
  2. Offline-First by Design: The mobile PWA treats network connectivity as an opportunistic enhancement, not a requirement. All reads and writes target an IndexedDB local store first.
  3. Deterministic Multi-Tenant Governance: Hierarchical RBAC (SUPERADMINADMINREP) enforcing strict resource quotas (maxReps, maxPoints, maxRoutes) and isolation.
Traceo Field Agent & Geofencing System Architecture
The backend is built with NestJS, leveraging a modular architecture, strict dependency injection, and Prisma ORM for type-safe database queries. Every check-in undergoes dual verification. The backend recalculates great-circle distance between the point's registered coordinates and the device's check-in coordinates using the Haversine formula:
Typescript
// backend/src/visits/visits.service.ts
getDistanceInMeters(lat1: number, lon1: number, lat2: number, lon2: number): number {
  const R = 6371e3 // Earth's mean radius in meters
  const phi1 = (lat1 * Math.PI) / 180
  const phi2 = (lat2 * Math.PI) / 180
  const deltaPhi = ((lat2 - lat1) * Math.PI) / 180
  const deltaLambda = ((lon2 - lon1) * Math.PI) / 180

  const a =
    Math.sin(deltaPhi / 2) * Math.sin(deltaPhi / 2) +
    Math.cos(phi1) * Math.cos(phi2) * Math.sin(deltaLambda / 2) * Math.sin(deltaLambda / 2)
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))

  return R * c // distance in meters
}
When a representative's device reconnects, the PWA flushes queued visits in a single batch request (POST /visits/sync). The ingestion pipeline performs 7 security and business validation steps per item:
  1. IDOR Prevention: Ensures REP users can only submit logs where repId === currentUser.id.
  2. Idempotency Guarantee: Checks idempotencyKey (UUIDv4) to prevent duplicate processing on network retries.
  3. Route Point Verification: Confirms the target route stop exists in the database.
  4. Ownership Verification: Validates that the active route is currently assigned to the submitting representative.
  5. Temporal Date Resolution: Verifies that the visit occurred on a scheduled date according to weekly recurrence rules (isRouteScheduledOnDate).
  6. Server-Side Geofence Audit: Recomputes distance against settings.geofenceRadius. If distance exceeds the threshold, the visit is flagged as REJECTED with an explicit reason string.
  7. Daily Limit Guard: Enforces that only one successful SYNCED check-in is logged per point per day.
Typescript
// Core sync processing step in visits.service.ts
const distance = this.getDistanceInMeters(
  v.checkInLatitude,
  v.checkInLongitude,
  rp.point.latitude,
  rp.point.longitude
)

let syncStatus: SyncStatus = SyncStatus.SYNCED
let rejectReason = null

if (distance > geofenceRadius) {
  syncStatus = SyncStatus.REJECTED
  rejectReason = `La distance de check-in (${Math.round(distance)}m) dépasse le rayon autorisé de ${geofenceRadius}m.`
}
Prisma
// Core Domain Models in backend/prisma/schema.prisma
model User {
  id           String   @id @default(uuid())
  name         String
  email        String   @unique
  passwordHash String
  role         Role     // SUPERADMIN | ADMIN | REP
  active       Boolean  @default(true)
  maxReps      Int      @default(5)
  maxPoints    Int      @default(20)
  maxRoutes    Int      @default(30)
  
  routes       Route[]  @relation("RepRoutes")
  visits       Visit[]  @relation("RepVisits")
}

model Point {
  id          String       @id @default(uuid())
  name        String
  address     String?
  latitude    Float
  longitude   Float
  routePoints RoutePoint[]
}

model Route {
  id             String         @id @default(uuid())
  repId          String
  rep            User           @relation("RepRoutes", fields: [repId], references: [id])
  startDate      DateTime
  endDate        DateTime?
  recurrenceType RecurrenceType // NONE | WEEKLY
  recurrenceDays String[]       // e.g. ["MONDAY", "WEDNESDAY"]
  status         RouteStatus    @default(ACTIVE)
  routePoints    RoutePoint[]
}

model Visit {
  id                String     @id @default(uuid())
  routePointId      String
  routePoint        RoutePoint @relation(fields: [routePointId], references: [id], onDelete: Cascade)
  repId             String
  rep               User       @relation("RepVisits", fields: [repId], references: [id])
  occurrenceDate    String     // YYYY-MM-DD
  deviceTimestamp   DateTime
  serverTimestamp   DateTime   @default(now())
  checkInLatitude   Float
  checkInLongitude  Float
  distanceFromPoint Float
  note              String?
  syncStatus        SyncStatus @default(PENDING) // PENDING | SYNCED | REJECTED
  rejectReason      String?
  idempotencyKey    String     @unique

  @@unique([routePointId, occurrenceDate, idempotencyKey])
}
The frontend codebase is split into two specialized experiences: Designed specifically for high-stress, on-the-move usage on mobile browsers and standalone installed PWAs:
  • Continuous GPS Watcher: Real-time polling of browser Geolocation API with accuracy indicators (accuracy < 15m).
  • Dynamic Proximity HUD: Live distance calculation showing meters remaining until within range.
  • Visual Radar Animations: Pulse indicators highlighting active target points on the interactive Leaflet map.
  • Modal Check-In Bottom Sheet: Fluid bottom sheets for rapid note entry and instant local submission.
Traceo Mobile Field PWA - Proximity Radar & Offline Check-In Sheet
Typescript
// frontend/src/lib/indexedDb.ts — Offline Persistence Engine
const DB_NAME = "traceo_pwa_db"
const STORE_NAME = "pending_visits"

export async function addVisitToQueue(visit: QueuedVisit): Promise<void> {
  const db = await openDb()
  return new Promise((resolve, reject) => {
    const tx = db.transaction(STORE_NAME, "readwrite")
    const store = tx.objectStore(STORE_NAME)
    const req = store.put(visit)
    req.onsuccess = () => resolve()
    req.onerror = () => reject(req.error)
  })
}
  • Live Activity Feed: Real-time stream of incoming check-ins, reporting agent identity, client site, timestamp, and registered check-in distance.
  • Route Sequencer: Interactive ordering of client stops with immediate sequence re-indexing and rep assignment.
  • Interactive Geospatial Dashboard: Leaflet map visualizer rendering agent paths, point clusters, and visit status color codes (Green = Visited, Grey = Pending, Red = Rejected).
Traceo Supervisor Operations Portal - Live Map & Real-Time Check-In Stream
Route Sequencer & Cyclical Assignment
Traceo Recurring Route Planner & Agent Assignment
Geospatial Point-of-Interest Directory
Traceo Geospatial Point-of-Interest & Geofencing Database
Traceo uses an intentional, high-contrast visual system tailored for outdoor screen legibility and institutional trust.
  • Brand Teal (#155E63 / 185 65% 24%): Primary brand identity, communicating precision and enterprise reliability.
  • Verified Emerald (#1F9D55 / 146 67% 37%): Clear visual confirmation for authenticated visits within geofence range.
  • Alert Crimson (#C0362C / 4 63% 46%): Instant feedback for distance breaches or route discrepancies.
  • Surface Neutrals (#F5F7F5 / #15211E): Low eye-strain background and ink contrast adhering to WCAG AAA standards.
Field Agent Quota & Role Administration
Traceo Multi-Tenant Agent & Quota Management
Standardized Field Workflow Guides
Traceo Operational Flow & Field Force Guidelines
Operational Metric
Before Traceo (Manual / Spreadsheets)
With Traceo Platform
Visit Verification0% verifiable (verbal/paper reports)100% hardware-verified GPS check-ins
Data Loss in Dead ZonesFrequent report loss & missing notes0% data loss (IndexedDB auto-replay)
Route Scheduling Time2 to 3 hours per week per manager< 15 minutes with visual drag-drop
Dispute ResolutionSubjective arguments over billing/hoursObjective audit log with exact meters & timestamps
Mobile PWA Load TimeN/A< 800ms cached startup via Service Worker
  1. Dual-Layer Geospatial Defense: Client-side geofencing is essential for user experience (giving immediate feedback), but server-side recalculation is the only way to guarantee tamper-proof security.
  2. Idempotency is Mandatory for Offline Sync: Offline queues will experience network drops mid-request. Assigning immutable client-side UUIDs (idempotencyKey) ensures network retries never duplicate transactional data.
  3. Prisma Lean Selects Prevent Mobile Over-Fetching: Mobile field agents require lean payloads. Explicit Prisma selects trimmed unnecessary payload weight by over 70%, accelerating offline synchronization over degraded mobile networks.
Case study written and engineered for portfolio presentation. Built with NestJS, Prisma, PostgreSQL, React 18, RTK Query, and Leaflet.

Related projects

Vet Tiaret — Bilingual Clinical Intake, Triage & Scheduling Platform

Vet Tiaret — Bilingual Clinical Intake, Triage & Scheduling Platform

Engineering an end-to-end veterinary clinical intake, triage, and scheduling ecosystem with real-time symptom classification, reducing staff call load by 65% and cutting appointment no-shows by 40%.
Luma — Calm Client Operations Assistant & Temporal Memory System

Luma — Calm Client Operations Assistant & Temporal Memory System

Designing and engineering a calm client operations system that turns natural conversations into evolving attention, eliminating mental load for solopreneurs.
NordCode — High-Trust Technical Identity & Studio Platform

NordCode — High-Trust Technical Identity & Studio Platform

Designing and engineering a high-trust, engineering-grade web presence for a software solutions studio with precision design tokens, 0-runtime animations, and blueprint aesthetics.
Zambo Tattoo — Studio Landing Page & Artist Showcase

Zambo Tattoo — Studio Landing Page & Artist Showcase

Designing and building a bold, high-contrast digital showcase and landing page for Zambo Tattoo studio with an interactive artwork gallery, artist spotlight, and seamless client booking flow.
CRYOJET — B2B Industrial Growth Platform & Digital Transformation

CRYOJET — B2B Industrial Growth Platform & Digital Transformation

Designing and engineering an enterprise B2B platform for Algeria's leading cryogenic industrial cleaning contractor—demystifying dry-ice technology, eliminating sales cycle latency with instant WhatsApp routing, and capturing enterprise leads across 58 wilayas.