- Workspace.getRouteKeyName()='ulid' so route() generates ULID URLs not ID
- QR modal 4xl→5xl; import QRCode in @script→window.QRCode (no ESM in @script)
- Bio slug unique rule scoped to (workspace_id, domain_id) not global
- updateActiveNav uses URL.pathname not raw getAttribute('href') (absolute URL fix)
- Add resources/views/components/ui/copy-button.blade.php Alpine component
- Analytics Index.render/baseQuery use $workspaceId not require_workspace() — prevents RuntimeException on Livewire action calls without middleware
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- QR Code: split-pane wizard with type tabs, live preview canvas, style/frame/advanced options
- UTM Builder modal: generate URL with UTM params, copy + create short link
- A/B Test: LinkVariants modal with auto-balance weights (min 2, max 5 variants)
- AI: SlugSuggester service (3 suggestions via claude-haiku), AI-slug button in CreateLink
- AI pages: /ai/insights, /ai/anomalies, /ai/ab-generator with sidebar entry
- Analytics: #[Url] attributes for range/country/device/linkId, 24h/7d/30d/90d buttons
- QR enum migration (MySQL-only guard) to add email/phone/sms/location types
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- All create modals now validate→create→dispatch(kebab-case event)→toast→close
- All edit/delete modals dispatch kebab-case events to Index classes
- Index components listen via #[On] and call resetPage() to refresh
- QR Code save() validates url field conditionally per type
- Tests updated to assert kebab-case event names
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add POST /logout route (was missing from auth.php)
- Add workspaceId property to Analytics component (fixes #[On] binding)
- tests/bootstrap.php: force APP_ENV=testing before Docker OS env takes over
- phpunit.xml: use tests/bootstrap.php + force=true on APP_ENV
- Update AuthenticationTest, ProfileTest, LoginRateLimitTest to match current app structure
- Add tests/Feature/Livewire/WorkspacePagesTest.php: 11 workspace route tests
- scripts/smoke-test.sh: HTTP smoke test for all routes
- Result: 75/75 tests passing, all smoke routes 302→login
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Overwrites the Analytics Index stub with a full Livewire component that
loads today's click count from the clicks table (workspace_id is a direct
column) and listens for live updates via Echo/Reverb using the
#[On('echo:workspace.{workspaceId}.analytics,click.recorded')] attribute.
Creates the corresponding blade view with a today-counter card and a
live recent-clicks feed (last 10 entries).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add Links Livewire page (Index component + blade view) with live search,
status filter, paginated table, and delete action using DeleteLink for
cache invalidation. Register workspace-scoped route group under
w/{workspace} with ResolveWorkspace middleware. Add stub Livewire pages
for QrCodes, Bio, Analytics, Domains, Settings, and Billing with a shared
coming-soon view.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>