# akncodes/ai-spend-audit architecture

> Architecture diagram of the GitHub repository akncodes/ai-spend-audit, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-05-12). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/akncodes/ai-spend-audit
- Repository: https://github.com/akncodes/ai-spend-audit

## Overview

1. This is a Next.js 15 App Router application organized around a single business flow: collect AI tool/spend data, analyze it, persist the audit, and expose a shareable result link. The codebase is split cleanly into route handlers, domain logic, service wrappers, and reusable UI.

2. The main user-facing surfaces are:
- `/` for the landing page
- `/scan` for entering team spend/tool usage
- `/audit/results/[slug]` for the authenticated/internal results view
- `/audit/share/[slug]` for a public share page
The `app/(audit)` route group keeps the audit experience together without changing URLs.

3. Input collection is handled by `components/forms/SpendForm.tsx` and `ToolSelector.tsx`, with `form-schemas.ts` providing validation rules. The repo uses Zod + React Hook Form, so validation happens before the request reaches the API layer.

4. The server API surface is small and purpose-built:
- `POST/GET /api/audit` for creating an audit
- `GET /api/audit/[slug]` for retrieving an existing audit by share slug
- `/api/tools` for the supported tool catalog
- `/api/leads` for capturing interested users
- `/api/health` for deployment/liveness checks
These route handlers are the boundary between the browser and the server-side domain logic.

5. `lib/audit-engine.ts` is the core business logic. It appears to be the deterministic scoring layer that decides whether a team is overpaying, calculates savings opportunities, and produces the audit findings. The presence of a dedicated unit test file for it suggests this logic is meant to stay pure and well-covered.

6. `lib/audit-service.ts` likely orchestrates the full audit lifecycle: accept normalized form data, invoke the audit engine, store the audit result, and return the slug used for sharing. This is the main application service that connects business rules to persistence and external services.

7. `lib/ai-service.ts` is the content-generation boundary. Per the README, Anthropic is used for summaries, so the audit likely combines deterministic savings analysis with an AI-written explanation or executive summary. This keeps the model-driven text separate from the scoring logic.

8. Persistence and integration are centralized:
- `lib/supabase.ts` encapsulates Supabase access
- Supabase provides the backing data store for audits and related records
- `lib/email-service.ts` handles outbound email, using Gmail/Nodemailer per the README
- `lib/tools-config.ts` provides the supported AI tools and their pricing/plan metadata
This makes the repo easy to diagram as “app → service layer → external providers.”

9. The results flow is slug-based. After an audit is created, the user is routed to a results page keyed by `slug`. The client component at `app/(audit)/results/[slug]/AuditResultsClient.tsx` suggests the page may fetch or hydrate data client-side after the initial server render. The public share page reuses the same underlying audit record but presents it without the internal scan workflow.

10. `lib/types.ts` and `lib/utils.ts` provide shared contracts and helpers used across UI, API, and services. The `components/ui` folder is a reusable primitive layer for the form and page UI, not a domain subsystem.

11. Quality gates are lightweight but focused: `__tests__/audit-engine.test.ts` validates the scoring logic, and `__tests__/form-validation.test.ts` validates the input schema behavior. CI is wired through GitHub Actions, so the main architectural risk areas are the business rules and form validation rather than infrastructure complexity.

12. Operationally, this is a serverless-style web app: all important work happens in request/response handlers or shared server modules, with no separate worker queue or background job system visible in the tree. The key external dependencies that matter architecturally are Supabase for data storage, Anthropic for summaries, and Gmail/Nodemailer for outbound email.

