feat(pitch-deck): branded short links for magic URLs (pitch.breakpilot.ai/p/ab3xk2)
Build pitch-deck / build-push-deploy (push) Successful in 1m31s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 32s
CI / test-python-voice (push) Successful in 34s
CI / test-bqas (push) Successful in 30s

- New pitch_short_links table stores 6-char alphanumeric codes mapped to magic link tokens
- GET /p/[code] redirects to /auth/verify?token=... (302, validates expiry)
- All magic link generation points (invite, generate-link, resend) now create a short code
- Emails (invite + resend) use the short URL — less token-like, cleaner for spam filters
- Copy-link UI shows short URL prominently with full URL as fallback
- Migration 008 added to /api/admin/migrate

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-05-07 10:34:24 +02:00
parent 54f0919b73
commit 76aad8b1d1
9 changed files with 87 additions and 17 deletions
@@ -116,11 +116,12 @@ export default function InvestorDetailPage() {
setBusy(false)
if (res.ok) {
const d = await res.json()
const link = d.short_url || d.url
try {
await navigator.clipboard.writeText(d.url)
flashToast('Magic link copied to clipboard')
await navigator.clipboard.writeText(link)
flashToast('Short link copied to clipboard')
} catch {
flashToast(`Link (copy manually): ${d.url}`)
flashToast(`Link (copy manually): ${link}`)
}
} else {
const err = await res.json().catch(() => ({}))
@@ -35,7 +35,7 @@ export default function NewInvestorPage() {
const [closingEdited, setClosingEdited] = useState(false)
const [error, setError] = useState('')
const [submitting, setSubmitting] = useState(false)
const [createdLink, setCreatedLink] = useState<string | null>(null)
const [createdLink, setCreatedLink] = useState<{ short: string; full: string } | null>(null)
const [copied, setCopied] = useState(false)
const prevLang = useRef<Lang>('de')
@@ -85,7 +85,7 @@ export default function NewInvestorPage() {
if (res.ok) {
const data = await res.json()
if (!sendEmail) {
setCreatedLink(data.magic_link_url)
setCreatedLink({ short: data.short_url, full: data.magic_link_url })
} else {
router.push('/pitch-admin/investors')
router.refresh()
@@ -103,7 +103,7 @@ export default function NewInvestorPage() {
async function copyLink() {
if (!createdLink) return
await navigator.clipboard.writeText(createdLink)
await navigator.clipboard.writeText(createdLink.short)
setCopied(true)
setTimeout(() => setCopied(false), 2000)
}
@@ -130,9 +130,15 @@ export default function NewInvestorPage() {
<p className="text-sm text-white/50">No email was sent. Copy the magic link below to use in your outreach.</p>
</div>
<div className="bg-black/40 border border-white/10 rounded-xl p-4 text-left">
<p className="text-[10px] font-semibold text-white/40 uppercase tracking-wider mb-2">Magic Link</p>
<p className="text-xs text-indigo-300 break-all leading-relaxed">{createdLink}</p>
<div className="bg-black/40 border border-white/10 rounded-xl p-4 text-left space-y-3">
<div>
<p className="text-[10px] font-semibold text-white/40 uppercase tracking-wider mb-1">Short Link <span className="text-green-400/70 normal-case font-normal">(use this in emails)</span></p>
<p className="text-sm text-indigo-300 font-mono">{createdLink?.short}</p>
</div>
<div>
<p className="text-[10px] font-semibold text-white/25 uppercase tracking-wider mb-1">Full Link</p>
<p className="text-[10px] text-white/30 break-all leading-relaxed font-mono">{createdLink?.full}</p>
</div>
</div>
<div className="flex items-center justify-center gap-3">
@@ -59,11 +59,12 @@ export default function InvestorsPage() {
setBusy(null)
if (res.ok) {
const data = await res.json()
const link = data.short_url || data.url
try {
await navigator.clipboard.writeText(data.url)
flashToast('Magic link copied to clipboard')
await navigator.clipboard.writeText(link)
flashToast('Short link copied to clipboard')
} catch {
flashToast(`Link (copy manually): ${data.url}`)
flashToast(`Link (copy manually): ${link}`)
}
} else {
const err = await res.json().catch(() => ({}))