Daycast

Smart Vending Machine Platform - Developer Guide

Django 5.2 React 18 TypeScript XState

๐ŸŽฏ What is Daycast?

Daycast is a platform for operating smart vending machines. It allows users to:

  • Scan a QR code on the machine
  • Open the machine door
  • Take whatever products they want
  • Close the door and pay automatically

๐Ÿ—๏ธ Architecture: The Two Systems

๐Ÿš€
  • ๐Ÿ“ฑ Frontend PWA (React + XState)
  • โšก Backend API (Django 5.2 + DRF)
  • ๐Ÿ’ณ Payment Processing (Stripe)
  • ๐ŸŽจ Modern UI/UX
  • ๐Ÿ“Š Analytics & Metrics
๐Ÿš๏ธ

TNS-Web (Legacy)

TheNewStand-Co/tns-web
  • ๐Ÿ”ง Hardware Control (SandStar)
  • ๐Ÿšช Door Open/Close Commands
  • ๐Ÿ“ฆ Product Detection
  • ๐Ÿ”Œ Legacy Integrations
  • ๐Ÿ Django 3.0.11
๐Ÿ”Œ Hardware Proxy Mode (Bridge Strategy)

The Hardware Proxy is the strategy for deploying new machines. This approach allows SandStar (the hardware provider) to continue their standard installation process without any changes - they configure machines to point to TNS-Web as they always have.

How it works: Daycast handles the user interface and Stripe payments, while TNS-Web acts as a bridge to control the physical hardware (door open/close, product detection).

๐Ÿ“… Migration Plan: This bridge will be tested and validated over time. Once stable, the legacy TNS-Web system will be gradually deprecated, and new machines will be migrated to connect directly to the Daycast system without the proxy layer.

Machines with hardware_proxy = True use this mode. Check the admin panel to see which machines are in proxy mode.

๐Ÿ’ก
Recommended Setup: Clone both repos into a parent folder (e.g., daycast-workspace/) to use Claude Code at the root level for both projects simultaneously.
daycast-workspace/ โ”œโ”€โ”€ newstand-platform/ # Daycast (active) โ””โ”€โ”€ tns-web/ # Legacy system

๐Ÿ”„ Transaction Flow

Step 1
๐Ÿ‘ค User
Scans QR
โ†’
Step 2
๐Ÿ“ฑ PWA
React App
โ†’
Step 3
โšก Daycast
Creates TX
โ†’
Step 4
๐Ÿ”ง TNS-Web
Opens Door
โ†’
Step 5
๐Ÿญ Hardware
SandStar

๐Ÿ“‹ Transaction States

Status Code Description
PENDING 1 Transaction started, door open
SUCCESSFUL 2 Payment completed successfully
PENDING_PAYMENT 9 Door closed, awaiting payment
FAILED 3 Error in the process

๐Ÿ“ Code Structure

๐Ÿš€ Daycast (newstand-platform)

backend/ โ”œโ”€โ”€ apps/ # Django apps โ”‚ โ”œโ”€โ”€ users/ # Auth, roles, profiles โ”‚ โ”œโ”€โ”€ organizations/ # Org hierarchy โ”‚ โ”œโ”€โ”€ products/ # Catalog, menus โ”‚ โ”œโ”€โ”€ machines/ # Vending machines โ”‚ โ”œโ”€โ”€ transactions/ # Purchases, payments โ”‚ โ””โ”€โ”€ common/ # Shared utils, tasks โ”œโ”€โ”€ api/ # DRF ViewSets, serializers โ”œโ”€โ”€ config/ # Settings, URLs, ASGI โ””โ”€โ”€ tests/ # pytest tests frontend/ โ”œโ”€โ”€ src/ โ”‚ โ”œโ”€โ”€ components/ # atoms/, molecules/, organisms/, pages/ โ”‚ โ”œโ”€โ”€ machines/ # XState state machines โ”‚ โ”œโ”€โ”€ services/ # API calls โ”‚ โ”œโ”€โ”€ hooks/ # Custom React hooks โ”‚ โ””โ”€โ”€ utils/ # Helpers โ””โ”€โ”€ envs/ # Environment files

