Skip to content

Architecture

This document describes the system architecture of OSGEO-Inject.

System Overview

graph TB
    subgraph "Client Browser"
        A[OSGeo Project Page]
        B[osgeo-inject.js]
        C[Badge UI]
    end

    subgraph "OSGEO-Inject Server"
        D[Nginx]
        E[Static Assets]
        F[Content JSON]
    end

    subgraph "Analytics"
        G[Matomo]
    end

    A -->|loads| B
    B -->|fetches| D
    D -->|serves| E
    D -->|serves| F
    B -->|renders| C
    B -->|tracks| G

Component Architecture

Client Components

classDiagram
    class OSGeoInject {
        +init()
        +config: Config
        +version: string
    }

    class Config {
        +baseUrl: string
        +matomoUrl: string
        +matomoSiteId: number
        +announcementEndpoint: string
        +cacheDuration: number
    }

    class Badge {
        +render()
        +toggle()
        +updateTheme()
    }

    class Analytics {
        +trackPageView()
    }

    OSGeoInject --> Config
    OSGeoInject --> Badge
    OSGeoInject --> Analytics

Server Components

C4Container
    title OSGEO-Inject Server Architecture

    Container(nginx, "Nginx", "Web Server", "Serves static assets with CORS")
    Container(matomo, "Matomo", "Analytics", "Tracks page views")
    ContainerDb(content, "Content", "JSON Files", "Announcements and history")
    ContainerDb(mariadb, "MariaDB", "Database", "Matomo data")

    Rel(nginx, content, "Reads")
    Rel(matomo, mariadb, "Stores data")

Data Flow

Page Load Sequence

sequenceDiagram
    participant Browser
    participant Page as OSGeo Project
    participant Inject as OSGEO-Inject Server
    participant Matomo

    Browser->>Page: Request page
    Page->>Browser: HTML response
    Browser->>Inject: Load osgeo-inject.js
    Inject->>Browser: JavaScript file
    Browser->>Inject: Load osgeo-inject.css
    Inject->>Browser: CSS file
    Browser->>Browser: Initialize badge
    Browser->>Inject: Fetch announcement.json
    Inject->>Browser: JSON response
    Browser->>Browser: Render badge
    Browser->>Matomo: Track page view (pixel)

Announcement Update Flow

sequenceDiagram
    participant Admin
    participant Script as update-announcement.sh
    participant Server as OSGEO-Inject Server
    participant Clients

    Admin->>Script: Create announcement
    Script->>Script: Archive current
    Script->>Script: Generate new JSON
    Script->>Server: Deploy via rsync
    Server->>Server: Update content files
    Note over Clients: Cache expires (1 hour)
    Clients->>Server: Fetch new announcement
    Server->>Clients: Updated JSON

File Structure

osgeo-inject/
├── src/
│   ├── js/
│   │   └── osgeo-inject.js      # Main JavaScript
│   ├── css/
│   │   └── osgeo-inject.css     # Styles
│   ├── content/
│   │   ├── announcement.json    # Current announcement
│   │   └── history.json         # Announcement history
│   └── images/
│       └── osgeo-logo.svg       # OSGeo logo
├── nginx/
│   └── nginx.conf               # Server configuration
├── nixos/
│   ├── module.nix               # NixOS module
│   └── vm-configuration.nix     # VM testbed
├── scripts/
│   ├── onboard-site.sh          # Site onboarding
│   ├── update-announcement.sh   # Announcement management
│   ├── backup.sh                # Backup workflow
│   └── restore.sh               # Restore workflow
├── docs/                        # MkDocs documentation
└── test/                        # Test files

Security Model

graph TB
    subgraph "Security Layers"
        A[HTTPS Only]
        B[CORS Whitelist]
        C[CSP Headers]
        D[Rate Limiting]
        E[Input Sanitization]
    end

    F[Request] --> A
    A --> B
    B --> C
    C --> D
    D --> E
    E --> G[Response]

CORS Strategy

Only whitelisted OSGeo project domains can load the resources:

map $http_origin $cors_origin {
    default "";
    "~^https?://.*\.osgeo\.org$" $http_origin;
    "~^https?://.*\.qgis\.org$" $http_origin;
    # ... other OSGeo projects
}

Content Security Policy

Content-Security-Policy: default-src 'self';
                         script-src 'self';
                         style-src 'self' 'unsafe-inline';
                         img-src 'self' data:;
                         connect-src 'self'

Performance Optimizations

Caching Strategy

Resource Cache Duration Strategy
JavaScript 1 hour must-revalidate
CSS 1 hour must-revalidate
Images 7 days immutable
Announcements 15 minutes must-revalidate

Asset Size Budget

Asset Budget Minified
JavaScript < 10KB
CSS < 5KB
Images < 50KB each Optimized
Total < 15KB

Client-Side Caching

// localStorage caching
const cacheKey = "osgeo-inject-announcement";
const cacheTimeKey = "osgeo-inject-announcement-time";
const cacheDuration = 3600000; // 1 hour

Monitoring & Analytics

graph LR
    A[Page View] -->|pixel| B[Matomo]
    B --> C[Dashboard]
    C --> D[Reports]

    subgraph "Tracked Data"
        E[Hostname]
        F[Path]
        G[Timestamp]
    end

Deployment Architecture

graph TB
    subgraph "Development"
        A[Local Dev]
        B[Nix Flake]
    end

    subgraph "CI/CD"
        C[GitHub Actions]
        D[Pre-commit Hooks]
    end

    subgraph "Production"
        E[NixOS Server]
        F[Let's Encrypt]
        G[Matomo Instance]
    end

    A --> B
    B --> C
    C --> E
    D --> C
    E --> F
    E --> G