Main entry points: [`lib/audit-service.ts`](https://github.com/akncodes/ai-spend-audit/blob/main/lib/audit-service.ts) (Audit service), [`components/forms/SpendForm.tsx`](https://github.com/akncodes/ai-spend-audit/blob/main/components/forms/SpendForm.tsx) (Spend form), [`app/api/audit/[slug]/route.ts`](https://github.com/akncodes/ai-spend-audit/blob/main/app/api/audit/[slug]/route.ts) (Audit by slug), [`components/forms/form-schemas.ts`](https://github.com/akncodes/ai-spend-audit/blob/main/components/forms/form-schemas.ts) (Form schemas)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_app["App routes"]
  node_landing["Landing<br/>page<br/>[page.tsx]"]
  node_scan_page["Scan page<br/>[page.tsx]"]
  node_audit_results_page["Results page<br/>[page.tsx]"]
  node_audit_results_client["Results client<br/>client page"]
  node_audit_share_page["Share page<br/>[page.tsx]"]
  node_api_audit["Audit API<br/>route handler<br/>[route.ts]"]
  node_api_audit_slug["Audit by slug<br/>route handler<br/>[route.ts]"]
  node_api_tools["Tools API<br/>route handler<br/>[route.ts]"]
  node_api_leads["Leads API<br/>route handler<br/>[route.ts]"]
  node_api_health["Health API<br/>route handler<br/>[route.ts]"]
end

subgraph group_components["UI layer"]
  node_spend_form["Spend form<br/>[SpendForm.tsx]"]
  node_tool_selector["Tool selector<br/>form field<br/>[ToolSelector.tsx]"]
  node_form_schemas["Form schemas<br/>validation<br/>[form-schemas.ts]"]
end

subgraph group_lib["Core logic"]
  node_audit_engine{{"Audit engine<br/>domain engine<br/>[audit-engine.ts]"}}
  node_audit_service{{"Audit service<br/>application service<br/>[audit-service.ts]"}}
  node_ai_service{{"AI service<br/>summary generator<br/>[ai-service.ts]"}}
  node_supabase[("Supabase<br/>persistence adapter<br/>[supabase.ts]")]
  node_email_service{{"Email service<br/>notification adapter<br/>[email-service.ts]"}}
  node_tools_config["Tools config<br/>catalog<br/>[tools-config.ts]"]
  node_types_utils["Shared types<br/>contracts<br/>[types.ts]"]
end

subgraph group_tests["Tests"]
  node_audit_engine_test["Engine test<br/>unit test"]
  node_form_validation_test["Schema test<br/>unit test"]
end

subgraph group_ci["CI"]
  node_ci_workflow["CI workflow<br/>pipeline<br/>[ci.yml]"]
end

node_landing -->|"start audit"| node_scan_page
node_scan_page -->|"renders"| node_spend_form
node_spend_form -->|"uses"| node_tool_selector
node_spend_form -->|"validates"| node_form_schemas
node_tool_selector -->|"populates"| node_tools_config
node_form_schemas -->|"guards"| node_api_audit
node_api_audit -->|"delegates"| node_audit_service
node_api_audit_slug -->|"reads"| node_supabase
node_audit_service -->|"scores"| node_audit_engine
node_audit_service -->|"summarizes"| node_ai_service
node_audit_service -->|"persists"| node_supabase
node_audit_service -->|"notifies"| node_email_service
node_audit_service -->|"uses"| node_tools_config
node_audit_service -->|"shares contracts"| node_types_utils
node_api_tools -->|"serves"| node_tools_config
node_api_leads -->|"triggers"| node_email_service
node_api_health -.->|"checks"| node_supabase
node_audit_results_page -->|"hydrates"| node_audit_results_client
node_audit_results_page -->|"loads"| node_api_audit_slug
node_audit_share_page -->|"loads"| node_api_audit_slug
node_audit_engine_test -->|"verifies"| node_audit_engine
node_form_validation_test -->|"verifies"| node_form_schemas
node_ci_workflow -->|"runs"| node_audit_engine_test
node_ci_workflow -->|"runs"| node_form_validation_test

click node_landing "https://github.com/akncodes/ai-spend-audit/blob/main/app/page.tsx"
click node_scan_page "https://github.com/akncodes/ai-spend-audit/blob/main/app/scan/page.tsx"
click node_audit_results_page "https://github.com/akncodes/ai-spend-audit/blob/main/app/(audit)/results/[slug]/page.tsx"
click node_audit_results_client "https://github.com/akncodes/ai-spend-audit/blob/main/app/(audit)/results/[slug]/AuditResultsClient.tsx"
click node_audit_share_page "https://github.com/akncodes/ai-spend-audit/blob/main/app/(audit)/share/[slug]/page.tsx"
click node_api_audit "https://github.com/akncodes/ai-spend-audit/blob/main/app/api/audit/route.ts"
click node_api_audit_slug "https://github.com/akncodes/ai-spend-audit/blob/main/app/api/audit/[slug]/route.ts"
click node_api_tools "https://github.com/akncodes/ai-spend-audit/blob/main/app/api/tools/route.ts"
click node_api_leads "https://github.com/akncodes/ai-spend-audit/blob/main/app/api/leads/route.ts"
click node_api_health "https://github.com/akncodes/ai-spend-audit/blob/main/app/api/health/route.ts"
click node_spend_form "https://github.com/akncodes/ai-spend-audit/blob/main/components/forms/SpendForm.tsx"
click node_tool_selector "https://github.com/akncodes/ai-spend-audit/blob/main/components/forms/ToolSelector.tsx"
click node_form_schemas "https://github.com/akncodes/ai-spend-audit/blob/main/components/forms/form-schemas.ts"
click node_audit_engine "https://github.com/akncodes/ai-spend-audit/blob/main/lib/audit-engine.ts"
click node_audit_service "https://github.com/akncodes/ai-spend-audit/blob/main/lib/audit-service.ts"
click node_ai_service "https://github.com/akncodes/ai-spend-audit/blob/main/lib/ai-service.ts"
click node_supabase "https://github.com/akncodes/ai-spend-audit/blob/main/lib/supabase.ts"
click node_email_service "https://github.com/akncodes/ai-spend-audit/blob/main/lib/email-service.ts"
click node_tools_config "https://github.com/akncodes/ai-spend-audit/blob/main/lib/tools-config.ts"
click node_types_utils "https://github.com/akncodes/ai-spend-audit/blob/main/lib/types.ts"
click node_audit_engine_test "https://github.com/akncodes/ai-spend-audit/blob/main/__tests__/audit-engine.test.ts"
click node_form_validation_test "https://github.com/akncodes/ai-spend-audit/blob/main/__tests__/form-validation.test.ts"
click node_ci_workflow "https://github.com/akncodes/ai-spend-audit/blob/main/.github/workflows/ci.yml"

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_landing,node_scan_page,node_audit_results_page,node_audit_results_client,node_audit_share_page,node_api_audit,node_api_audit_slug,node_api_tools,node_api_leads,node_api_health toneBlue
class node_spend_form,node_tool_selector,node_form_schemas toneAmber
class node_audit_engine,node_audit_service,node_ai_service,node_supabase,node_email_service,node_tools_config,node_types_utils toneMint
class node_audit_engine_test,node_form_validation_test toneRose
class node_ci_workflow toneIndigo
```

## Components

### App routes

Next.js App Router pages and route handlers that expose the product and API.

- [Landing](https://github.com/akncodes/ai-spend-audit/blob/main/app/page.tsx): page · Top-level marketing or entry page. · `app/page.tsx`
- [Scan page](https://github.com/akncodes/ai-spend-audit/blob/main/app/scan/page.tsx): page · Entry point for collecting spend and tool usage. · `app/scan/page.tsx`
- [Results page](https://github.com/akncodes/ai-spend-audit/blob/main/app/(audit)/results/[slug]/page.tsx): page · Authenticated/internal audit results route. · `app/(audit)/results/[slug]/page.tsx`
- [Results client](https://github.com/akncodes/ai-spend-audit/blob/main/app/(audit)/results/[slug]/AuditResultsClient.tsx): client page · Client-side wrapper for the results view and hydration. · `app/(audit)/results/[slug]/AuditResultsClient.tsx`
- [Share page](https://github.com/akncodes/ai-spend-audit/blob/main/app/(audit)/share/[slug]/page.tsx): page · Public shareable audit view keyed by slug. · `app/(audit)/share/[slug]/page.tsx`
- [Audit API](https://github.com/akncodes/ai-spend-audit/blob/main/app/api/audit/route.ts): route handler · Create and retrieve audits through the server boundary. · `app/api/audit/route.ts`
- [Audit by slug](https://github.com/akncodes/ai-spend-audit/blob/main/app/api/audit/[slug]/route.ts): route handler · Fetch an existing audit record by share slug. · `app/api/audit/[slug]/route.ts`
- [Tools API](https://github.com/akncodes/ai-spend-audit/blob/main/app/api/tools/route.ts): route handler · Serves the supported tool catalog and metadata. · `app/api/tools/route.ts`
- [Leads API](https://github.com/akncodes/ai-spend-audit/blob/main/app/api/leads/route.ts): route handler · Captures interested users and inbound lead data. · `app/api/leads/route.ts`
- [Health API](https://github.com/akncodes/ai-spend-audit/blob/main/app/api/health/route.ts): route handler · Deployment and liveness probe endpoint. · `app/api/health/route.ts`

### UI layer

Reusable form and UI components used by the scan and results flows.

- [Spend form](https://github.com/akncodes/ai-spend-audit/blob/main/components/forms/SpendForm.tsx): form · Primary input form for team spend and usage data. · `components/forms/SpendForm.tsx`
- [Tool selector](https://github.com/akncodes/ai-spend-audit/blob/main/components/forms/ToolSelector.tsx): form field · Selectable tool input used by the audit form. · `components/forms/ToolSelector.tsx`
- [Form schemas](https://github.com/akncodes/ai-spend-audit/blob/main/components/forms/form-schemas.ts): validation · Zod rules and shared form validation contracts. · `components/forms/form-schemas.ts`

### Core logic

Domain services, persistence adapters, and shared utilities.

- [Audit engine](https://github.com/akncodes/ai-spend-audit/blob/main/lib/audit-engine.ts): domain engine · Deterministic scoring and savings opportunity logic. · `lib/audit-engine.ts`
- [Audit service](https://github.com/akncodes/ai-spend-audit/blob/main/lib/audit-service.ts): application service · Orchestrates normalization, scoring, persistence, and slug creation. · `lib/audit-service.ts`
- [AI service](https://github.com/akncodes/ai-spend-audit/blob/main/lib/ai-service.ts): summary generator · Produces AI-written audit summaries and explanations. · `lib/ai-service.ts`
- [Supabase](https://github.com/akncodes/ai-spend-audit/blob/main/lib/supabase.ts): persistence adapter · Database access wrapper for audits and related records. · `lib/supabase.ts`
- [Email service](https://github.com/akncodes/ai-spend-audit/blob/main/lib/email-service.ts): notification adapter · Outbound email integration for notifications or lead follow-up. · `lib/email-service.ts`
- [Tools config](https://github.com/akncodes/ai-spend-audit/blob/main/lib/tools-config.ts): catalog · Supported tools, pricing, and plan metadata. · `lib/tools-config.ts`
- [Shared types](https://github.com/akncodes/ai-spend-audit/blob/main/lib/types.ts): contracts · Common types and helpers used across the app. · `lib/types.ts`

### Tests

Focused validation of the scoring and form schema behavior.

- [Engine test](https://github.com/akncodes/ai-spend-audit/blob/main/__tests__/audit-engine.test.ts): unit test · Validates the deterministic scoring rules. · `__tests__/audit-engine.test.ts`
- [Schema test](https://github.com/akncodes/ai-spend-audit/blob/main/__tests__/form-validation.test.ts): unit test · Validates the input schema behavior. · `__tests__/form-validation.test.ts`

### CI

Repository automation for continuous integration.

- [CI workflow](https://github.com/akncodes/ai-spend-audit/blob/main/.github/workflows/ci.yml): pipeline · GitHub Actions configuration for repository checks. · `.github/workflows/ci.yml`

## Connections

- Landing → Scan page: start audit · Users move from the landing page into the scan flow.
- Scan page → Spend form: renders · The scan page composes the main audit form.
- Spend form → Tool selector: uses · The form includes a reusable tool selection control.
- Spend form → Form schemas: validates · Client-side validation is driven by shared schemas.
- Tool selector → Tools config: populates · Tool options come from the supported catalog.
- Form schemas → Audit API: guards · Validated form data is sent to the audit API.
- Audit API → Audit service: delegates · The route handler forwards normalized requests to the application service.
- Audit by slug → Supabase: reads · Slug lookups fetch stored audit records.
- Audit service → Audit engine: scores · The service invokes the deterministic scoring core.
- Audit service → AI service: summarizes · The service requests generated explanatory copy.
- Audit service → Supabase: persists · Audit results are stored for later retrieval and sharing.
- Audit service → Email service: notifies · Outbound email can be triggered as part of the audit lifecycle.
- Audit service → Tools config: uses · Supported tool metadata informs audit normalization and scoring.
- Audit service → Shared types: shares contracts · Shared types and helpers keep service boundaries consistent.
- Tools API → Tools config: serves · The tools API exposes the catalog to the UI.
- Leads API → Email service: triggers · Lead capture can hand off to email notification logic.
- Health API → Supabase: checks · Health checks may verify downstream connectivity.
- Results page → Results client: hydrates · The server page delegates interactive rendering to the client component.
- Results page → Audit by slug: loads · The results view fetches the underlying audit by slug.
- Share page → Audit by slug: loads · The public share view reuses the same slug-based audit fetch.
- Engine test → Audit engine: verifies · Unit coverage protects the scoring rules.
- Schema test → Form schemas: verifies · Unit coverage protects schema behavior.
- CI workflow → Engine test: runs · CI executes the scoring logic tests.
- CI workflow → Schema test: runs · CI executes the form validation tests.