๐Ÿ”ถ TNS-Web (Legacy)

tns-web/ โ”œโ”€โ”€ accounts/ # User auth, addresses โ”œโ”€โ”€ cards/ # Loyalty cards โ”œโ”€โ”€ payments/ # Stripe, balance โ”œโ”€โ”€ vending/ # Machine operations โ”œโ”€โ”€ integrations/ # Third-party APIs โ”œโ”€โ”€ business/ # Enterprise, teams โ”œโ”€โ”€ tns/ # Settings, URLs, celery โ””โ”€โ”€ pytests/ # Tests

TNS-Web has 23+ Django apps. Key ones for vending: vending/, payments/, integrations/

๐Ÿ”‘ Key Files to Know

File Purpose
backend/apps/transactions/ Transaction model, states, payment logic
backend/apps/machines/models.py VendingMachine model, test modes, hardware proxy
frontend/src/machines/VendingMachine.ts Main XState machine for purchase flow
frontend/src/services/index.ts All API calls (vmStart, vmPay, etc.)
tns-web/vending/views.py Legacy vending endpoints (hardware control)
tns-web/integrations/sandstar/ SandStar hardware API integration

โš™๏ธ Project Setup

๐Ÿ“‹ Requirements

Docker Desktop

To run services

Node.js 18+ & Yarn

For frontend

1Password CLI

For secrets

๐Ÿš€ Installation Steps

  • 1
    Clone the repositories
    mkdir daycast-workspace && cd daycast-workspace git clone https://github.com/TheNewStand-Co/newstand-platform.git git clone https://github.com/TheNewStand-Co/tns-web.git
  • 2
    Setup Claude Code Skills
    cd newstand-platform/skills ./setup.sh
  • 3
    Get environment files

    Search in 1Password under "Daycast":
    โ€ข Backend: "Daycast | Backend env.local"
    โ€ข Frontend: "Daycast | Frontend env"

  • 4
    Setup Backend
    cd newstand-platform/backend make setup # Docker, migrations, superuser
  • 5
    Setup Frontend
    cd ../frontend yarn install

๐Ÿ”ถ TNS-Web Setup (Legacy - for Hardware Bridge)

TNS-Web is needed when working with vending machines that use the Hardware Proxy bridge.

  • 1
    Get environment file

    Search in 1Password: "TNS-Web | env"

    cd tns-web cp env.example .env # Paste values from 1Password
  • 2
    Copy Docker Compose file
    cp .docker/docker-compose/docker_compose_dev.yml docker-compose.yml
  • 3
    Build and start containers
    docker-compose build docker-compose up -d
  • 4
    Run migrations (first time only)
    docker-compose exec tns-web python manage.py collectstatic --noinput docker-compose exec tns-web python manage.py migrate

TNS-Web runs on http://localhost:8000 - Note: If running both, change Daycast backend port.

๐Ÿ”— URLs

Environment URL
Local Frontend http://localhost:3000
Local API http://localhost:8000/api/v1/
Local Admin http://localhost:8000/admin/
Staging Admin https://backend.staging.daycast.co/admin/
Production Admin https://backend.daycast.co/admin/

๐Ÿ” Credentials: Search in 1Password under "Daycast" for admin credentials.

๐ŸŒ External Services

โ˜๏ธ Azure (Hosting & Logs)

Account: azure@newstand.com (credentials in 1Password)

Web Apps:
Production web-app Portal
Staging daycast-staging Portal
TNS-Web tns-web (prod & staging) Rancher
View Logs with Azure CLI:
# Login to Azure az login # Stream live logs (Production) az webapp log tail --name web-app --resource-group app # Stream live logs (Staging) az webapp log tail --name daycast-staging --resource-group app # Download logs az webapp log download --name web-app --resource-group app # TNS-Web logs: Use Rancher dashboard instead

