Files
Claude d43f78b161 av: clone broadcastbeat sources + AV Beat rebrand (Phase 1)
- Replaces the prior Rocket scaffold (saved on pre-bb-clone-rollback branch)
- Domain: broadcastbeat.com -> avbeat.com
- Brand: Broadcast Beat -> AV Beat
- Slug: broadcastbeat -> avbeat (package, identifiers)
- Schema fallback: bb -> av (env var name unchanged)
- Placeholder AV BEAT logo (gold->red gradient) at /assets/logos/av.svg
- All BB/RMP logo references repointed

Outstanding before public DNS swap:
  - Supabase av schema bootstrap (mirror of bb tables)
  - WordPress archive import (avbeat-com -> av.articles)
  - Coolify env vars
  - dev-avbeat.onsethost.com staging deploy + visual review
2026-06-02 15:32:56 +00:00

120 lines
4.8 KiB
TypeScript

import { serve } from "https://deno.land/std@0.192.0/http/server.ts";
serve(async (req) => {
// ✅ CORS preflight
if (req?.method === "OPTIONS") {
return new Response("ok", {
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "POST, OPTIONS",
"Access-Control-Allow-Headers": "*",
},
});
}
try {
const { email, inviterName, role, token, message, siteUrl } = await req?.json();
const RESEND_API_KEY = Deno?.env?.get("RESEND_API_KEY");
if (!RESEND_API_KEY) {
throw new Error("RESEND_API_KEY is not set");
}
const acceptUrl = `${siteUrl || "https://avbeat.com"}/invite/accept?token=${token}`;
const roleLabel = role === "editor" ? "Editor" : role === "admin" ? "Administrator" : "Contributor";
const htmlBody = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body style="margin:0;padding:0;background:#0d1117;font-family:Arial,sans-serif;">
<table width="100%" cellpadding="0" cellspacing="0" style="background:#0d1117;padding:40px 20px;">
<tr>
<td align="center">
<table width="600" cellpadding="0" cellspacing="0" style="background:#111827;border-radius:8px;overflow:hidden;border:1px solid #1f2937;">
<tr>
<td style="background:#1a2535;padding:24px 32px;border-bottom:1px solid #2a3a50;">
<p style="margin:0;color:#3b82f6;font-size:13px;font-weight:700;letter-spacing:2px;text-transform:uppercase;">BroadcastBeat</p>
<p style="margin:4px 0 0;color:#9ca3af;font-size:12px;">Digital Platform for Broadcast Engineering</p>
</td>
</tr>
<tr>
<td style="padding:32px;">
<h1 style="margin:0 0 16px;color:#f9fafb;font-size:22px;font-weight:700;">You've been invited to contribute</h1>
<p style="margin:0 0 16px;color:#9ca3af;font-size:15px;line-height:1.6;">
${inviterName || "A BroadcastBeat administrator"} has invited you to join BroadcastBeat as a <strong style="color:#3b82f6;">${roleLabel}</strong>.
</p>
${message ? `<div style="background:#1f2937;border-left:3px solid #3b82f6;padding:12px 16px;border-radius:4px;margin:0 0 24px;">
<p style="margin:0;color:#d1d5db;font-size:14px;font-style:italic;">"${message}"</p>
</div>` : ""}
<p style="margin:0 0 24px;color:#9ca3af;font-size:14px;line-height:1.6;">
As a ${roleLabel}, you'll be able to submit articles for publication on our platform. Click the button below to accept your invitation and set up your account.
</p>
<table cellpadding="0" cellspacing="0">
<tr>
<td style="background:#3b82f6;border-radius:6px;">
<a href="${acceptUrl}" style="display:inline-block;padding:12px 28px;color:#ffffff;font-size:14px;font-weight:700;text-decoration:none;letter-spacing:0.5px;">Accept Invitation</a>
</td>
</tr>
</table>
<p style="margin:24px 0 0;color:#6b7280;font-size:12px;">
This invitation expires in 7 days. If you did not expect this invitation, you can safely ignore this email.
</p>
<p style="margin:12px 0 0;color:#4b5563;font-size:11px;word-break:break-all;">
Or copy this link: ${acceptUrl}
</p>
</td>
</tr>
<tr>
<td style="background:#0d1117;padding:16px 32px;border-top:1px solid #1f2937;">
<p style="margin:0;color:#4b5563;font-size:11px;text-align:center;">© BroadcastBeat · Digital Platform for Broadcast Engineering</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>`;
const res = await fetch("https://api.resend.com/emails", {
method: "POST",
headers: {
"Authorization": `Bearer ${RESEND_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
from: "onboarding@resend.dev",
to: [email],
subject: `You've been invited to contribute to BroadcastBeat`,
html: htmlBody,
}),
});
const data = await res?.json();
if (!res?.ok) {
throw new Error(data?.message || "Failed to send email");
}
return new Response(JSON.stringify({ success: true, id: data.id }), {
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
});
} catch (error) {
return new Response(JSON.stringify({ error: error.message }), {
status: 500,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
});
}
});