Back to Experiments
EXP.01 React Coming Soon

Dive & Operations Log

Digital logbook for tracking dives, equipment maintenance, and operations.

Interactive

Live Demo

Demo Coming Soon

The live demo for this experiment is not yet available.

Context

The Problem

In the Navy, on yachts, and in the oil fields, I filled out paper logbooks daily. Every dive, every equipment check, every maintenance task — logged by hand. These records are critical for safety audits, insurance, and operational continuity. But paper logs get lost, damaged, or become unreadable. Finding a specific entry from six months ago means flipping through hundreds of pages.

Digital alternatives exist, but they're often bloated enterprise software designed for large organizations, not individual operators or small crews. I wanted to build something that captures the simplicity of a paper logbook with the power of digital search and organization.

Background

The Connection

Twenty years of writing in logbooks gave me strong opinions about what matters:

  • Speed of entry — You're logging between tasks, often in challenging conditions. Every extra click costs time and attention.
  • Offline-first — Yachts at sea, rigs in the Gulf, remote dive sites — connectivity is a luxury, not a given.
  • Structured but flexible — Some entries need specific fields (dive depth, equipment serial numbers), others need freeform notes.
  • Immutable audit trail — Regulatory bodies care about log integrity. Entries should be timestamped and append-only.

Architecture

The Approach

I chose React for this experiment to demonstrate proficiency with the most widely-used frontend framework. The architecture decisions reflect the real constraints:

Offline-First with Sync Using IndexedDB for local storage with a sync queue for when connectivity returns. All operations work offline; sync is opportunistic.

Form-First Design The UI is optimized for rapid data entry. Tab navigation, smart defaults, and templates for common entry types.

Type-Safe Throughout TypeScript interfaces define every entity. The same types are shared between frontend and API.

Code

Technical Deep Dive

The core challenge was handling offline sync without data loss or conflicts. Here's the approach:

Each entry gets a client-generated UUID and timestamp. When online, entries sync to the server in order. Conflicts are rare because entries are append-only — you don't edit, you add amendments.

The sync queue handles network failures gracefully, retrying with exponential backoff. A background service worker manages the queue even when the app isn't open.

typescript
// Sync queue manager
interface SyncQueueItem {
  id: string;
  timestamp: number;
  operation: 'create' | 'update';
  entity: 'log_entry' | 'equipment' | 'dive';
  payload: unknown;
  retryCount: number;
}

async function processSyncQueue() {
  const queue = await db.syncQueue.toArray();

  for (const item of queue) {
    try {
      await syncToServer(item);
      await db.syncQueue.delete(item.id);
    } catch (error) {
      if (item.retryCount < MAX_RETRIES) {
        await db.syncQueue.update(item.id, {
          retryCount: item.retryCount + 1
        });
      }
    }
  }
}

Offline sync queue with retry logic

Retrospective

What I Learned

What worked well:

  • IndexedDB performance exceeded expectations even with thousands of entries
  • TypeScript caught numerous bugs during development that would have been runtime errors
  • The offline-first approach forced cleaner architecture decisions
  • What I'd change:

  • Would explore using CRDTs for true conflict-free replication
  • The form validation logic grew complex — a form library would have helped
  • Should have implemented export functionality earlier (PDF, CSV)
  • Trade-offs accepted:

  • Prioritized entry speed over rich formatting — plain text with minimal markdown
  • No real-time collaboration — this is a personal/crew tool, not enterprise software
  • Technologies

    The Stack

    React UI framework
    TypeScript Type safety
    Vite Build tool
    Dexie.js IndexedDB wrapper
    TanStack Query Server state
    Tailwind CSS Styling