Azure Portal - Use azure@newstand.com

๐Ÿ› Sentry (Error Tracking)

Monitor errors and exceptions in production.

Organization new-stand-ka.sentry.io
Project: Daycast ns-platform
Project: TNS-Web tns-web

๐Ÿ” Credentials in 1Password under "Sentry"

๐Ÿ“ง Mailgun (Email Service)

Transactional emails: receipts, password resets, notifications.

Dashboard app.mailgun.com
Domain mg.daycast.co

๐Ÿ” Credentials in 1Password under "Mailgun"

๐Ÿ›ก๏ธ Cloudflare (DNS & CDN)

DNS management, CDN, and Cloudflare Pages for frontend hosting.

Dashboard dash.cloudflare.com
Domain daycast.co
Pages (Frontend) daycast-pwa

๐Ÿ” Credentials in 1Password under "Cloudflare"

๐Ÿ“ Notion (Documentation)

Project documentation, specs, and historical context. Contains mixed TNS-Web and Daycast docs.

Project Docs New Stand Workspace

๐Ÿ” Request access from team lead

๐Ÿ’ก
All credentials are in 1Password. Search for: "Azure", "Sentry", "Mailgun", or "Cloudflare"

๐Ÿค– Working with Claude Code

This project is developed using Claude Code as the primary AI assistant. Claude has access to specialized skills and agents that understand the Daycast codebase.

๐Ÿ’ก
First time setup: Run cd skills && ./setup.sh to configure Claude Code skills for this project.

๐Ÿ“š Available Skills

Skills are auto-invoked based on context. You can also call them explicitly.

django-drf-patterns

Django 5.2 + DRF: ViewSets, serializers, models, async tasks

react-xstate-patterns

React 18 + XState: Components, hooks, state machines

stripe-integration

Payments: Checkout, webhooks, SetupIntents

db-query

PostgreSQL queries with Azure credentials

sandstar-api

SandStar VMS hardware integration

daycast-azure

Azure resources: Key Vault, Web Apps, DB

review

Automated code review with prioritization

docker-cicd-patterns

Docker, Compose, GitHub Actions

project-guide

Opens this documentation in browser

๐Ÿค– Available Agents

Agent Purpose When Used
backend-reviewer Python/Django code review When reviewing .py files
frontend-reviewer React/TypeScript code review When reviewing .tsx/.ts files
security-auditor Security vulnerability audit Security-sensitive code, pre-deploy
test-writer Generates pytest/Vitest tests When writing tests
architect Architecture decisions Feature design discussions

โ˜๏ธ Azure MCP Integration

Claude Code has access to Azure MCP (Model Context Protocol) which allows direct interaction with Azure resources without leaving the editor.

What you can do:

Database Queries Use /db-query skill - Claude retrieves credentials from Azure Key Vault automatically
View Logs Ask Claude to "show logs from web-app" or "tail staging logs"
Key Vault Claude can read secrets from daycast-keyvault for scripts
Resource Info Ask about web app status, settings, or configuration
๐Ÿ’ก
Prefer Azure MCP over CLI when working in Claude Code. It's faster and doesn't require manual login. For terminal work outside Claude, use az login with azure@newstand.com.

Example prompts:

# Database "Query the database for failed transactions today" "Show me users who signed up this week" # Logs "Show recent logs from production web-app" "Check for errors in staging" # Azure Resources "What's the status of daycast-staging web app?" "Get the database password from Key Vault"

โŒจ๏ธ Useful Commands

Claude Skills

/review-pr 123 # Review a PR /db-query # Query database /test # Generate tests /review # Code review

Ask Claude

# Example prompts: "Explain how transactions work" "Review this PR for security issues" "Write tests for this ViewSet" "Query the database for pending transactions"

