# rapabru/sag.calculator architecture

> Architecture diagram of the GitHub repository rapabru/sag.calculator, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-26). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/rapabru/sag.calculator
- Repository: https://github.com/rapabru/sag.calculator

## Overview

SAG Calculator is a browser-based slackline rigging calculator. Users adjust a rig and person configuration, calculate static sag and clearance plus leash and backup-fall outcomes, then inspect the plotted profile and results. The app also supports saved local presets, change-based history with optional Supabase account sync, multilingual UI, guided onboarding, and image/PDF-oriented export. The graph follows documented capability boundaries; omitted source excerpts mean some UI wiring is represented only where explicit evidence exists.

Main entry points: [`src/App.tsx`](https://github.com/rapabru/sag.calculator/blob/main/src/App.tsx) (App shell), [`src/physics/index.ts`](https://github.com/rapabru/sag.calculator/blob/main/src/physics/index.ts) (Calculation coordinator), [`src/history/storage.ts`](https://github.com/rapabru/sag.calculator/blob/main/src/history/storage.ts) (History storage), [`src/components/SagChart.tsx`](https://github.com/rapabru/sag.calculator/blob/main/src/components/SagChart.tsx) (Sag chart)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_interface["Calculator interface"]
  node_entry["App shell<br/>[App.tsx]"]
  node_controls["Rig controls<br/>[App.tsx]"]
  node_results["Result panels<br/>[ResultsPanel.tsx]"]
  node_chart["Sag chart<br/>[SagChart.tsx]"]
  node_geometry["Chart geometry<br/>[chartGeometry.ts]"]
  node_export["Export tools<br/>[exportImage.ts]"]
  node_guide["Welcome guide<br/>[GuideTour.tsx]"]
  node_historyui["History panel<br/>[HistoryPanel.tsx]"]
end

subgraph group_models["Rig physics"]
  node_calculator["Calculation coordinator<br/>[index.ts]"]
  node_static["Static sag solver<br/>[staticSolver.ts]"]
  node_fall["Leash fall solver<br/>[fallSolver.ts]"]
  node_backup["Backup fall solver"]
  node_tree["Tree anchor model"]
end

subgraph group_persistence["Saved data"]
  node_history["History storage<br/>[storage.ts]"]
  node_localstore[("Browser storage<br/>[storage.ts]")]
  node_presets["Preset storage<br/>[storage.ts]"]
end

subgraph group_services["Account and language"]
  node_authui["Account button<br/>[AccountButton.tsx]"]
  node_session["Session state<br/>[useSession.ts]"]
  node_supabase["Supabase service<br/>[supabase.ts]"]
  node_remotehistory[("Remote history<br/>[storage.ts]")]
  node_language["Language context"]
  node_locales["Locale bundles<br/>[en.json]"]
end

node_user(("Slackline user"))

node_user -->|"opens and configures"| node_entry
node_entry -->|"renders"| node_controls
node_entry -->|"calculates"| node_calculator
node_controls -->|"supplies rig input"| node_calculator
node_calculator -->|"solves static sag"| node_static
node_calculator -->|"solves leash fall"| node_fall
node_calculator -->|"solves backup fall"| node_backup
node_calculator -->|"adjusts tree effects"| node_tree
node_entry -->|"renders results"| node_results
node_entry -->|"renders profile"| node_chart
node_chart -->|"computes chart scale"| node_geometry
node_entry -->|"exports calculation"| node_export
node_entry -->|"shows onboarding"| node_guide
node_entry -->|"loads and records"| node_history
node_historyui -->|"selects history entry"| node_entry
node_entry -->|"renders history"| node_historyui
node_history -->|"reads and writes"| node_localstore
node_entry -->|"loads and saves presets"| node_presets
node_entry -->|"renders account action"| node_authui
node_authui -->|"uses session actions"| node_session
node_session -.->|"authenticates"| node_supabase
node_history -.->|"requests sync client"| node_supabase
node_history -.->|"syncs history rows"| node_remotehistory
node_entry -->|"uses translations"| node_language
node_language -->|"selects bundle"| node_locales

click node_entry "https://github.com/rapabru/sag.calculator/blob/main/src/App.tsx"
click node_controls "https://github.com/rapabru/sag.calculator/blob/main/src/App.tsx"
click node_results "https://github.com/rapabru/sag.calculator/blob/main/src/components/ResultsPanel.tsx"
click node_chart "https://github.com/rapabru/sag.calculator/blob/main/src/components/SagChart.tsx"
click node_geometry "https://github.com/rapabru/sag.calculator/blob/main/src/components/chartGeometry.ts"
click node_export "https://github.com/rapabru/sag.calculator/blob/main/src/components/exportImage.ts"
click node_guide "https://github.com/rapabru/sag.calculator/blob/main/src/components/GuideTour.tsx"
click node_calculator "https://github.com/rapabru/sag.calculator/blob/main/src/physics/index.ts"
click node_static "https://github.com/rapabru/sag.calculator/blob/main/src/physics/staticSolver.ts"
click node_fall "https://github.com/rapabru/sag.calculator/blob/main/src/physics/fallSolver.ts"
click node_backup "https://github.com/rapabru/sag.calculator/blob/main/src/physics/backupFallSolver.ts"
click node_tree "https://github.com/rapabru/sag.calculator/blob/main/src/physics/treeAnchorSolver.ts"
click node_historyui "https://github.com/rapabru/sag.calculator/blob/main/src/components/HistoryPanel.tsx"
click node_history "https://github.com/rapabru/sag.calculator/blob/main/src/history/storage.ts"
click node_localstore "https://github.com/rapabru/sag.calculator/blob/main/src/history/storage.ts"
click node_presets "https://github.com/rapabru/sag.calculator/blob/main/src/presets/storage.ts"
click node_authui "https://github.com/rapabru/sag.calculator/blob/main/src/components/AccountButton.tsx"
click node_session "https://github.com/rapabru/sag.calculator/blob/main/src/auth/useSession.ts"
click node_supabase "https://github.com/rapabru/sag.calculator/blob/main/src/auth/supabase.ts"
click node_remotehistory "https://github.com/rapabru/sag.calculator/blob/main/src/history/storage.ts"
click node_language "https://github.com/rapabru/sag.calculator/blob/main/src/i18n/LanguageContext.tsx"
click node_locales "https://github.com/rapabru/sag.calculator/blob/main/src/i18n/locales/en.json"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_entry,node_controls,node_results,node_chart,node_geometry,node_export,node_guide,node_historyui,node_user toneBlue
class node_calculator,node_static,node_fall,node_backup,node_tree toneAmber
class node_history,node_localstore,node_presets toneMint
class node_authui,node_session,node_supabase,node_remotehistory,node_language,node_locales toneRose
```

## Components

### Calculator interface

- [App shell](https://github.com/rapabru/sag.calculator/blob/main/src/App.tsx): `src/App.tsx`
- [Rig controls](https://github.com/rapabru/sag.calculator/blob/main/src/App.tsx): `src/App.tsx`
- [Result panels](https://github.com/rapabru/sag.calculator/blob/main/src/components/ResultsPanel.tsx): `src/components/ResultsPanel.tsx`
- [Sag chart](https://github.com/rapabru/sag.calculator/blob/main/src/components/SagChart.tsx): `src/components/SagChart.tsx`
- [Chart geometry](https://github.com/rapabru/sag.calculator/blob/main/src/components/chartGeometry.ts): `src/components/chartGeometry.ts`
- [Export tools](https://github.com/rapabru/sag.calculator/blob/main/src/components/exportImage.ts): `src/components/exportImage.ts`
- [Welcome guide](https://github.com/rapabru/sag.calculator/blob/main/src/components/GuideTour.tsx): `src/components/GuideTour.tsx`
- [History panel](https://github.com/rapabru/sag.calculator/blob/main/src/components/HistoryPanel.tsx): `src/components/HistoryPanel.tsx`

### Rig physics

- [Calculation coordinator](https://github.com/rapabru/sag.calculator/blob/main/src/physics/index.ts): `src/physics/index.ts`
- [Static sag solver](https://github.com/rapabru/sag.calculator/blob/main/src/physics/staticSolver.ts): `src/physics/staticSolver.ts`
- [Leash fall solver](https://github.com/rapabru/sag.calculator/blob/main/src/physics/fallSolver.ts): `src/physics/fallSolver.ts`
- [Backup fall solver](https://github.com/rapabru/sag.calculator/blob/main/src/physics/backupFallSolver.ts): `src/physics/backupFallSolver.ts`
- [Tree anchor model](https://github.com/rapabru/sag.calculator/blob/main/src/physics/treeAnchorSolver.ts): `src/physics/treeAnchorSolver.ts`

### Saved data

- [History storage](https://github.com/rapabru/sag.calculator/blob/main/src/history/storage.ts): `src/history/storage.ts`
- [Browser storage](https://github.com/rapabru/sag.calculator/blob/main/src/history/storage.ts): `src/history/storage.ts`
- [Preset storage](https://github.com/rapabru/sag.calculator/blob/main/src/presets/storage.ts): `src/presets/storage.ts`

### Account and language

- [Account button](https://github.com/rapabru/sag.calculator/blob/main/src/components/AccountButton.tsx): `src/components/AccountButton.tsx`
- [Session state](https://github.com/rapabru/sag.calculator/blob/main/src/auth/useSession.ts): `src/auth/useSession.ts`
- [Supabase service](https://github.com/rapabru/sag.calculator/blob/main/src/auth/supabase.ts): `src/auth/supabase.ts`
- [Remote history](https://github.com/rapabru/sag.calculator/blob/main/src/history/storage.ts): `src/history/storage.ts`
- [Language context](https://github.com/rapabru/sag.calculator/blob/main/src/i18n/LanguageContext.tsx): `src/i18n/LanguageContext.tsx`
- [Locale bundles](https://github.com/rapabru/sag.calculator/blob/main/src/i18n/locales/en.json): `src/i18n/locales/en.json`

### Other components

- **Slackline user**

## Connections

- Slackline user → App shell: opens and configures
- App shell → Rig controls: renders
- App shell → Calculation coordinator: calculates
- Rig controls → Calculation coordinator: supplies rig input
- Calculation coordinator → Static sag solver: solves static sag
- Calculation coordinator → Leash fall solver: solves leash fall
- Calculation coordinator → Backup fall solver: solves backup fall
- Calculation coordinator → Tree anchor model: adjusts tree effects
- App shell → Result panels: renders results
- App shell → Sag chart: renders profile
- Sag chart → Chart geometry: computes chart scale
- App shell → Export tools: exports calculation
- App shell → Welcome guide: shows onboarding
- App shell → History storage: loads and records
- History panel → App shell: selects history entry
- App shell → History panel: renders history
- History storage → Browser storage: reads and writes
- App shell → Preset storage: loads and saves presets
- App shell → Account button: renders account action
- Account button → Session state: uses session actions
- Session state → Supabase service: authenticates
- History storage → Supabase service: requests sync client
- History storage → Remote history: syncs history rows
- App shell → Language context: uses translations
- Language context → Locale bundles: selects bundle
