TQ

Gridlink App

Overview

Gridlink is an internal dashboard for Gridlink Research, a digital marketing company serving medical practices. It tracks clients, leads, cases (patient pipeline), campaigns, and integrates with external platforms like GoHighLevel.

Architecture

┌──────────────┐     ┌──────────────┐     ┌──────────┐

│ Browser │────▶│ Nginx │────▶│ Next.js │

│ │ │ (port 80) │ │ (port │

│ │ │ │──┐ │ 3000) │

└──────────────┘ └──────────────┘ │ └──────────┘

┌──────────┐ ┌──────────┐

│ Flask │────▶│ SQLite │

│ API │ │ DB │

│ (port │ └──────────┘

│ 5000) │

└──────────┘

  • Frontend: Next.js 16 + Tailwind CSS + ApexCharts
  • Backend: Flask (Python) + Gunicorn
  • Database: SQLite with WAL mode (/opt/gridlink/data/gridlink.db)
  • Reverse Proxy: Nginx — routes /api/* to Flask, everything else to Next.js
  • Host: 10.222.222.88 (Ubuntu 22.04)
  • Tech Stack

    LayerTechnologyVersion
    Frontend FrameworkNext.js (App Router)16.2.6
    UI StylingTailwind CSS4.x
    ChartsApexCharts / react-apexcharts3.x
    Backend FrameworkFlask3.1.1
    WSGI ServerGunicorn23.0.0
    DatabaseSQLite3.x (WAL mode)
    RuntimeNode.js 20 / Python 3.10
    Process Managersystemd
    Reverse ProxyNginx1.18

    Directory Structure

    /opt/gridlink/
    

    ├── frontend/ # Next.js app

    │ ├── src/

    │ │ ├── app/ # Pages (App Router)

    │ │ ├── components/# React components

    │ │ └── lib/ # API client, utilities

    │ └── .env.local # Environment config

    ├── backend/ # Flask API

    │ ├── api.py # Route handlers

    │ ├── models.py # Database models + helpers

    │ └── venv/ # Python virtualenv

    └── data/

    └── gridlink.db # SQLite database

    Services

    ServiceUnit FilePortDescription
    gridlink-api/etc/systemd/system/gridlink-api.service5000Flask API via Gunicorn
    gridlink-web/etc/systemd/system/gridlink-web.service3000Next.js frontend
    nginxsystem default80Reverse proxy

    Common Commands

    # Check status
    

    systemctl status gridlink-api gridlink-web

    Restart after code changes

    systemctl restart gridlink-api # Backend changes

    cd /opt/gridlink/frontend && npm run build && systemctl restart gridlink-web # Frontend changes

    View logs

    journalctl -u gridlink-api -f

    journalctl -u gridlink-web -f

    Data Model

    The app uses a relational data model centered around the medical marketing workflow:

  • Clients — Medical practices (each maps to a GHL sub-account/location)
  • Leads — Potential patients generated by marketing campaigns
  • Cases — Patient pipeline entries created when leads convert to consultations
  • Campaigns — Marketing campaigns run for clients
  • Activity Log — Audit trail of all data changes
  • See the Data Dictionary for full schema details.

    Component System

    Gridlink uses a component architecture for external integrations. Each component:

  • Gets a settings page under Settings > Components
  • Has configurable sync frequency
  • Syncs data into local mirror tables
  • Shows sync status and error states
  • Currently planned components:

  • GoHighLevel — CRM data sync (contacts, opportunities, appointments, etc.)
  • Encompass — Distribution platform (credentials pending)
  • Deployment

    The app runs on a dedicated VM (10.222.222.88). To deploy changes:

  • Copy updated files to /opt/gridlink/
  • For backend: systemctl restart gridlink-api
  • For frontend: cd /opt/gridlink/frontend && npm run build && systemctl restart gridlink-web
  • No containerization currently — systemd manages the processes directly.

    Conventions

  • Read-only sync: External data is synced into local mirror tables. Updates go through the source platform, not through Gridlink.
  • Dark mode default: The UI uses a dark theme matching the TailAdmin style.
  • API prefix: All backend routes start with /api/.
  • Auto-updating docs: The Data Dictionary introspects the database at runtime — no manual schema documentation needed.
  • Last updated: 5/26/2026