docs: update README with current project status, optimize CLAUDE.md

README: reflect completed phases (1-5, 8-9), accurate tech stack
(Vuetify 3 not Tailwind, Passport not Sanctum, standalone tickets
not SupportPal), current codebase counts (59 migrations, 29 models,
85 pages, ~497 tests), and separate implemented vs planned features.

CLAUDE.md: reduce from 281 to 184 lines — trim derivable directory
listings, remove stale counts, cut redundant examples, update all
metrics to current state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Dev
2026-03-16 11:55:01 -04:00
parent 1d4a9f33f6
commit 2bf8a5b6bf
2 changed files with 268 additions and 375 deletions

251
CLAUDE.md
View File

@@ -1,38 +1,28 @@
# CLAUDE.md - EZSCALE Site
## Project
EZSCALE Site — Laravel 12 application replacing WHMCS for VPS/Dedicated Server hosting management (billing, subscriptions, provisioning, customer management, SSO).
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 GitHub issues and `TASKS.md`:
1. **Before starting any phase work:** Check the relevant GitHub issue (see `gh issue list`) and `TASKS.md` for current status.
2. **While working:** Update the GitHub issue with progress comments as significant milestones are completed (e.g., `gh issue comment <number> --body "Completed X"`).
3. **After completing work:** Update `TASKS.md` to check off completed items and close/update the corresponding GitHub issue.
4. **New tasks discovered during work:** Create sub-issues or add items to `TASKS.md` immediately.
1. **Before starting:** Check the relevant GitHub issue (`gh issue list`) and `TASKS.md` for current status.
2. **While working:** Update the GitHub issue with progress comments (`gh issue comment <number> --body "Completed X"`).
3. **After completing:** Update `TASKS.md` to check off completed items and close the corresponding GitHub issue.
4. **New tasks discovered:** Create sub-issues or add items to `TASKS.md` immediately.
5. **Commit messages:** Reference the GitHub issue number (e.g., `Fix checkout validation (#3)`).
GitHub issues: https://github.com/EZSCALE/accounting/issues
## Documentation Updates (MANDATORY)
When a phase is completed or a significant task within a phase is finished:
1. **Update `TASKS.md`** — Check off completed items, add new items discovered during work
2. **Update GitHub issues** — Add progress comments (`gh issue comment <number> --body "..."`) and close completed issues
3. **Update `CLAUDE.md`** — Reflect any new tech stack changes, directory structure changes, or convention updates
4. **Update memory files** — Record key patterns, gotchas, and environment details learned during the work
5. **Update `PROJECT_DEVELOPMENT.md`** — If architectural decisions changed or new integrations were added
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 layout and design against the EZSCALE design system (navy blue palette, Plus Jakarta Sans font, custom SCSS in `resources/styles/`)
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 to verify:
- Login/Register (split-screen auth layout with gradient art)
- Marketing homepage (transparent navbar, animated heroes, mega footer)
- Admin/Account dashboards (sidebar + top navbar layout)
- Pricing page (service type tabs, billing cycle toggle)
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.
@@ -40,241 +30,154 @@ The Laravel application is in **`website/`**. All artisan, composer, and npm com
```
website/
├── app/
│ ├── Models/ # 16 Eloquent models (Service uses SoftDeletes, TaxRate, EmailTemplate)
│ ├── Http/Controllers/ # Account/, Admin/, and Api/V1/ controllers
│ └── Api/V1/ # RESTful API controllers (Customer + Admin/)
│ ├── Http/Resources/ # API Resources (Service, Invoice, Subscription, Ticket, Customer, etc.)
│ ├── Models/ # 29 Eloquent models
│ ├── Http/Controllers/ # Account/, Admin/, Api/V1/ controllers
├── Http/Resources/ # API Resources
│ ├── Services/Billing/ # BillingServiceInterface, Stripe, PayPal, Dunning
│ ├── Events/ # PaymentSucceeded/Failed, SubscriptionCreated/Cancelled
│ ├── Listeners/ # HandlePaymentSucceeded/Failed
── Console/Commands/ # RetryProvisioningCommand, SyncStripePrices
│ └── Providers/ # AppServiceProvider, FortifyServiceProvider
├── bootstrap/app.php # Middleware, exceptions, routing (Laravel 12 style)
├── config/ # App, auth, fortify, passport, cashier, paypal, permission
├── database/
│ ├── migrations/ # 44 migrations
│ ├── factories/ # 8 factories
│ └── seeders/ # Roles, plans, admin user
│ ├── 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 (migrated from js/)
│ │ ├── app.ts # Entry point with Vuetify + Pinia
│ │ ├── bootstrap.ts
│ │ ├── types/ # TypeScript interfaces
│ │ ── utils/ # Resolvers, formatters
│ ├── stores/ # Pinia stores (toast.ts)
├── navigation/ # account.ts, admin.ts, marketing.ts
│ │ ├── plugins/vuetify/ # theme.ts, defaults.ts, icons.ts, index.ts
│ │ ├── @layouts/ # Layout types (NavLink, NavGroup, NavSectionTitle)
│ │ ├── Layouts/ # AccountLayout, AdminLayout, AuthLayout, MarketingLayout
│ │ ├── Components/ # AppSidebar, AppTopNavbar, CommandPalette, ToastStack, NotificationPanel, SkeletonLoader, EmptyState, Breadcrumbs, StatCard, StatusChip, ThemeSwitcher, marketing/ (HeroSection, PricingCard, GlassCard, ScrollReveal, etc.)
│ │ └── Pages/ # Auth/ (7), Profile/ (2), Plans/ (1), Checkout/ (1), Subscriptions/ (2), Billing/ (3), Services/ (2), Tickets/ (3), Admin/ (30+), Marketing/ (12), Dashboard
│ ├── styles/ # Custom EZSCALE design system SCSS
│ │ ├── _variables.scss # Design tokens (colors, spacing, typography)
│ │ ├── _mixins.scss # Reusable SCSS mixins
│ │ ├── _animations.scss # Keyframe animations and transitions
│ │ ├── _typography.scss # Font definitions (Plus Jakarta Sans, JetBrains Mono)
│ │ ├── _component-overrides.scss # Vuetify component style overrides
│ │ ├── _marketing.scss # Marketing-specific styles
│ │ ├── _layouts.scss # Layout-specific styles
│ │ ├── variables/ # _vuetify.scss, _template.scss
│ │ └── styles.scss # Main entry — imports all design system files
│ ├── images/
│ └── views/app.blade.php # Inertia root template
├── routes/ # web.php, account.php, admin.php, marketing.php, webhooks.php, api.php
├── tests/ # 252 Pest tests passing (1310 assertions)
├── composer.json
├── package.json
└── vite.config.js
│ ├── 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), Laravel 12 slim structure (no Kernel files)
- **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 primary (#1d4ed8), Plus Jakarta Sans + JetBrains Mono fonts (Bunny Fonts CDN), subdomain-aware theming (light for marketing, dark for admin/account)
- **Charts:** ECharts via `vue-echarts` for analytics dashboards
- **Utilities:** `@vueuse/core` for composable utilities
- **Testing:** Pest 4 + PHPUnit 12 (347 tests, 1866 assertions)
- **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, Redis for cache/queue/sessions
- **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 for queue management
- **Queue:** Laravel Horizon
## Commands
```bash
cd website
composer run dev # Start all dev servers (artisan serve + queue + pail + vite)
php artisan serve # Laravel dev server only
php artisan test --compact # Run Pest tests
php artisan migrate # Run migrations
npm run dev # Vite dev server only
npm run build # Production build
vendor/bin/pint --dirty --format agent # Format changed files
```
## TypeScript Requirement (MANDATORY)
**All frontend code MUST use TypeScript.** This applies to all Vue components, composables, utilities, and type definitions.
**All frontend code MUST use TypeScript.**
### Rules
- All `.vue` files must use `<script setup lang="ts">` (never plain `<script setup>`)
- Define component props with `interface Props` and `withDefaults(defineProps<Props>(), {...})`
- Define emits with typed `defineEmits<{ event: [payload: Type] }>()`
- Use explicit types for `ref<Type>()`, `computed<Type>()`, and function return types
- 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/` (e.g., `models.ts`, `billing.ts`)
- Shared types go in `resources/ts/types/`
- Inertia page props should be typed with interfaces
### Example Component Pattern
```vue
<script setup lang="ts">
import { Link } from '@inertiajs/vue3'
import AppLayout from '@/Layouts/AppLayout.vue'
interface Props {
title: string
items: Item[]
count?: number
}
interface Item {
id: number
name: string
status: 'active' | 'inactive'
}
defineOptions({ layout: AppLayout })
const props = withDefaults(defineProps<Props>(), {
count: 0,
})
const isActive = computed<boolean>(() => props.count > 0)
</script>
```
## Design System
The EZSCALE design system replaces the previous Vuexy-based theme. Key design tokens and patterns:
### Colors
- **Primary:** Navy blue `#1d4ed8`, lighter variant `#3b82f6`
- **Subdomain theming:** Marketing uses light mode, Admin/Account use dark mode by default
- **Theme persistence:** User preference saved to localStorage key `ezscale-theme`, read on Vuetify init
- **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 (via Bunny Fonts CDN)
- **Code font:** JetBrains Mono (via Bunny Fonts CDN)
- **UI font:** Plus Jakarta Sans (Bunny Fonts CDN)
- **Code font:** JetBrains Mono (Bunny Fonts CDN)
### Key Patterns
- **Component structure:** `<script lang="ts" setup>` props interface state computed methods watchers
- **Vuetify components:** VCard, VBtn, VTextField, VSelect, VTextarea, VIcon, VAvatar, VChip, VDataTable, etc.
- **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` for toast notifications)
- **Icons:** Tabler icons via `@iconify/vue` (e.g., `tabler-smart-home`, `tabler-chart-bar`)
- **Shared components:** AppSidebar, AppTopNavbar, CommandPalette, ToastStack, NotificationPanel, SkeletonLoader, EmptyState, Breadcrumbs
- **Marketing components:** HeroSection, NetworkHero, VpsHero, DedicatedHero, WebHostingHero, GameServerHero, GlassCard, ScrollReveal, PricingCard
- **State management:** Pinia stores (e.g., `stores/toast.ts`)
- **Icons:** Tabler icons via `@iconify/vue` (e.g., `tabler-smart-home`)
### Model Notes
### 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)
Always maximize use of subagents (Task tool) to reduce context usage in the main conversation. This keeps the main terminal fast and avoids running out of context on large tasks.
Maximize use of subagents (Task tool) to reduce context usage. Main conversation should orchestrate; heavy lifting goes to agents.
### Rules
- **Parallel agents**: When multiple independent tasks exist (e.g., reading several files, researching different topics, building separate components), launch them as parallel agents in a single message rather than doing them sequentially in the main context.
- **Delegate research**: Use `Explore` agents for codebase exploration, file searches, and understanding existing patterns. Do not manually grep/read dozens of files in the main context.
- **Delegate implementation**: Use `general-purpose` agents for self-contained implementation tasks (e.g., "create this component", "write this migration", "update these 5 files with this pattern").
- **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 designing features before implementing.
- **Keep main context for orchestration**: The main conversation should coordinate agents, communicate with the user, and handle simple/quick edits. Heavy lifting goes to agents.
- **Background agents**: Use `run_in_background: true` for long-running tasks that don't block other work. Check results later with the Read tool on the output file.
- **Batch similar work**: If updating 10+ files with the same pattern, send them to an agent rather than editing each one in the main context.
### Frontend Design Skill
When using the `frontend-design` skill, **ALWAYS** run it in the background using `run_in_background: true`. Never run it in the main context window — it consumes significant context and produces large outputs. Check its output file when complete using the Read tool.
- **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
Chrome is available for visual testing and screenshot comparison. Use it to verify UI matches design references.
```bash
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`** (not just `--headless`) for modern headless mode
- **Must use `--virtual-time-budget=15000`** (or higher) to wait for SPA JavaScript to render before capturing
- **Must use `--no-sandbox`** in this environment
- Must use `--headless=new`, `--virtual-time-budget=15000`, and `--no-sandbox`
- dbus errors in output are harmless — ignore them
- After every successful `npm run build`, screenshot key pages to verify visual consistency
- Use for verifying layout, spacing, and component rendering
- Can be delegated to agents for parallel screenshot capture
- Read the resulting PNG with the Read tool to view it
### Examples of When to Use Agents
- Exploring how a feature works across multiple files → `Explore` agent
- Creating multiple Vue pages/components → parallel `general-purpose` agents
- Writing tests for new code → `general-purpose` agent
- Researching design system patterns → `Explore` agent
- Building a new API endpoint (controller + request + test) → `general-purpose` agent
- Reviewing changes before committing → `feature-dev:code-reviewer` agent
## Code Conventions
### PHP
- PSR-12 coding standards, enforced by Pint
- PSR-12, enforced by Pint
- `declare(strict_types=1);` in all PHP files
- Explicit return types and parameter type hints on all methods
- 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 (controllers stay thin)
- Policies for authorization
- Events/Listeners for side effects (email, provisioning, etc.)
- Eloquent models and relationships over raw DB queries; avoid `DB::`, prefer `Model::query()`
- 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()` helper only, never `env()` outside config files
- Named routes with `route()` helper for URL generation
- Feature and Unit tests (Pest) for all new functionality
- `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 changes
- Run `vendor/bin/pint --dirty --format agent` before finalizing
### Frontend (Vue/TypeScript)
- All components use `<script setup lang="ts">`
- Props defined via `interface Props` + `defineProps<Props>()`
- Subdomain-aware theming: marketing = light, admin/account = dark (user can toggle, persisted to localStorage)
- Use Vuetify components directly (VCard, VBtn, VTextField, VSelect, VTextarea, VChip, etc.) — not raw HTML
- Use Inertia `Link` component for navigation (not `<a>` tags for internal links)
- 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 use VChip with color prop and resolveStatusColor() utilities
- Use Pinia stores for shared state (e.g., `stores/toast.ts` for toast notifications)
- Use ECharts via `vue-echarts` for charts and analytics visualizations
- 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 protection on all forms (webhooks exempted via `bootstrap/app.php`)
- CSRF on all forms (webhooks exempted via `bootstrap/app.php`)
- Rate limiting on auth and API endpoints
- Encrypted storage for sensitive data (API keys, credentials)
- Audit logging for admin actions and billing events
## Domains
- **ezscale.dev** **ezscale.cloud** (marketing site) — dev uses `.dev`, production will use `.cloud`
- **account.ezscale.dev** **account.ezscale.cloud** (customer dashboard)
- **admin.ezscale.dev** **admin.ezscale.cloud** (admin panel, Cloudflare Zero Trust)
- **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), Pterodactyl (Game), SynergyCP (Dedicated), Enhance (Hosting) — idempotent provisioning with retry
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
## Reference Docs
- `TASKS.md` — Task list and progress tracking (update after each phase)
- `TASKS.md` — Task list and progress tracking
- `PROJECT_DEVELOPMENT.md` — Architecture decisions, database schema, API integrations
- `FEATURES.md` — Feature specifications (35+ features)
- `ADVANCED_FEATURES.md` — Advanced feature specs (28 features)
- `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
- `IDEAS.md` — Future feature ideas
- `website/CLAUDE.md` — Laravel Boost guidelines (auto-generated, Laravel/Pest/Pint conventions)
- `docs/` — Deployment configs (`deployment/`), API specs (`integrations/`), scripts (`scripts/`), feature plans (`superpowers/`)
- `website/CLAUDE.md` — Laravel Boost guidelines (auto-generated)