Boban Blaskovic
030185f02e
URL-prefix workspace routing: /w/{public_id}/... persistent in path
...
User: 'workspace stays in URL only until tab change' + 'use random 25-char
string or UUID for workspace identifier'.
Migration:
- workspaces.public_id: varchar(25) unique nullable.
- Backfill existing rows with Str::random(25).
Workspace model:
- Auto-fill public_id on create via booted() with collision-check loop.
- Override getRouteKeyName() → 'public_id' so route-model-binding uses
the opaque public_id everywhere (not the guessable slug).
Routes:
- Authed routes wrapped in prefix 'w/{wsId}' → URL shape
/w/bPSyuQpMDI0bl0LBKlwVOLdsl/dashboard etc.
- Bare /dashboard /sites /servers etc. now redirect to current
workspace's prefixed URL (covers external bookmarks / first visit).
ResolveCurrentWorkspace middleware:
- Resolution priority: route param {wsId} → ?workspace query →
session sticky → user.current_workspace_id → first owned.
- On resolve: URL::defaults(['wsId' => public_id]) auto-injects param
into every route() call, so all Volt wire:navigate / @route()
helpers carry the workspace through the entire SPA session.
- forceFill + saveQuietly to avoid triggering observers on user.
Sidebar:
- Workspace-switch links now point to /w/{public_id}/dashboard (not
the slug ?workspace=…).
TestCase:
- URL::defaults({wsId: 'test-workspace'}) so route('dashboard') etc.
generates valid URLs in tests.
- actingAsWithWorkspace() helper for tests that need a real workspace
bound to a logged-in user.
Browser-verified: click Sidebar → Sites navigates to
/w/bPSyuQpMDI0bl0LBKlwVOLdsl/sites, public_id sticks across every
internal navigation. 36/36 Page-Pest still green.
2026-06-01 01:34:38 +02:00
Boban Blaskovic
4f0c787f89
Pages: Cluster Wizard (4-step) + Site Details (6 tabs) — final 12/12
...
- pages/clusters/create: 4-step wizard (Basis/Region+Size/WordPress/Review),
sticky summary card with live monthly price (size × nodes), creates real
Cluster on submit, redirects to servers index. 6 tests.
- pages/sites/show: 6-tab interface (Übersicht/WordPress/PHP/Files/Cron/Logs)
via Volt setTab(), URL-bound tab state. Overview metrics + Quick-Action
toggles (maintenance/cache/CDN) persist directly. WP+PHP config forms,
file tree + wp-config preview, cron table, log console with level coloring.
5 tests.
- Routes: Volt for clusters.create + sites.show with route-model-binding.
- CSS: clu-detail-tabs, clu-log-console, clu-log-level (info/warn/error),
clu-file-tree, clu-file-row.
- Full regression: 47/47 Pest tests green (214 assertions).
ALL 12 templates ported to Volt + Pest.
2026-05-31 23:08:15 +02:00
Boban Blaskovic
d57d456d02
Pages: Backups + Team + Security + Settings (14 Pest tests)
...
- backups: 4 metrics (last/storage/recovery/failed), recent backups
table with pagination, sticky config card (toggles for daily/snapshots/
replication + storage meter). 4 tests.
- team: 4 metrics (members/admins/invites/2fa), members table with
avatar+role+scope+2fa+last-active, open invitations table with
resend/revoke actions. 3 tests.
- security: 4 metrics (blocked24h/firewall-rules/ssl-expiring/2fa),
advisories panel (high+critical events), threat feed (live), SSL
certificates table with days-to-expiry. 3 tests.
- settings: 2-col layout with sticky left nav (workspace/notifications/
billing/api/danger), reactive section switching, workspace form,
billing card with quota meter, danger-zone with delete CTA. 4 tests.
- CSS additions: clu-settings-grid, clu-settings-nav, clu-danger.
- Routes: 4 Volt routes (backups/team/security/settings).
2026-05-31 23:04:18 +02:00
Boban Blaskovic
b15e6f2146
Page: Servers — Volt cards grid with gauges + 3 Pest tests
...
- pages/servers/index Volt: 4 metrics (active nodes, avg CPU, avg RAM,
maintenance), env segmented filter (all/prod/edge/staging), region select.
- Server card grid with country flag, name, env, spec line (vCPU/RAM/disk),
3 horizontal gauges (CPU/RAM/disk) color-coded warn>70 / bad>90,
sites_count footer, SSH + more row actions.
- CSS additions: clu-server-card/head/flag/name/meta/spec/foot, clu-gauge*.
- Routes: Volt::route servers.index.
- 3 Pest tests green (redirect, chrome+grid, env filter).
2026-05-31 22:52:01 +02:00
Boban Blaskovic
1622ac3a18
Page: Sites — Volt with search/filter/sort/pagination + 5 Pest tests
...
- pages/sites/index Volt: search by domain (debounced), 4-segment
status filter (all/updates/warnings/critical), server + sort selects,
paginated table (15/page).
- 4 metric tiles from Site aggregates (online/updates/pagespeed/visitors).
- Site cell with favicon initial, ssl/cache info, server/wp/php pills,
visitors + response, status health label, row actions.
- routes/web.php: Volt::route for sites.index.
- CSS additions: clu-page-title/sub, clu-seg, clu-ghost-btn, clu-toolbar,
clu-pager, clu-row-actions.
- 5 Pest tests green (redirect, chrome, list+paginate, search, segment filter).
2026-05-31 22:50:03 +02:00
Boban Blaskovic
21c2f8a63a
Page: Dashboard + App-Layout + Sidebar component
...
- layouts/app.blade.php rewritten as Volt-compatible layout with
clu-bg-aurora body, clu-app-grid (236px sidebar + main).
- components/clu/sidebar.blade.php: brand, workspace switch (Acme Cluster),
6 nav items with route-based active state, plan box (PRO, 87/100).
- routes/web.php: Volt::route for dashboard, placeholder routes
for sites/servers/backups/security/team/settings (sidebar links resolve).
- placeholder.blade.php: holds spaceholder pages with shared chrome.
- CSS: app-grid, sidebar, ws-switch, nav, plan-box, topbar, search,
icon-btn, metric, card, table, site-cell, favicon, health, feed.
- pages/dashboard Volt: 4 metrics (Sites Online, Ø Response, Updates,
Blocked/24h) computed from DB, top-8 sites table, top-8 activity feed.
- Test: tests/Feature/Pages/DashboardPageTest.php (3 green)
redirect-guest, render-auth, sees seeded site.
2026-05-31 22:38:12 +02:00
Boban Blaskovic
67598ab649
Portainer-ready compose stack + app changes
2026-05-31 17:04:03 +02:00
Boban Blaskovic
624b21fcb9
Initial CluPilot stack setup
...
Laravel 12 + Livewire v3 + Tailwind v4 + Reverb WebSocket
behind Nginx Proxy Manager (external SSL termination, HTTP-only internal).
MariaDB 11, Redis 7, Mailpit. Dark auth views.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 23:00:14 +02:00