boban
308778b99d
fix(bio): prevent duplicate slugs within same workspace
...
- Migration: add UNIQUE(workspace_id, slug) to bio_pages
Old (subdomain_host, slug) unique allowed MySQL NULL bypass —
two free-plan bios with NULL subdomain_host + same slug were not caught
- Edit::save(): validate slug uniqueness before update, dispatch toast on conflict
- Edit::save(): validate slug format (alphanumeric + dash/underscore, max 64)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 23:09:17 +02:00
boban
deb5f310a1
fix(bio): plan-aware URL + plan-seeder + ulid→slug fix
...
- Migration: add bio_pages_limit to plans, make limit cols nullable (agency=unlimited)
- PlanSeeder: 4 plans (free/pro/business/agency) with tier/features/bio_pages_limit
- workspaces:assign-default-plan command: assigns free plan to unassigned workspaces
- BioPage::publicUrl(): free=apex-path, pro+=subdomain, custom=custom-domain
- Security: str_ends_with check uses '.'.$apex to prevent evilnimu.li bypass
- BioPage::shortPublicUrl(): URL without scheme for display
- PlanLimitsService: use bio_pages_limit column (was features['bio_pages']), null=unlimited
- BioPageController: fix $bio → $page variable (view expects $page)
- Bio index/edit views: use publicUrl()/shortPublicUrl(), not hardcoded ULID URLs
- Bio edit view: publicUrlBase/displayUrlBase from component (plan-aware prefix)
- Create-bio modal: plan-aware URL prefix display
- PlanFactory/WorkspaceFactory: free()/pro() states for tests
- Tests: PublicUrlTest (5 cases), Free404FixTest (3 cases)
Known pre-existing failure (not caused by this change):
- Tests\Feature\Auth\EmailVerificationTest::email can be verified
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 22:44:54 +02:00
boban
2d231fe6b8
fix: bio public /b/{slug} route + QR types + code cleanup
...
- Add GET /b/{slug} route alias (nimu.li shorthand for bio pages)
- QR wizard: extend type enum to include email, phone, sms, location
- Modals: replace FQCN references with imported class aliases (Pint clean)
- Analytics: add missing Carbon/Builder imports, improve return types
- Octane config: add ResetCurrentWorkspace import
- scripts/crawl-all.sh: curl+PHPUnit based crawler (replaces Playwright)
All 158 tests pass, PHPStan clean, Pint clean.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 16:41:05 +02:00
boban
257d1b94f1
feat: QR wizard, UTM Builder, A/B variants, AI features, analytics URL filters
...
- 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>
2026-05-16 15:14:19 +02:00
boban
8f1398380f
fix(billing): pm_type/pm_last_four migration, narrow CSRF exclusion, EU paper size
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 01:46:54 +02:00
boban
3b19bbe88f
fix(db): null-safe unique keys on rollup tables, workspace slug unique, link slug scoping
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 00:11:39 +02:00
boban
23fd5a5e30
feat(db): add all Phase 1 migrations
...
Creates all Nimuli domain tables: plans, workspaces, workspace_members,
workspace_invitations, billing_profiles, domains, links, link_variants,
qr_codes, bio_pages, bio_blocks, clicks (+ hourly/daily/by_referrer/by_utm
aggregates), translations, webhooks, webhook_deliveries. Also extends the
users table with ulid, 2FA fields, locale, theme, default_workspace_id,
and soft deletes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 00:04:01 +02:00
boban
25dddf5293
feat: initial Nimuli scaffold with Laravel 12, Livewire 3, Octane, Reverb, Docker
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 23:51:57 +02:00