Skip to Content

Last Updated: 4/7/2026


System Architecture & Project Structure

โ€œWhere Did They Go?โ€ is built as a modern web application using Vue 3 for the frontend and Node.js/Express for the backend. This article explains the system architecture using the C4 model (Context, Container, Component) and describes the projectโ€™s directory structure.

C4 Model Overview

The C4 model provides a hierarchical view of software architecture, starting from the high-level system context and drilling down into containers and components. This project uses three levels of C4 diagrams to document its architecture.


System Context Diagram

system-context-diagram (1).png

What This Diagram Shows

The System Context diagram shows โ€œWhere Did They Go?โ€ as a single system and its relationship to external actors. The application serves two primary user groups:

Students โ€” K-12 students exploring Kansas history, geography, and demographic changes as part of their coursework. Students interact with the map interface to visualize population trends and infrastructure development.

Teachers โ€” Educators who use the application as a teaching tool in social studies, history, or geography lessons. Teachers guide students through the interface and use the visualizations to support curriculum objectives.

Key architectural decision: The system operates as a standalone web application with no external API dependencies. All data is pre-processed and served as static JSON/GeoJSON files, ensuring the application works reliably without requiring third-party services or API keys.


Container Diagram

container-diagram (1).png

What This Diagram Shows

The Container diagram breaks the system into three major containers:

UI (Vue 3 Single-Page Application) โ€” The frontend runs entirely in the userโ€™s web browser. Built with Vue 3, it provides an interactive SVG-based map using D3.js for geographic projections and data visualization. The UI communicates with the backend only to fetch static data files.

Backend (Express Server) โ€” A lightweight Node.js/Express server that serves the initial HTML page and provides static file access to JSON/GeoJSON datasets. The backend does NOT implement REST API endpoints or dynamic data processingโ€”it functions purely as a file server with compression middleware.

File Storage (JSON/GeoJSON Files) โ€” Pre-processed geographic and demographic data stored as static files in the server/public/ directory. Files are organized by state (currently only Kansas) and data type (geojson/, json/, csv/). The frontend fetches these files directly using standard HTTP requests.

Important note: A PostgreSQL database container exists in the development environment but is NOT currently used by the application logic. The database is reserved for future features but does not participate in the current data flow.

Ports:

  • Client (development): http://localhost:5173
  • Server: http://localhost:3000

Component Diagram

component-diagram (1).png

What This Diagram Shows

The Component diagram zooms into the Vue 3 UI container to show its internal structure:

App.vue (Timeline & Playback Controller) โ€” The root component manages the timeline slider and play/pause button. It maintains the current year as reactive state and passes this value to BaseMap. The play button automatically advances the timeline every 3.5 seconds when active.

BaseMap.vue (Map Container & Registration API) โ€” The central orchestrator component that:

  • Renders the SVG container for all map visualizations
  • Provides a registration API (via Vueโ€™s provide/inject) that data components use to register themselves
  • Manages the filter panel UI, showing/hiding filters based on zoom level
  • Tracks map state (zoom level, current year, selected county)
  • Invokes hooks to notify data components of state changes
  • Handles county click events to transition between State View and County View

Data Components (9 Layers) โ€” Each data layer is implemented as a separate Vue component:

  • BorderData.vue โ€” County boundaries and optional population heat map
  • CityData.vue โ€” City locations, names, and population labels
  • RailroadData.vue โ€” Railroad lines with construction year filtering
  • InterstateData.vue โ€” Interstate highways with opening year filtering
  • RiverData.vue โ€” River and waterway lines
  • LakeData.vue โ€” Lake and reservoir polygons
  • SchoolData.vue โ€” School building locations with hover tooltips
  • HealthcareData.vue โ€” Healthcare facility symbols with hover tooltips
  • TractData.vue โ€” Census tract boundaries

Each data component:

  1. Injects the registerKey to access BaseMapโ€™s registration API
  2. Calls registerComponent(label, options) to register itself and receive hooks
  3. Subscribes to hooks (onYearChange, onZoomChange, onCountyTransition) to react to map state changes
  4. Fetches its data using fetchGeojson() or fetchJson() utility functions
  5. Renders its visualization to the SVG using D3.js

Project Structure

The repository is organized into distinct directories for frontend, backend, testing, documentation, and development environment configuration:

client/

The Vue 3 frontend application. Key subdirectories:

  • **src/components/** โ€” Vue components, including BaseMap.vue and all nine data layer components
  • **src/enums/** โ€” TypeScript-style enums (MapZoomLevel, HookType, GroupType) that define constants used across components
  • **src/utility/** โ€” Utility functions including fetchers.js (data loading), RegisterKey.js (registration API types), and interpolators (color calculations)
  • **src/d3/** โ€” D3.js helper functions for transitions and animations
  • **src/__tests__/** โ€” Frontend unit tests

server/

The Node.js/Express backend. Key subdirectories:

  • **public/** โ€” Static files served to the frontend, organized by state (e.g., public/kansas/geojson/, public/kansas/json/)
  • **routes/** โ€” Express route handlers (currently only renders the index page)
  • **app.js** โ€” Express application configuration with static file serving and compression middleware
  • **bin/** โ€” Server startup script

.devcontainer/

Docker Dev Container configuration for consistent development environments:

  • **devcontainer.json** โ€” VS Code Dev Container settings
  • **docker-compose.yml** โ€” Multi-container setup (client, server, database)
  • **Dockerfile** โ€” Container image definition
  • **postCreateCommand.sh** โ€” Runs after container creation to install dependencies
  • **postAttachCommand.sh** โ€” Runs when attaching to the container to start services

documentation/

Project documentation and design artifacts:

  • **c4-diagrams/** โ€” SVG files for System Context, Container, and Component diagrams
  • **Requirements and Design Ideas.docx** โ€” Original project requirements document

tests/

Testing resources and test data files for both frontend and backend.


Data Flow

  1. User opens the application in their browser
  2. Express server sends the initial HTML page
  3. Vue 3 application loads and mounts
  4. BaseMap.vue renders and provides the registration API
  5. Each data component registers itself and subscribes to hooks
  6. Data components fetch their JSON/GeoJSON files from the server
  7. Components render their data to the SVG using D3.js
  8. User interactions (timeline changes, county clicks, filter toggles) trigger hook callbacks
  9. Components update their visualizations in response to hook invocations

No REST API: The backend never processes requests for dynamic data. All data transformations and filtering happen in the browser using JavaScript.


Technology Stack

Frontend:

  • Vue 3 (Composition API with <script setup>)
  • D3.js (geographic projections, SVG rendering)
  • JavaScript (no TypeScript, but JSDoc comments provide type hints)

Backend:

  • Node.js
  • Express (with compression middleware)
  • Static file serving only

Development:

  • Docker Dev Containers
  • VS Code (recommended IDE)

Data Formats:

  • GeoJSON (geographic features with properties)
  • JSON (tabular data like city populations)

Whatโ€™s Next

ย