Skip to content
Follow-up System — platform screenshot

Platform · Level Up Training Center · 2026

Follow-up System

Task accountability platform with verified closure, SLA tracking and WhatsApp follow-ups.

Work-accountability platform: 11-state task workflow enforced in Postgres, progress-vs-time check-ins, escalation up the manager chain, WhatsApp follow-ups and SHA-256 closure certificates.

My role
Product, architecture and full-stack build
Stack
TypeScript · Fastify · React 19 · PostgreSQL · Drizzle · WhatsApp Cloud API · Docker
Microsoft-ecosystem fit

▸ Responsible AI: audit trail, separation of duties

▸ Accessibility: keyboard-first, EN/AR RTL

▸ Teams Adaptive Card notifications

11

States in the task workflow

SHA-256

Hash-chained audit log

EN / AR

Full RTL interface

Live demo

Interactive demo

Staff and manager views with sample data: progress against time, check-ins, escalation, more-time approvals and automations.

Follow-up System — main screen
Follow-up System — mobile

Source · Level Up Follow-up System website (sign-in) and the follow-up board from the public demo with sample data

01 — Problem

Task completion relied on self-reporting, overdue work was identified late, and reminders were sent manually.

02 — Approach

  1. 01

    Closure engine: 11-state machine enforced server-side, Definition of Done per task type, no one reviews their own work.

  2. 02

    Progress vs time on every task; WhatsApp check-ins at 50% and 75%; ask-for-more-time with manager approval.

  3. 03

    Transactional outbox + SKIP LOCKED dispatcher: each reminder fires exactly once, even across crashes.

  4. 04

    Closed tasks issue a canonical-JSON + SHA-256 certificate; the audit log is append-only and hash-chained.

03 — Architecture

System architecture

  1. S01

    React 19 web

  2. S02

    Fastify API · RBAC

  3. S03

    State machine

  4. S04

    Postgres triggers

  5. S05

    Outbox dispatcher

  6. S06

    WhatsApp

04 — Engineering notes

Reminders that cannot silently fail

Notifications are written in the same transaction as the change that caused them. A worker then claims due deliveries, and SKIP LOCKED lets several workers run without ever sending the same message twice.

ts
// apps/api/src/notifications/dispatcher.ts (production)
const claimed = await db.execute(sql`
  UPDATE notification_deliveries d
     SET status = 'sending', attempts = d.attempts + 1, updated_at = now()
   WHERE d.id IN (
     SELECT id FROM notification_deliveries
      WHERE status IN ('pending', 'failed') AND next_attempt_at <= now()
      ORDER BY next_attempt_at
      LIMIT ${batch}
      FOR UPDATE SKIP LOCKED)
   RETURNING d.id, d.notification_id, d.channel, d.attempts`);

Failures back off exponentially. After the last attempt a delivery is marked dead and shown in the admin delivery log with a retry button.

Closure you can verify

ts
// apps/api/src/lib/crypto.ts (production)
/** Deterministic JSON (sorted keys) so hashes are reproducible by auditors. */
export function canonicalJson(value: unknown): string {
  if (value === null || typeof value !== 'object') return JSON.stringify(value ?? null);
  if (Array.isArray(value)) return `[${value.map(canonicalJson).join(',')}]`;
  const entries = Object.entries(value as Record<string, unknown>)
    .filter(([, v]) => v !== undefined)
    .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
  return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson(v)}`).join(',')}}`;
}

Each certificate stores the SHA-256 of that canonical payload, covering owner, verifier, checklist and evidence file hashes. A public endpoint re-hashes it on demand.

Follow-up System — detail screen 1
Follow-up System — detail screen 2

Outcome

Managers see at-risk work before deadlines, and every completed task has an auditable record of ownership and verification.

Next project

NCLDP Website

NCLDP Website — platform screenshot