๐Ÿ“‹ Development Guidelines

These are the coding standards and best practices for the Daycast project. All contributors should follow these guidelines.

๐Ÿ Backend (Django)

Code Style

FormatterBlack (line-length: 88)
Importsisort with Django profile
Lintingflake8
Type HintsRequired on all public functions

โœ… DO

  • Use snake_case for functions, variables, modules
  • Use PascalCase for classes
  • Add type hints to public functions
  • Use select_related / prefetch_related for related objects
  • Use Django's ORM for database queries
  • Write tests for ViewSets and services
  • Use @extend_schema for API documentation

โŒ DON'T

  • Write raw SQL (use ORM instead)
  • Log sensitive data (tokens, passwords)
  • Skip migrations in commits
  • Use print() instead of logging
  • Put business logic in views (use services)
  • Commit .env files

โš›๏ธ Frontend (React)

Code Style

LintingESLint (airbnb-style)
FormattingPrettier (integrated)
TypeScriptStrict mode enabled

โœ… DO

  • Use PascalCase for components
  • Use camelCase for hooks and utils
  • Use XState for complex state flows
  • Follow Atomic Design (atoms, molecules, organisms)
  • Use Styled Components for styling
  • Write Vitest tests for components

โŒ DON'T

  • Use any type (use proper types)
  • Use inline styles (use Styled Components)
  • Leave console.log in production code
  • Use Redux (we use XState)
  • Skip TypeScript errors with // @ts-ignore

๐Ÿ“ Git & PRs

Commit Messages

Use conventional commits:

feat: Add new vending machine flow fix: Resolve transaction timeout issue chore: Update dependencies docs: Add API documentation refactor: Simplify payment logic test: Add tests for transaction service

Pull Request Checklist

  • Link related issues
  • Describe scope and changes
  • Flag any migrations or env var changes
  • Include screenshots for UI changes
  • Ensure CI is green
  • Request appropriate reviewers

๐Ÿงช Testing

๐Ÿ Backend (Daycast)

# Run all tests make test # Run with coverage (80% threshold) make test-coverage # Run specific app tests make test-app APP=transactions # Run fast (parallel, no coverage) make test-fast

Tests location: backend/tests/<app>/test_*.py

โš›๏ธ Frontend (Daycast)

# Run all tests yarn test # Watch mode yarn test:watch # Coverage report yarn test:coverage

Tests colocated: Component.test.tsx next to component

๐Ÿ”ถ TNS-Web (Legacy)

# Run tests inside container docker-compose exec tns-web python manage.py test -v 2 # Run pytest docker-compose exec tns-web pytest --no-cov

Tests location: pytests/

๐Ÿ“– API Documentation

Daycast Swagger localhost:8000/api/docs/
Daycast ReDoc localhost:8000/api/redoc/
TNS-Web Swagger localhost:8000/data/swagger/

โ“ Frequently Asked Questions

Vending & Transactions

What happens when a user scans a QR code? โ–ผ
  1. User scans QR โ†’ Opens PWA with machine ID
  2. PWA calls /api/v1/transactions/setup/ to create SetupIntent
  3. User enters card details (Stripe Elements)
  4. PWA calls /api/v1/transactions/start/
  5. Backend creates Transaction + calls TNS-Web to open door
  6. Door opens, user takes products
  7. Door closes โ†’ TNS-Web sends webhook with products taken
  8. Backend processes payment via Stripe
  9. Receipt sent to user
What is "Hardware Proxy" mode? โ–ผ

Hardware Proxy is the bridge between Daycast and the legacy TNS-Web system for controlling vending machine hardware.

  • Daycast handles: UI, user auth, Stripe payments
  • TNS-Web handles: Door control, product detection (via SandStar)

Machines with hardware_proxy = True use this mode.

