Files
website/docs/superpowers/specs/2026-04-26-dedicated-server-lineup-design.md
Andrew 0d0f6faf40 docs(spec): dedicated server lineup design
Captures the brainstorm: 8 new Dell 14th-gen chassis SKUs alongside
existing rack inventory, per-chassis configurator at
/dedicated-servers/{slug}, 5-stage post-order build tracker,
tiered setup fees waived at Semi-Annual+ cycles.

User approved design + skipped spec-review gate. Implementation
phasing in 4 commits per the spec.

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

276 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Dedicated Server Lineup — Design Spec
**Date:** 2026-04-26
**Status:** Approved (skip user-review gate per owner override — implementation starting immediately)
**Owner:** Andrew
**Repo:** `EZSCALE/website`
## Goals
1. Ship the **new Dell 14th-gen dedicated server lineup** (8 chassis SKUs sourced from SaveMyServer per order) on `/dedicated-servers`.
2. Re-surface the **existing 12th/13th-gen rack inventory** (currently `status: hidden` in the seeder) so it's visible alongside the new line as instant-deploy "in stock" SKUs.
3. Build an interactive **per-chassis configurator** at `/dedicated-servers/{slug}` covering CPU, RAM, per-bay drives, OS, bandwidth, networking, IPv4.
4. Add a **5-stage post-order build status tracker** (Ordered → Hardware acquired → Assembly → Racked → Deployed) visible to the customer and editable by admins.
5. Wire **tiered setup fees** that waive automatically on Semi-Annual / Annual cycles.
## Non-goals (deferred)
- **C from Q6: Two-preset cards** (`Starter` + `Performance` per chassis) — v1.1, after first-month signal on what people actually buy
- **Workload bundles page** — v2 if pricing-positioning-vs-budget-bundlers keeps coming up in support
- **Automated SaveMyServer order placement** — admin-driven for v1
- **Live capacity check at order time** — buffer-stock model not in v1
- **Multi-region (currently Atlanta-only)** — `Location` selector renders but only has one option
- **Custom-quote builder for non-catalog requests** — uses existing `/contact` form
- **Hetzner comparison rows** — placeholder; fills in when separate research lands
## Sources of truth
| Asset | Path | Role |
|---|---|---|
| Catalog JSON | `docs/integrations/savemyserver/dedicated-server-catalog.json` | 27 raw SaveMyServer products, drive options, BOM costs |
| Build sheets | `../infrastructure/docs/dedicated-server-configurations.md` | Curated 8-product BOMs, EZSCALE Standard Build (locked baseline) |
| Pricing | `../infrastructure/docs/dedicated-server-pricing-2026q2.md` | Customer-facing monthly prices, margin math, drive add-on tables |
| Configurator design | `../infrastructure/docs/superpowers/specs/2026-04-24-dedicated-server-gen14-configurator-design.md` | 15 configurable option groups, cross-server compliance matrix |
| Competitor research | `../infrastructure/docs/competitors-atlanta-2026.md` | ColoCrossing/GTHost positioning baseline |
| Rack reality | `../infrastructure/docs/reference/rack-atl.md` | Existing customer-rentable rack slots |
## EZSCALE Standard Build (locked baseline — applies to all 8 14th-gen chassis)
Non-negotiable per `dedicated-server-configurations.md`:
| Component | Selection |
|---|---|
| CPU | 2× Intel Xeon Gold 6230 (40C / 2.10 GHz) |
| RAM | 32 GB DDR4-2666 ECC RDIMM (2× 16 GB) |
| Boot | Dell BOSS Card with 2× 240 GB M.2 SSDs (mirrored) — **all main bays free for data** |
| Storage controller | PERC HBA330 (Non-RAID, IT mode) — N/A on R740xd NVMe (pure-PCIe) |
| iDRAC | iDRAC9 Enterprise License |
| Power | Dual redundant PSU |
| Network | 1× 1 GbE onboard + 1× 10 Gbps SFP+ |
| Drive trays | Pre-installed in every bay |
| OS | No OS (customer choice via post-provisioning panel) |
| Bandwidth | 1 Gbps unmetered uplink |
| IPv4 | 1× included |
| IPv6 | /64 included |
## The 8 14th-gen chassis
| Slug | Title | Form | Bays | Std build cost | Starting $/mo | Setup tier |
|---|---|---|---|---|---|---|
| `r440-4lff` | R440 4-Bay 3.5" LFF (1U) | 1U | 4× LFF | $1,690.61 | $119 | 2 ($349) |
| `r540-8lff` | R540 8-Bay 3.5" LFF (2U) | 2U | 8× LFF | $1,877.03 | $159 | 3 ($549) |
| `r640-8sff` | R640 8-Bay 2.5" SFF (1U) | 1U | 8× SFF | $1,411.83 | $179 | 2 ($349) |
| `r740-16sff` | R740 16-Bay 2.5" SFF (2U) | 2U | 16× SFF | $1,704.26 | $229 | 3 ($549) |
| `r740xd-24sff` | R740xd 24-Bay 2.5" SFF (2U) | 2U | 24× SFF | $1,919.73 | $279 | 3 ($549) |
| `r740xd-12lff` | R740xd 12-Bay 3.5" LFF (2U) | 2U | 12× LFF | $2,148.96 | $249 | 3 ($549) |
| `r640-10nvme` | R640 10-Bay U.2 NVMe (1U) | 1U | 10× NVMe | $1,606.79 | $239 | 4 ($799) |
| `r740xd-24nvme` | R740xd 24-Bay U.2 NVMe (2U) | 2U | 24× NVMe | $2,275.44 | $279 | 4 ($799) |
Setup tiers (per Q5 brainstorm):
| Tier | Chassis class | Setup fee |
|---|---|---|
| 1 | Single-socket Budget (R240/R340) — *not in v1 lineup* | $149 |
| 2 | Dual-socket 1U | $349 |
| 3 | Dual-socket 2U | $549 |
| 4 | NVMe / Quad-socket Enterprise | $799 |
**Setup fee waived on Semi-Annual (6 mo) and Annual (12 mo) cycles. Non-refundable once hardware is purchased** (typically within 24h of order). Rental fees stay under the 14-day money-back guarantee.
## Architecture
### Routes
```
/dedicated-servers ← catalog landing (chassis grid)
/dedicated-servers/{slug} ← per-chassis detail + configurator
account.<domain>/services/{service} ← existing route, gets BuildStatusPanel
admin.<domain>/orders/{order}/build ← admin milestone updater
```
### Database
**1. Migration: `add_setup_fee_to_plans_table`**
```php
$table->decimal('setup_fee', 10, 2)->default(0)->after('price');
```
**2. Migration: `create_service_build_milestones_table`**
```php
Schema::create('service_build_milestones', function (Blueprint $table): void {
$table->id();
$table->foreignId('subscription_id')->constrained()->cascadeOnDelete();
$table->string('stage'); // 'ordered' | 'hardware_acquired' | 'assembly' | 'racked' | 'deployed'
$table->timestamp('reached_at')->nullable();
$table->text('note')->nullable();
$table->foreignId('updated_by')->nullable()->constrained('users');
$table->timestamps();
$table->unique(['subscription_id', 'stage']);
});
```
**3. PlanSeeder updates**
- Re-enable existing 12th/13th-gen rows: `status: hidden``status: active`. Stock counts preserved.
- Insert 8 new 14th-gen rows with: `features` JSON containing `cpu`, `ram`, `storage`, `bays`, `tier` (chassis tier number), `lead_time_days: '7-10'`, `generation: '14th-gen'`. Setup fee per the table above.
**4. ConfigOptionSeeder updates**
Add a `Dedicated Gen14 Configurator` group cluster per `2026-04-24-dedicated-server-gen14-configurator-design.md`:
- `dedicated_server_gen14_cpu` (standard CPU group — R440/R540/R640/R740)
- `dedicated_server_gen14_cpu_r740xd` (R740xd-only CPU group)
- `dedicated_server_gen14_ram` (RAM tiers)
- `dedicated_server_gen14_os` (OS selector)
- `dedicated_server_gen14_bandwidth` (bandwidth tiers)
- `dedicated_server_gen14_networking` (private networking add-on)
- `dedicated_server_gen14_ipv4` (IPv4 block size)
- `dedicated_server_gen14_location` (Atlanta only for v1)
- `dedicated_server_gen14_lff_bays_1_4` (drive selection bays 1-4 LFF)
- `dedicated_server_gen14_lff_bays_5_8` (drive selection bays 5-8 LFF)
- `dedicated_server_gen14_r740xd_lff_bays` (R740xd 12-bay LFF)
- `dedicated_server_gen14_sff_slots_1_8` (SFF slots 1-8)
- `dedicated_server_gen14_sff_slots_9_16` (SFF slots 9-16, R740 only)
- `dedicated_server_gen14_sff_slots_17_24` (SFF slots 17-24, R740xd SFF only)
- `dedicated_server_gen14_nvme_slots` (U.2 NVMe slots)
Attach each sub-group only to applicable chassis per the cross-server compliance matrix.
### Frontend file map
```
resources/ts/Pages/Marketing/
├─ DedicatedServers.vue (REWRITE)
└─ DedicatedServerDetail.vue (NEW)
resources/ts/Pages/Account/Services/
└─ Show.vue (extend with BuildStatusPanel)
resources/ts/Pages/Admin/Orders/
└─ BuildTracker.vue (NEW)
resources/ts/Components/Marketing/Dedicated/
├─ ChassisCard.vue (NEW)
├─ GenerationFilter.vue (NEW)
├─ DedicatedConfigurator/
│ ├─ index.vue
│ ├─ CpuSelector.vue
│ ├─ RamSelector.vue
│ ├─ DriveBayPicker.vue
│ ├─ OsSelector.vue
│ ├─ BandwidthSelector.vue
│ ├─ NetworkingSelector.vue
│ ├─ Ipv4Selector.vue
│ └─ ConfiguratorFooter.vue
└─ BuildStatusPanel.vue (used by both customer + admin)
resources/ts/stores/
└─ dedicatedConfigurator.ts (NEW Pinia store)
```
### Pinia state
```ts
state = {
chassis: Plan | null,
cpu: string,
ramGb: number, // 32, 64, 128, 256, 512, 1024, 1536
bays: Array<string|'empty'>,
os: string,
bandwidth: string,
privateNetworking: boolean,
ipv4: 1 | 5 | 13 | 29,
cycle: 'monthly' | 'quarterly' | 'semi_annual' | 'annual',
}
getters = {
baselinePrice, cpuUpgradeCost, ramUpgradeCost, driveCost,
bandwidthCost, ipv4Cost, cycleSubtotal, setupFee,
cycleTotal, shareUrl, checkoutUrl,
}
```
### URL state contract
`/dedicated-servers/{slug}?<params>` and `/checkout/{plan_id}?<params>` share:
| Param | Values | Default |
|---|---|---|
| `cpu` | option value slug | baseline |
| `ram` | `32` `64` `128` `256` `512` `1024` `1536` | `32` |
| `bays` | comma-list, length = bay count | chassis-specific lean preset |
| `os` | `none` `alma9` `ubuntu24` `debian12` `windows-byol` | `none` |
| `bw` | `1g-unmetered` `10g-1tb` `10g-10tb` `10g-100tb` `10g-unmetered` | `1g-unmetered` |
| `pn` | `0` `1` | `0` |
| `ipv4` | `1` `5` `13` `29` | `1` |
| `cycle` | `monthly` `quarterly` `semi_annual` `annual` | `monthly` |
### Setup fee flow
Setup fee is calculated at checkout based on `plan.setup_fee` and selected cycle:
```php
$includesSetupFee = in_array($cycle, ['monthly', 'quarterly']);
$setupFee = $includesSetupFee ? $plan->setup_fee : 0;
```
Surfaced as a separate line item on the checkout page with explanatory text.
### Build tracker stages
| # | Stage | Triggered by | Customer-visible message |
|---|---|---|---|
| 1 | `ordered` | Subscription `created` event | "Order received. We're placing the hardware order with our supplier." |
| 2 | `hardware_acquired` | Admin click | "Hardware acquired and en route to our datacenter (typically 2-3 days)." |
| 3 | `assembly` | Admin click | "Server received in Atlanta. Our DC tech is configuring iDRAC and assembly." |
| 4 | `racked` | Admin click | "Server racked, powered up, and online for final QA." |
| 5 | `deployed` | Admin click | "Server is live. Root credentials and iDRAC access have been emailed." |
The `deployed` milestone flips `subscription.status` from `pending``active` and triggers the deployment email.
## Edge cases
| Case | Behavior |
|---|---|
| URL has more bay entries than chassis has bays | Truncate; toast warning |
| URL has invalid CPU for the chassis | Fall back to baseline; snackbar |
| Subscription cancelled before `hardware_acquired` | Full refund (rental + setup fee) |
| Subscription cancelled after `hardware_acquired`, inside 14 days | Pro-rated rental refund; setup fee non-refundable; chassis added to "ready-to-deploy" inventory |
| Customer wants off-catalog chassis | "Need something custom?" CTA → `/contact` form |
| Mobile (< 768 px) | DriveBayPicker collapses to single-column list; sticky footer docks to viewport bottom |
| Browser back/forward | URL hydration restores everything |
## Testing
- **Pest** — `tests/Feature/Marketing/DedicatedServersTest.php` and `tests/Feature/Account/BuildTrackerTest.php`
- **Vitest** — *deferred (Vitest not currently installed in this project; covered by Playwright + Pest)*
- **Playwright** — `tests/e2e/dedicated-configurator.spec.ts` (one happy-path E2E)
## Acceptance criteria
- [ ] Migration adds `plans.setup_fee` and `service_build_milestones` table
- [ ] PlanSeeder seeds 8 new 14th-gen rows; un-hides existing 12th/13th-gen rows
- [ ] ConfigOptionSeeder adds 15 sub-groups under "Dedicated Gen14 Configurator" with chassis-specific attachments
- [ ] `/dedicated-servers` lists all dedicated plans (both lines), generation filter works
- [ ] `/dedicated-servers/{slug}` works for all 8 new chassis slugs
- [ ] Configurator computes correct totals across all option groups
- [ ] Setup fee shows on Monthly/Quarterly, hides on Semi-Annual/Annual
- [ ] Setup fee non-refundable note on checkout + FAQ
- [ ] `Order this configuration` deep-links with all params; checkout pre-selects them
- [ ] `Copy share link` works
- [ ] BuildStatusPanel renders during build; admin can mark milestones; customer sees timestamps
- [ ] `deployed` milestone flips subscription `pending``active`
- [ ] Pest tests pass
- [ ] `npm run build` and `php artisan test --compact` pass
- [ ] Mobile layout works without horizontal scroll
## Open implementation questions (deferred to phase work)
- Exact RAM upgrade pricing tiers — pull from `dedicated-server-pricing-2026q2.md` at seeder-write time
- Exact drive add-on prices per chassis — pull from catalog JSON `drives.drives` array per chassis
- Bandwidth tier pricing — pull from `dedicated-server-pricing-2026q2.md`
- Hetzner comparison row data — pending separate research