# alexmattson/roost architecture

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

- Interactive diagram: https://gitdiagram.com/alexmattson/roost
- Repository: https://github.com/alexmattson/roost
- Video tour (about a minute): https://gitdiagram.com/alexmattson/roost/video

## Overview

Roost is a browser-only analytics and reconciliation app for Sandpiper inventory and Quail point-of-sale. The user connects the services, loads their records, and gets a Home briefing, date-scoped analysis, inventory/POS lookup, and a full-range Sync view; findings can lead to edits or recording sales in Sandpiper. The graph follows the documented workflow and sampled app/data-provider wiring. Several page and backend implementations were not sampled, so their internal call links are intentionally limited.

Main entry points: [`src/store/data.jsx`](https://github.com/alexmattson/roost/blob/main/src/store/data.jsx) (Shared data state), [`src/App.jsx`](https://github.com/alexmattson/roost/blob/main/src/App.jsx) (App routing), [`src/pages/Analyze.jsx`](https://github.com/alexmattson/roost/blob/main/src/pages/Analyze.jsx) (Analyze views), [`src/lib/webbackend.js`](https://github.com/alexmattson/roost/blob/main/src/lib/webbackend.js) (Web backend adapter)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_experience["App experience"]
  node_app["App routing<br/>[App.jsx]"]
  node_login["Connection gate<br/>[LoginGate.jsx]"]
  node_home["Home briefing<br/>[Home.jsx]"]
  node_analyze["Analyze views<br/>[Analyze.jsx]"]
  node_inventory["Inventory records<br/>[Inventory.jsx]"]
  node_pos["POS records<br/>[PosSales.jsx]"]
  node_sync["Sync findings<br/>[Sync.jsx]"]
  node_stock["Stock management<br/>[AddStock.jsx]"]
  node_tags["Print tags<br/>[PrintTags.jsx]"]
  node_channels["Channel management<br/>[ManageChannels.jsx]"]
end

subgraph group_data["Data preparation"]
  node_state["Shared data state<br/>[data.jsx]"]
  node_nav["Mode and range state<br/>[nav.jsx]"]
  node_normalization["Normalize records<br/>[analytics.js]"]
  node_quailnorm["Normalize POS sales<br/>[quail.js]"]
  node_channelsdata["Channel attribution<br/>[channel.js]"]
  node_ledger["Sales ledger<br/>[ledger.js]"]
  node_venue["Resolve venues<br/>[resolve.js]"]
end

subgraph group_analysis["Analysis and review"]
  node_reconcile["Reconciliation engine<br/>[reconcile.js]"]
  node_metrics["Analytics engine<br/>[analytics.js]"]
end

subgraph group_integrations["External systems"]
  node_backend["Web backend adapter<br/>[webbackend.js]"]
  node_sandpiper["Sandpiper"]
  node_quail["Quail POS"]
  node_browser[("Browser storage")]
end

node_owner(("Booth owner"))

node_owner -->|"connects"| node_login
node_login -->|"sets credentials"| node_state
node_owner -->|"uses"| node_app
node_app -->|"loads and refreshes"| node_state
node_app -->|"routes to"| node_home
node_app -->|"routes to"| node_analyze
node_app -->|"routes to"| node_inventory
node_app -->|"routes to"| node_pos
node_app -->|"routes to"| node_sync
node_state -->|"requests data"| node_backend
node_backend -->|"fetches and updates"| node_sandpiper
node_backend -->|"fetches sales"| node_quail
node_backend -->|"caches records"| node_browser
node_state -->|"normalizes inventory"| node_normalization
node_state -->|"normalizes sales"| node_quailnorm
node_state -->|"builds attribution"| node_channelsdata
node_state -->|"resolves venue context"| node_venue
node_state -->|"builds ledger"| node_ledger
node_state -->|"computes findings"| node_reconcile
node_home -->|"reads briefing data"| node_state
node_analyze -->|"computes metrics"| node_metrics
node_analyze -->|"uses sales ledger"| node_ledger
node_analyze -->|"uses register times"| node_quailnorm
node_inventory -->|"reads and edits records"| node_state
node_pos -->|"reads sales"| node_state
node_sync -->|"reads findings"| node_state
node_sync -->|"reviews discrepancies"| node_reconcile
node_stock -->|"adds stock"| node_state
node_tags -->|"requests barcodes"| node_state
node_channels -->|"manages channels"| node_state
node_app -->|"selects views"| node_nav
node_nav -->|"sets range and tab"| node_analyze

click node_app "https://github.com/alexmattson/roost/blob/main/src/App.jsx"
click node_login "https://github.com/alexmattson/roost/blob/main/src/pages/LoginGate.jsx"
click node_home "https://github.com/alexmattson/roost/blob/main/src/pages/Home.jsx"
click node_analyze "https://github.com/alexmattson/roost/blob/main/src/pages/Analyze.jsx"
click node_inventory "https://github.com/alexmattson/roost/blob/main/src/pages/Inventory.jsx"
click node_pos "https://github.com/alexmattson/roost/blob/main/src/pages/PosSales.jsx"
click node_sync "https://github.com/alexmattson/roost/blob/main/src/pages/Sync.jsx"
click node_stock "https://github.com/alexmattson/roost/blob/main/src/pages/AddStock.jsx"
click node_tags "https://github.com/alexmattson/roost/blob/main/src/pages/PrintTags.jsx"
click node_channels "https://github.com/alexmattson/roost/blob/main/src/pages/ManageChannels.jsx"
click node_state "https://github.com/alexmattson/roost/blob/main/src/store/data.jsx"
click node_nav "https://github.com/alexmattson/roost/blob/main/src/store/nav.jsx"
click node_normalization "https://github.com/alexmattson/roost/blob/main/src/lib/analytics.js"
click node_quailnorm "https://github.com/alexmattson/roost/blob/main/src/lib/quail.js"
click node_channelsdata "https://github.com/alexmattson/roost/blob/main/src/lib/channel.js"
click node_ledger "https://github.com/alexmattson/roost/blob/main/src/lib/ledger.js"
click node_venue "https://github.com/alexmattson/roost/blob/main/src/lib/resolve.js"
click node_reconcile "https://github.com/alexmattson/roost/blob/main/src/lib/reconcile.js"
click node_metrics "https://github.com/alexmattson/roost/blob/main/src/lib/analytics.js"
click node_backend "https://github.com/alexmattson/roost/blob/main/src/lib/webbackend.js"

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_app,node_login,node_home,node_analyze,node_inventory,node_pos,node_sync,node_stock,node_tags,node_channels toneBlue
class node_state,node_nav,node_normalization,node_quailnorm,node_channelsdata,node_ledger,node_venue toneAmber
class node_reconcile,node_metrics toneMint
class node_backend,node_sandpiper,node_quail,node_browser toneRose
class node_owner toneIndigo
```

## Components

### App experience

- [App routing](https://github.com/alexmattson/roost/blob/main/src/App.jsx): `src/App.jsx`
- [Connection gate](https://github.com/alexmattson/roost/blob/main/src/pages/LoginGate.jsx): `src/pages/LoginGate.jsx`
- [Home briefing](https://github.com/alexmattson/roost/blob/main/src/pages/Home.jsx): `src/pages/Home.jsx`
- [Analyze views](https://github.com/alexmattson/roost/blob/main/src/pages/Analyze.jsx): `src/pages/Analyze.jsx`
- [Inventory records](https://github.com/alexmattson/roost/blob/main/src/pages/Inventory.jsx): `src/pages/Inventory.jsx`
- [POS records](https://github.com/alexmattson/roost/blob/main/src/pages/PosSales.jsx): `src/pages/PosSales.jsx`
- [Sync findings](https://github.com/alexmattson/roost/blob/main/src/pages/Sync.jsx): `src/pages/Sync.jsx`
- [Stock management](https://github.com/alexmattson/roost/blob/main/src/pages/AddStock.jsx): `src/pages/AddStock.jsx`
- [Print tags](https://github.com/alexmattson/roost/blob/main/src/pages/PrintTags.jsx): `src/pages/PrintTags.jsx`
- [Channel management](https://github.com/alexmattson/roost/blob/main/src/pages/ManageChannels.jsx): `src/pages/ManageChannels.jsx`

### Data preparation

- [Shared data state](https://github.com/alexmattson/roost/blob/main/src/store/data.jsx): `src/store/data.jsx`
- [Mode and range state](https://github.com/alexmattson/roost/blob/main/src/store/nav.jsx): `src/store/nav.jsx`
- [Normalize records](https://github.com/alexmattson/roost/blob/main/src/lib/analytics.js): `src/lib/analytics.js`
- [Normalize POS sales](https://github.com/alexmattson/roost/blob/main/src/lib/quail.js): `src/lib/quail.js`
- [Channel attribution](https://github.com/alexmattson/roost/blob/main/src/lib/channel.js): `src/lib/channel.js`
- [Sales ledger](https://github.com/alexmattson/roost/blob/main/src/lib/ledger.js): `src/lib/ledger.js`
- [Resolve venues](https://github.com/alexmattson/roost/blob/main/src/lib/resolve.js): `src/lib/resolve.js`

### Analysis and review

- [Reconciliation engine](https://github.com/alexmattson/roost/blob/main/src/lib/reconcile.js): `src/lib/reconcile.js`
- [Analytics engine](https://github.com/alexmattson/roost/blob/main/src/lib/analytics.js): `src/lib/analytics.js`

### External systems

- [Web backend adapter](https://github.com/alexmattson/roost/blob/main/src/lib/webbackend.js): `src/lib/webbackend.js`
- **Sandpiper**
- **Quail POS**
- **Browser storage**

### Other components

- **Booth owner**

## Connections

- Booth owner → Connection gate: connects
- Connection gate → Shared data state: sets credentials
- Booth owner → App routing: uses
- App routing → Shared data state: loads and refreshes
- App routing → Home briefing: routes to
- App routing → Analyze views: routes to
- App routing → Inventory records: routes to
- App routing → POS records: routes to
- App routing → Sync findings: routes to
- Shared data state → Web backend adapter: requests data
- Web backend adapter → Sandpiper: fetches and updates
- Web backend adapter → Quail POS: fetches sales
- Web backend adapter → Browser storage: caches records
- Shared data state → Normalize records: normalizes inventory
- Shared data state → Normalize POS sales: normalizes sales
- Shared data state → Channel attribution: builds attribution
- Shared data state → Resolve venues: resolves venue context
- Shared data state → Sales ledger: builds ledger
- Shared data state → Reconciliation engine: computes findings
- Home briefing → Shared data state: reads briefing data
- Analyze views → Analytics engine: computes metrics
- Analyze views → Sales ledger: uses sales ledger
- Analyze views → Normalize POS sales: uses register times
- Inventory records → Shared data state: reads and edits records
- POS records → Shared data state: reads sales
- Sync findings → Shared data state: reads findings
- Sync findings → Reconciliation engine: reviews discrepancies
- Stock management → Shared data state: adds stock
- Print tags → Shared data state: requests barcodes
- Channel management → Shared data state: manages channels
- App routing → Mode and range state: selects views
- Mode and range state → Analyze views: sets range and tab
