- Python 48.8%
- TypeScript 45.2%
- HTML 2.2%
- CSS 2%
- PLpgSQL 1%
- Other 0.7%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| .dev/2026-06-10-planner-order-workspace | ||
| .github/workflows | ||
| backend | ||
| docs | ||
| frontend | ||
| plan/design/swatch | ||
| scripts | ||
| .env.example | ||
| .gitignore | ||
| .pre-commit-config.yaml | ||
| AGENTS.md | ||
| CONTEXT.md | ||
| docker-compose.yml | ||
| Dockerfile.backend | ||
| Dockerfile.frontend | ||
| nginx.conf | ||
| pyproject.toml | ||
| README.md | ||
| render.yaml | ||
| start-local.sh | ||
| uv.lock | ||
Alloy
Work request intake and estimate management for Inno Metalworks. Friendly interface for field operators (iPad wizard) and planners (desktop queue/estimate builder) that integrates with ProShop ERP via GraphQL API.
Quick Start
Local ports & full procedure: docs/runbook-local.md
(Postgres host 5433, API 8000, Vite 5173 — do not guess.)
Rebuild stance: docs/rebuild-constitution.md · Agents: AGENTS.md
Finish contract: docs/plans/2026-08-01-finish-roadmap.md · Discipline: docs/engineering-discipline.md · Handoff: docs/plans/HANDOFF.md
# Backend
uv sync --extra dev
# .env: ALLOY_DATABASE_URL=...@localhost:5433/alloy (see .env.example)
(cd backend && uv run alembic upgrade head)
uv run uvicorn backend.app.main:create_app --factory --reload # :8000
# Frontend
cd frontend && npm install && npm run dev # :5173
# Or use Docker
docker compose up # Postgres host :5433, backend :8000, frontend :8080
Stack
Backend: FastAPI, SQLAlchemy (async), Alembic, Pydantic, PostgreSQL
Frontend: React 18, TypeScript, Vite, shadcn/ui, Tailwind, TanStack Query, Zustand
Auth: Local JWT (HS256, bcrypt passwords), Row-Level Security (RLS)
Integration: ProShop ERP via GraphQL API (OAuth 2.0 client credentials)
Storage: S3 (or local fallback in ./uploads)
Architecture
backend/
├── app/
│ ├── api/ # FastAPI routers (auth, work_requests, estimates, sync, etc.)
│ ├── core/ # Database, auth, security, SSE, RLS
│ ├── models/ # SQLAlchemy models (19 models)
│ ├── schemas/ # Pydantic schemas
│ ├── services/ # Business logic
│ │ └── proshop/ # ProShop integration (client, sync, push)
│ ├── repositories/ # Data access layer
│ ├── tasks/ # Background tasks (sync scheduler)
│ └── dependencies.py
├── alembic/versions/ # Single genesis migration
├── scripts/ # seed_users.py
├── sql/ # rls_policies.sql
└── tests/
frontend/src/
├── api/ # API client functions
├── components/ # shadcn/ui components + domain components
├── hooks/ # React Query hooks
├── pages/ # tech/, planner/, admin/
├── stores/ # Zustand stores (auth, ui, notifications, toast)
├── types/ # TypeScript types
└── lib/ # Utilities (cn, format)
ProShop Integration
Alloy owns workflow data (drafts, RFI, templates, attachments). ProShop is the system of record for companies, contacts, parts, work orders, and estimates.
Inbound sync (ProShop -> Alloy): Scheduled interval + manual trigger. Pulls contacts/companies by lastModifiedTime.
Outbound push (Alloy -> ProShop): Planner clicks "Push to ProShop" -> creates Contact -> Part -> Work Order -> Estimate in dependency order.
API reference: reference/proshop-api/INTAKE-API-REFERENCE.md
Configuration
Copy .env.example to .env. Backend uses ALLOY_ prefix:
| Variable | Purpose |
|---|---|
ALLOY_DATABASE_URL |
PostgreSQL connection |
ALLOY_JWT_SECRET |
JWT signing secret (min 32 chars) |
ALLOY_AWS_* |
S3 config (optional) |
ALLOY_CORS_ORIGINS |
Comma-separated origins |
PROSHOP_BASE_URL |
ProShop API base URL |
PROSHOP_CLIENT_ID |
ProShop OAuth client ID |
PROSHOP_CLIENT_SECRET |
ProShop OAuth client secret |
PROSHOP_SCOPE |
ProShop OAuth scope |
VITE_API_URL |
Backend URL for frontend |
Commands
# Backend
uv sync --extra dev # Install with dev deps
uv run uvicorn backend.app.main:create_app --factory --reload
uv run alembic upgrade head # Run migrations
uv run pytest # Tests (SQLite in-memory)
uv run ruff check backend # Lint
uv run mypy backend # Type check
# Frontend
npm run dev # Dev server
npm run build # Production build
npm run lint # ESLint
npm run typecheck # TypeScript check
Roles
| Role | Capabilities |
|---|---|
| technician | Create/submit requests via wizard, respond to RFI |
| planner | Above + claim requests, build estimates, push to ProShop |
| admin | All + manage users/entities, sync dashboard, settings, templates |
Multi-Tenant
Routes use /app/:groupSlug/*. Each group has its own data, settings (shop rate, WR numbering), and ProShop sync config. New client = new group.
Work Request Status Flow
draft -> submitted -> needs_info <-> submitted
-> in_review -> needs_info
-> estimate_ready -> in_review
-> pushed -> closed
Any (except closed/cancelled) -> cancelled
Development
Design doc: docs/plans/2026-03-07-alloy-v2-design.md
Implementation plan: docs/plans/2026-03-07-alloy-v2-implementation.md
Execution prompts: docs/plans/execution-prompts.md