What are the different transaction statuses? โ–ผ
PENDING (1)Door is open, user selecting products
SUCCESSFUL (2)Payment completed
FAILED (3)Error occurred
PENDING_PAYMENT (9)Door closed, processing payment
DOOR_MALFUNCTION (6)Door error detected
EMPTY_VEND (7)No products taken
What is "Free Vend" mode? โ–ผ

Machines with is_free_vend = True allow users to take products without payment. The door opens normally but no charge is made.

Use case: Employee perks, promotional events, or subsidized vending.

Development

Where do I find credentials for staging/production? โ–ผ

All credentials are stored in 1Password under the "Daycast" vault:

  • Daycast | Backend env.local - Local env file
  • Daycast | Frontend env - Frontend env file
  • Daycast | Admin credentials - Staging/prod admin
How do I test the vending flow locally? โ–ผ
  1. Start backend: make up
  2. Start frontend: yarn dev
  3. Go to admin โ†’ Machines โ†’ Enable test_mode
  4. Use test mode "full" to simulate products taken
  5. Scan QR or navigate to /qr/?vending_machine=MACHINE_ID

Use Stripe test cards: 4242 4242 4242 4242

๐Ÿ”ง Troubleshooting Guide

Common issues and how to resolve them. This guide is also useful for the support team.

๐Ÿšซ Development Issues

Docker won't start

โ–ผ
  1. Verify Docker Desktop is running
  2. Check ports: lsof -i :8000 and lsof -i :5432
  3. Restart: make down && make up
  4. Rebuild: docker-compose build --no-cache

Frontend won't connect to backend

โ–ผ
  1. Check backend is running: curl http://localhost:8000/api/v1/
  2. Verify VITE_API_URL in frontend env
  3. Check CORS settings in backend
  4. Clear browser cache and retry

โณ Transaction Issues

Transaction stuck in PENDING

โ–ผ

The door closed but payment wasn't processed.

  1. Check if TNS-Web webhook was received (check order_detail in transaction)
  2. Review TNS-Web logs for communication errors
  3. Verify Hardware Proxy configuration on the machine
  4. Use /db-query skill to investigate the state
# Check transaction in database SELECT id, status, order_detail, door_closed_at FROM transactions_transaction WHERE id = 'TRANSACTION_ID';

Stripe SetupIntent Error

โ–ผ
  • SetupIntent already succeeded: User navigated back. A new SetupIntent is generated automatically.
  • SetupIntent expired: More than 24 hours passed. Start a new transaction.
  • Invalid payment method: Card declined or incorrect data.

Hardware Proxy not working

โ–ผ
  1. Verify the machine has hardware_proxy = True
  2. Check Dynamic Preferences in Admin โ†’ Global Preferences โ†’ Vending:
    • TNS_VENDING_API_URL
    • TNS_VENDING_API_TOKEN
  3. Test connection from Django shell:
    from apps.integrations.tns_vending_client import tns_vending_client success, response = tns_vending_client.list_vending_machines() print(success, response)

Door won't open

โ–ผ
  1. Check machine status in admin (should be "active")
  2. Verify external_id matches SandStar machine ID
  3. Check TNS-Web logs for hardware errors
  4. Verify SandStar API credentials in TNS-Web admin
  5. Test direct SandStar API call (ask infra team)

๐Ÿ’ณ Payment Issues

Payment failed after door closed

โ–ผ
  1. Check Stripe dashboard for the payment attempt
  2. Look at TransactionSetupIntent for error messages
  3. Common causes:
    • Card declined
    • Insufficient funds
    • Card expired
    • 3D Secure failed
  4. Transaction will be in FAILED status

User charged but products not dispensed

โ–ผ

This requires manual refund investigation.

  1. Find transaction in admin
  2. Check order_detail for items taken
  3. Compare with Stripe charge amount
  4. If mismatch, issue refund via Stripe dashboard
  5. Update transaction status to FULLY_REFUNDED or PARTIALLY_REFUNDED