Files
website/CLAUDE.md
Andrew 8a984f86ad docs(claude): expand strategic direction + sister-project context
Adds two sections to the project-level CLAUDE.md:

- "Strategic Direction: WHMCS Replacement" — scopes the long-arc plan
  (storefront, billing, provisioning, customer area, marketing site,
  admin RBAC, notifications, marketing email automation, future
  registrar / SSL / multi-tenant / partner API) so future sessions
  don't accidentally re-litigate decisions.

- "Sister Projects (Reference)" — calls out infrastructure/ (Ezra +
  capacity / costs source-of-truth) and ezscale_api/ (Battlelog/ACP
  SaaS) as separate Gitea repos with their own CLAUDE.md, plus the
  catalog-data flow (website pulls hardware inventory + IP
  availability from infrastructure/).

Also clarifies cross-repo conventions: Gitea (not GitHub), no shared
DBs, design docs under docs/superpowers/specs/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 22:11:11 -04:00

16 KiB

CLAUDE.md - EZSCALE Site

Project

EZSCALE Site — Laravel 12 application for VPS/Dedicated Server hosting management (billing, subscriptions, provisioning, customer management, SSO).

Phase Tracking (MANDATORY)

All work MUST be tracked against Gitea issues and TASKS.md. Use Gitea MCP tools (mcp__gitea__*) — never gh CLI.

  1. Before starting: Check the relevant Gitea issue (mcp__gitea__list_issues for repo EZSCALE/website) and TASKS.md for current status.
  2. While working: Update the Gitea issue with progress comments (mcp__gitea__add_issue_comment).
  3. After completing: Update TASKS.md to check off completed items and close the corresponding Gitea issue.
  4. New tasks discovered: Create sub-issues or add items to TASKS.md immediately.
  5. Commit messages: Reference the Gitea issue number (e.g., Fix checkout validation (#3)).

Gitea repo: https://git.ezscale.cloud/EZSCALE/website Gitea issues: https://git.ezscale.cloud/EZSCALE/website/issues

Documentation Updates (MANDATORY)

When a phase or significant task is finished, update: TASKS.md, GitHub issues, CLAUDE.md, memory files, and PROJECT_DEVELOPMENT.md (if architecture changed).

Visual Verification (MANDATORY)

After every successful npm run build:

  1. Take headless Chrome screenshots of affected pages
  2. Compare against the EZSCALE design system (navy blue palette, Plus Jakarta Sans, custom SCSS in resources/styles/)
  3. Fix any visual discrepancies before considering the task complete
  4. Key pages: Login/Register, Marketing homepage, Admin/Account dashboards, Pricing page

Laravel App Location

The Laravel application is in website/. All artisan, composer, and npm commands run from there.

website/
├── app/
│   ├── Models/              # 29 Eloquent models
│   ├── Http/Controllers/    # Account/, Admin/, Api/V1/ controllers
│   ├── Http/Resources/      # API Resources
│   ├── Services/Billing/    # BillingServiceInterface, Stripe, PayPal, Dunning
│   ├── Events/              # Payment, Subscription events
│   ├── Listeners/           # Event handlers
│   └── Console/Commands/    # RetryProvisioning, SyncStripePrices
├── bootstrap/app.php        # Middleware, exceptions, routing (Laravel 12 slim — no Kernel files)
├── database/                # 59 migrations, 24 factories, seeders
├── resources/
│   ├── ts/                  # TypeScript source (Vue 3 + Inertia)
│   │   ├── types/           # Shared TypeScript interfaces
│   │   ├── Layouts/         # AccountLayout, AdminLayout, AuthLayout, MarketingLayout
│   │   ├── Components/      # Shared + marketing components
│   │   └── Pages/           # 85 Vue pages (Auth/7, Admin/41, Marketing/14, etc.)
│   └── styles/              # EZSCALE design system SCSS (8 files)
├── routes/                  # web, account, admin, marketing, webhooks, api
└── tests/                   # ~497 Pest tests

Tech Stack

  • Framework: Laravel 12 (PHP 8.3)
  • Frontend: Vue 3 + Inertia.js v2 + TypeScript (REQUIRED) + Vuetify 3 + Vite 7
  • UI Theme: Custom EZSCALE design system — navy blue #1d4ed8, Plus Jakarta Sans + JetBrains Mono (Bunny Fonts CDN), subdomain-aware theming (light for marketing, dark for admin/account)
  • Charts: ECharts via vue-echarts
  • Utilities: @vueuse/core
  • Testing: Pest 4 + PHPUnit 12 (~497 tests)
  • Formatting: Laravel Pint
  • Payments: Laravel Cashier (Stripe) + srmklive/paypal (PayPal)
  • Database: MySQL 8.x, database driver for sessions (Redis NOT installed)
  • Auth: Laravel Fortify (login, register, 2FA, password reset, email verify) + Passport (OAuth2/SSO)
  • Roles: spatie/laravel-permission (admin, customer)
  • Queue: Laravel Horizon

Commands

cd website
composer run dev               # Start all dev servers (artisan serve + queue + pail + vite)
php artisan test --compact     # Run Pest tests
npm run build                  # Production build
vendor/bin/pint --dirty --format agent  # Format changed files

TypeScript Requirement (MANDATORY)

All frontend code MUST use TypeScript.

  • All .vue files must use <script setup lang="ts"> (never plain <script setup>)
  • Props: interface Props + withDefaults(defineProps<Props>(), {...})
  • Emits: defineEmits<{ event: [payload: Type] }>()
  • Explicit types for ref<Type>(), computed<Type>(), and function return types
  • No any type — use proper interfaces or type aliases
  • Shared types go in resources/ts/types/
  • Inertia page props should be typed with interfaces

Design System

Colors

  • Primary: Navy blue #1d4ed8, lighter variant #3b82f6
  • Subdomain theming: Marketing = light mode, Admin/Account = dark mode by default
  • Theme persistence: localStorage key ezscale-theme, read on Vuetify init

Typography

  • UI font: Plus Jakarta Sans (Bunny Fonts CDN)
  • Code font: JetBrains Mono (Bunny Fonts CDN)

Key Patterns

  • Component ordering: <script lang="ts" setup> then props interface, state, computed, methods, watchers
  • Layout system: AppSidebar (collapsible) + AppTopNavbar (sticky) + CommandPalette (Cmd+K)
  • Navigation types: NavLink, NavGroup, NavSectionTitle (see resources/ts/@layouts/types.ts)
  • State management: Pinia stores (e.g., stores/toast.ts)
  • Icons: Tabler icons via @iconify/vue (e.g., tabler-smart-home)

Gotchas

  • User::billingInvoices() — renamed from invoices() to avoid conflict with Laravel Cashier's built-in invoices() method. All call sites use billingInvoices(). The withCount uses alias billing_invoices_count.

Agent Usage (MANDATORY)

Maximize use of subagents (Task tool) to reduce context usage. Main conversation should orchestrate; heavy lifting goes to agents.

  • Parallel agents: Launch independent tasks as parallel agents, not sequentially in main context.
  • Delegate research: Use Explore agents for codebase exploration and file searches.
  • Delegate implementation: Use general-purpose agents for self-contained tasks.
  • Delegate reviews: Use feature-dev:code-reviewer agents to review code after writing it.
  • Delegate architecture: Use feature-dev:code-architect or Plan agents for feature design.
  • Background agents: Use run_in_background: true for long-running tasks.
  • Batch similar work: 10+ file updates with the same pattern go to an agent.
  • Frontend Design Skill: ALWAYS run in background (run_in_background: true).

Headless Chrome

google-chrome --headless=new --disable-gpu --no-sandbox --screenshot=/tmp/screenshot.png --window-size=1920,1080 --virtual-time-budget=15000 "URL"
  • Must use --headless=new, --virtual-time-budget=15000, and --no-sandbox
  • dbus errors in output are harmless — ignore them
  • Read the resulting PNG with the Read tool to view it

Code Conventions

PHP

  • PSR-12, enforced by Pint
  • declare(strict_types=1); in all PHP files
  • Explicit return types and parameter type hints
  • PHP 8 constructor property promotion
  • Form Request classes for validation (not inline in controllers)
  • Service classes for business logic (thin controllers)
  • Events/Listeners for side effects (email, provisioning)
  • Eloquent over raw queries; avoid DB::, prefer Model::query()
  • Eager loading to prevent N+1 queries
  • config() only, never env() outside config files
  • Named routes with route() helper
  • Pest tests for all new functionality
  • Database transactions for multi-step operations
  • Check sibling files for conventions before creating new files
  • Run vendor/bin/pint --dirty --format agent before finalizing

Frontend (Vue/TypeScript)

  • Use Vuetify components directly (VCard, VBtn, VTextField, etc.) — not raw HTML
  • Use Inertia Link component for navigation (not <a> tags)
  • Use useForm() from @inertiajs/vue3 for form submissions
  • Status badges: VChip with resolveStatusColor() utilities
  • Pinia stores for shared state
  • ECharts via vue-echarts for charts

Security

  • All API endpoints require authentication
  • Admin routes protected by role-based middleware
  • CSRF on all forms (webhooks exempted via bootstrap/app.php)
  • Rate limiting on auth and API endpoints
  • Audit logging for admin actions and billing events

Domains

  • ezscale.dev (dev) / ezscale.cloud (prod) — marketing site
  • account.ezscale.dev / account.ezscale.cloud — customer dashboard
  • admin.ezscale.dev / admin.ezscale.cloud — admin panel (Cloudflare Zero Trust)
  • Subdomain routing configured in bootstrap/app.php via Route::domain()

Key Business Domains

  1. Billing — Subscriptions, invoices, payments (Stripe + PayPal), dunning, coupons
  2. Provisioning — VirtFusion (VPS), SynergyCP (Dedicated), Enhance (Hosting), Pterodactyl (Game) — idempotent with retry
  3. Customer Management — Profiles, support tickets, notifications
  4. Admin Panel — Dashboard, analytics, user/service management
  5. SSO — Single sign-on via Laravel Passport

Strategic Direction: WHMCS Replacement

This app is being built into a full WHMCS replacement for EZSCALE. Scope to track:

  • Storefront / catalog — product browsing, configurable options, cart, checkout, multi-currency, quotes, coupons, tax (regional)
  • Billing — subscriptions, invoices, dunning, credit balances, refunds, Stripe + PayPal (more gateways later)
  • Provisioning — VirtFusion / SynergyCP / Enhance / Pterodactyl modules (idempotent, retry, suspension/termination hooks)
  • Customer area — services list, KB, ticketing, login history, two-factor, affiliate dashboard, credits
  • Marketing site — pricing, status page, blog, lead capture, affiliate landing pages
  • Admin panel — RBAC staff, financial reports, fraud detection, dunning queue, manual invoice ops, refund flows
  • Notifications — transactional email, Discord webhooks, Slack handoff to Ezra (see infrastructure/)
  • Marketing email automation — drip campaigns, lifecycle/winback, broadcast announcements, segmented lists (lead/customer/lapsed), unsubscribe + preference center, deliverability hooks (Stalwart). Active planning.
  • Future — domain registrar integration, SSL provisioning, reseller multi-tenancy (see KASM_AND_MULTITENANCY.md), API for partner integrations

When planning new work, check what's already shipped (recent commits cover KB, tickets v2, multi-currency, cart, quotes, affiliates, credits, staff RBAC, fraud detection, service panels, churn prevention, login history, financial reports, configurable checkout). Gap-analyze against WHMCS feature parity before building.

Sister Projects (Reference)

The EZSCALE platform is split across three repositories, all on Gitea (git.ezscale.cloud). Read their CLAUDE.md files when touching cross-repo concerns; do not modify them from this repo.

Catalog data model: website/ owns the product catalog (SKUs, pricing, configurable options, descriptions). It pulls from various sources to populate inventory and capacity dynamically — most notably from infrastructure/ for the VPS and dedicated server lineups. Treat infrastructure/ as the source-of-truth for hardware inventory, capacity, and rack reality; treat website/ as the source-of-truth for what's for sale, at what price, and to whom.

../infrastructure/ — Ops platform & Ezra AI agent

Path: /home/andrew/local_projects/infrastructure/ · Repo: git@git.ezscale.cloud:EZSCALE/infrastructure.git

Houses everything that runs the business (not the storefront): K3s clusters (US/EU), Terraform-managed Cloudflare DNS, Ansible playbooks, the web/ Laravel 13 admin panel that hosts Ezra (the AI ops agent — capacity scoring, MRR forecasting, ticket sync, customer intelligence, investor reports), plus deep reference docs.

What website/ pulls from infrastructure/ (catalog inputs):

  • VPS lineups — VirtFusion package definitions, hypervisor capacity, plan availability per region. Source: infrastructure/web/app/Services/ApiClients/VirtFusion* + Services/Capacity/. Use to drive the /vps product pages and "stock available" indicators.
  • Dedicated server lineups — SynergyCP inventory + the rack reality in infrastructure/docs/reference/rack-atl.md (server SKUs, specs, current allocations). Use to drive the /dedicated product pages.
  • Vendor costs / marginsinfrastructure/docs/reference/business-costs.md (Evocative, Hetzner, etc.). Reference when setting prices; never expose to customers.
  • IP availabilityinfrastructure/docs/reference/ip-resources.md (ARIN vs Evocative leases). Drives whether IPv4 add-ons can be sold without a waitlist.

Other intersections (non-catalog):

  • API client patternsinfrastructure/web/app/Services/ApiClients/BaseApiClient provides retry, rate-limit, and IPv4 DNS pinning. Port that base class here when our provisioning clients need the same hardening.
  • Customer intelligenceServices/Intelligence/ syncs scoring/segmentation. Website billing events should feed this; risk scores from it should drive fraud thresholds here.
  • Ticketing — Ezra ingests SupportPal tickets and drafts AI responses. As website/ takes over ticketing, agree on a sync contract (or have Ezra read from our DB).
  • Reverse DNS / mailServices/Rdns/ (PowerDNS) and Stalwart/SOGo. Customer rDNS requests in the account panel should flow through Ezra, not direct PowerDNS calls.
  • Identity — Authentik IdP at id.ezscale.cloud. Staff SSO should integrate via SocialiteProviders/Authentik (already used in infrastructure/web/); customers stay on Fortify + Passport.
  • Other reference docspowerdns.md, mail-server.md, authentik.md, llc-agreement.md, zfs-storage.md, uptime-kuma.md, hardware-monitoring.md.

../ezscale_api/ — Battlelog/ACP SaaS API

Path: /home/andrew/local_projects/ezscale_api/ · Repo: git@git.ezscale.cloud:EZSCALE/api.git · Endpoint: api.ezscale.cloud

Centralized Laravel 12 API at api.ezscale.cloud that fronts Battlelog (BF3/BF4/BFH) for the ACP (Adkats Control Panel) product — game-server admin SaaS sold to Battlefield community server operators. TimescaleDB-backed, single shared API key, multi-tenant ACP instances consume it.

Key intersections with website/:

  • As a product — ACP is one SKU in the website catalog. When provisioning ACP, website calls into the ACP tenant orchestrator (separate from this API) but tenants in turn need the API key issued/revoked here.
  • API key lifecycle — Currently a single static EZSCALE_API_KEY. When website starts selling ACP plans with usage limits, we'll likely need per-tenant keys here — coordinate before changing the auth model.
  • Real-time pattern — Standalone Node.js Socket.IO + Redis pub/sub setup (ezscale_api/socketio/) is a reusable template if website needs live admin dashboards beyond polling.
  • Helm/K8s deployment templateezscale_api/helm/ezscale-api/ is the cleanest deploy reference for our eventual K8s migration of website/.

Cross-repo conventions

  • Git host: Gitea at git.ezscale.cloud (NOT GitHub). Use mcp__gitea__* tools, never gh CLI for these repos.
  • DB hosts: Each app has its own DB. Cross-repo data access is via HTTP APIs, never shared DB connections.
  • Docs format: Each repo's CLAUDE.md is the canonical onboarding doc. docs/superpowers/specs/ holds design docs; docs/reference/ (in infrastructure) holds long-lived ops reference.

Reference Docs

  • TASKS.md — Task list and progress tracking
  • PROJECT_DEVELOPMENT.md — Architecture decisions, database schema, API integrations
  • FEATURES.md — Feature specifications
  • ADVANCED_FEATURES.md — Advanced feature specs
  • KASM_AND_MULTITENANCY.md — Kasm Workspaces + reseller multi-tenancy
  • GETTING_STARTED.md — Development setup guide
  • docs/ — Deployment configs (deployment/), API specs (integrations/), scripts (scripts/), feature plans (superpowers/)
  • website/CLAUDE.md — Laravel Boost guidelines (auto-generated)