Updates CLAUDE.md (design system, tech stack, directory structure, conventions), TASKS.md (redesign and bug fix items checked off), and creates session log for the 2026-03-14 redesign session covering layout rebuild, SCSS replacement, component migration, and 12 bug fixes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
282 lines
16 KiB
Markdown
282 lines
16 KiB
Markdown
# CLAUDE.md - EZSCALE Site
|
|
|
|
## Project
|
|
EZSCALE Site — Laravel 12 application replacing WHMCS 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.
|
|
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
|
|
|
|
### 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/`)
|
|
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)
|
|
|
|
## Laravel App Location
|
|
The Laravel application is in **`website/`**. All artisan, composer, and npm commands run from there.
|
|
|
|
```
|
|
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.)
|
|
│ ├── 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
|
|
├── 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
|
|
```
|
|
|
|
## Tech Stack
|
|
- **Framework:** Laravel 12 (PHP 8.3), Laravel 12 slim structure (no Kernel files)
|
|
- **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)
|
|
- **Formatting:** Laravel Pint
|
|
- **Payments:** Laravel Cashier (Stripe) + srmklive/paypal (PayPal)
|
|
- **Database:** MySQL 8.x, Redis for cache/queue/sessions
|
|
- **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
|
|
|
|
## 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.
|
|
|
|
### 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
|
|
- No `any` type — use proper interfaces or type aliases
|
|
- Shared types go in `resources/ts/types/` (e.g., `models.ts`, `billing.ts`)
|
|
- 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
|
|
|
|
### Typography
|
|
- **UI font:** Plus Jakarta Sans (via Bunny Fonts CDN)
|
|
- **Code font:** JetBrains Mono (via 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.
|
|
- **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
|
|
|
|
### Model Notes
|
|
- **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.
|
|
|
|
### 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").
|
|
- **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.
|
|
|
|
### 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
|
|
- 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
|
|
- `declare(strict_types=1);` in all PHP files
|
|
- Explicit return types and parameter type hints on all methods
|
|
- 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()`
|
|
- 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
|
|
- 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
|
|
|
|
### 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 `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
|
|
|
|
## Security
|
|
- All API endpoints require authentication
|
|
- Admin routes protected by role-based middleware
|
|
- CSRF protection 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)
|
|
- 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
|
|
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)
|
|
- `PROJECT_DEVELOPMENT.md` — Architecture decisions, database schema, API integrations
|
|
- `FEATURES.md` — Feature specifications (35+ features)
|
|
- `ADVANCED_FEATURES.md` — Advanced feature specs (28 features)
|
|
- `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)
|
|
- `SESSION_LOG_2026-03-14.md` — Full frontend redesign session log (design system, bug fixes)
|