Function bodies 101 total
MetricCard function · typescript · L32-L50 (19 LOC)app/admin/dashboard/page.tsx
function MetricCard({ title, value, change, icon }: {
title: string;
value: string | number;
change?: string;
icon: string;
}) {
return (
<div className="bg-white rounded-lg shadow p-6 border border-gray-200">
<div className="flex items-center justify-between mb-2">
<span className="text-gray-600 text-sm font-medium">{title}</span>
<span className="text-2xl">{icon}</span>
</div>
<div className="text-3xl font-bold text-gray-900 mb-1">{value}</div>
{change && (
<div className="text-sm text-green-600">{change}</div>
)}
</div>
);
}ErrorModal function · typescript · L52-L153 (102 LOC)app/admin/dashboard/page.tsx
function ErrorModal({ error, onClose }: { error: ErrorDetail; onClose: () => void }) {
return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-lg shadow-xl max-w-3xl w-full max-h-[90vh] overflow-auto">
{/* Header */}
<div className="sticky top-0 bg-white border-b border-gray-200 px-6 py-4 flex items-center justify-between">
<div>
<h3 className="text-xl font-bold text-gray-900">Error Details</h3>
<p className="text-sm text-gray-500 mt-1">{error.timestamp}</p>
</div>
<button
onClick={onClose}
className="text-gray-400 hover:text-gray-600 text-2xl leading-none"
>
×
</button>
</div>
{/* Content */}
<div className="p-6 space-y-4">
{/* Error Type */}
<div>
<label className="text-sm font-semibold text-gray-700 block mb-1DashboardPage function · typescript · L201-L494 (294 LOC)app/admin/dashboard/page.tsx
export default function DashboardPage() {
const [metrics, setMetrics] = useState<MetricData | null>(null);
const [healthChecks, setHealthChecks] = useState<HealthCheck[]>([]);
const [loading, setLoading] = useState(true);
const [selectedError, setSelectedError] = useState<ErrorDetail | null>(null);
const [lastUpdate, setLastUpdate] = useState<Date>(new Date());
useEffect(() => {
loadDashboardData();
}, []);
async function loadDashboardData() {
setLoading(true);
try {
// Simulate API calls - replace with actual API
await new Promise(resolve => setTimeout(resolve, 500));
// Mock metrics
setMetrics({
users: 1234,
sessions: 2456,
pageviews: 5678,
conversions: 89,
avgSessionDuration: 145,
});
// Mock health checks with detailed errors
const checks: HealthCheck[] = [
{
name: 'Submit Quiz API',
status: 'healthy',
message: 'Responding normally'loadDashboardData function · typescript · L212-L325 (114 LOC)app/admin/dashboard/page.tsx
async function loadDashboardData() {
setLoading(true);
try {
// Simulate API calls - replace with actual API
await new Promise(resolve => setTimeout(resolve, 500));
// Mock metrics
setMetrics({
users: 1234,
sessions: 2456,
pageviews: 5678,
conversions: 89,
avgSessionDuration: 145,
});
// Mock health checks with detailed errors
const checks: HealthCheck[] = [
{
name: 'Submit Quiz API',
status: 'healthy',
message: 'Responding normally',
lastChecked: new Date().toISOString(),
},
{
name: 'Get Results API',
status: 'healthy',
message: 'Responding normally',
lastChecked: new Date().toISOString(),
},
{
name: 'Generate Image API',
status: 'error',
message: 'Timeout after 30s',
lastChecked: new Date().toISOString(),
details: {
Bar function · typescript · L67-L76 (10 LOC)app/admin/insights/page.tsx
function Bar({ pct, color }: { pct: number; color: string }) {
return (
<div className="w-full bg-gray-100 rounded-full h-2.5 overflow-hidden">
<div
className="h-2.5 rounded-full transition-all duration-500"
style={{ width: `${Math.max(pct, pct > 0 ? 1 : 0)}%`, backgroundColor: color }}
/>
</div>
);
}Card function · typescript · L78-L84 (7 LOC)app/admin/insights/page.tsx
function Card({ children, className = "" }: { children: React.ReactNode; className?: string }) {
return (
<div className={`bg-white rounded-xl border border-gray-200 shadow-sm p-6 ${className}`}>
{children}
</div>
);
}SectionHeader function · typescript · L86-L93 (8 LOC)app/admin/insights/page.tsx
function SectionHeader({ title, subtitle }: { title: string; subtitle?: string }) {
return (
<div className="mb-5">
<h2 className="text-xl font-bold text-gray-900">{title}</h2>
{subtitle && <p className="text-sm text-gray-500 mt-1">{subtitle}</p>}
</div>
);
}Repobility · code-quality intelligence · https://repobility.com
generateInsightsSynthesis function · typescript · L95-L152 (58 LOC)app/admin/insights/page.tsx
function generateInsightsSynthesis(data: InsightsData): string[] {
const top = data.archetypeRanked[0];
const second = data.archetypeRanked[1];
const topRole = Object.entries(data.roleCounts).sort((a, b) => b[1] - a[1])[0][0];
const insights: string[] = [];
if (top) {
if (top.id === "craft" || top.id === "vision") {
insights.push(
`${top.pct}% of respondents identify as ${top.label}s — the largest segment. This signals a market grappling with quality and strategy in an AI-saturated landscape. These marketers aren't looking for shortcuts; they want tools that help them do their best work at scale.`
);
} else if (top.id === "maverick") {
insights.push(
`${top.pct}% of respondents are Mavericks — a strong signal that this audience is AI-forward and willing to experiment. They're likely already using AEO tools and are primed for advanced workflows rather than introductory content.`
);
} else if (top.id === "spark") {
insiQuestionSection function · typescript · L154-L229 (76 LOC)app/admin/insights/page.tsx
function QuestionSection({
questions,
roleKey,
distributions,
answeredSubmissions,
isEstimated,
}: {
questions: QuestionInterpretation[];
roleKey: string;
distributions: Record<string, { answer: string; count: number; pct: number }[]>;
answeredSubmissions: number;
isEstimated: boolean;
}) {
const hasData = answeredSubmissions > 0 || isEstimated;
return (
<div className="space-y-6">
{questions.map((q) => {
const dist = distributions[q.id] || [];
const distMap: Record<string, { count: number; pct: number }> = {};
for (const d of dist) distMap[d.answer] = { count: d.count, pct: d.pct };
return (
<Card key={q.id}>
<div className="mb-4">
<span className="text-xs font-semibold uppercase tracking-wide text-gray-400">
{q.id.toUpperCase()}
</span>
<h3 className="text-base font-semibold text-gray-900 mt-1">{q.text}</h3>
</div>
InsightsPage function · typescript · L231-L521 (291 LOC)app/admin/insights/page.tsx
export default function InsightsPage() {
const [data, setData] = useState<InsightsData | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [activeRole, setActiveRole] = useState<string>("all");
const [activeQuestionRole, setActiveQuestionRole] = useState<"ic" | "manager" | "executive">("ic");
useEffect(() => {
fetch("/api/insights")
.then((r) => r.json())
.then((d) => {
if (d.error) throw new Error(d.error);
setData(d);
})
.catch((e) => setError(e.message))
.finally(() => setLoading(false));
}, []);
if (loading) {
return (
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
<div className="text-gray-500 text-sm">Loading insights...</div>
</div>
);
}
if (error || !data) {
return (
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
<div className="text-rDELETE function · typescript · L4-L22 (19 LOC)app/api/admin/remove-user/route.ts
export async function DELETE(request: NextRequest) {
const secret = request.headers.get("x-admin-secret");
if (!secret || secret !== process.env.ADMIN_SECRET) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const userId = request.nextUrl.searchParams.get("userId");
if (!userId) {
return NextResponse.json({ error: "Missing userId" }, { status: 400 });
}
const deleted = await redis.del(`quiz:${userId}`);
return NextResponse.json({
success: true,
deleted: deleted > 0,
message: deleted > 0 ? `Removed quiz:${userId}` : `No record found for ${userId}`,
});
}verifySlackSignature function · typescript · L5-L20 (16 LOC)app/api/admin/slack-action/route.ts
function verifySlackSignature(request: NextRequest, body: string): boolean {
const signingSecret = process.env.SLACK_SIGNING_SECRET;
if (!signingSecret) return false;
const timestamp = request.headers.get("x-slack-request-timestamp") || "";
const slackSig = request.headers.get("x-slack-signature") || "";
// Reject requests older than 5 minutes
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const baseString = `v0:${timestamp}:${body}`;
const hmac = crypto.createHmac("sha256", signingSecret).update(baseString).digest("hex");
const computedSig = `v0=${hmac}`;
return crypto.timingSafeEqual(Buffer.from(computedSig), Buffer.from(slackSig));
}POST function · typescript · L22-L100 (79 LOC)app/api/admin/slack-action/route.ts
export async function POST(request: NextRequest) {
const body = await request.text();
if (!verifySlackSignature(request, body)) {
return NextResponse.json({ error: "Invalid signature" }, { status: 401 });
}
const params = new URLSearchParams(body);
const payload = JSON.parse(params.get("payload") || "{}");
const action = payload.actions?.[0];
if (!action) {
return NextResponse.json({ error: "No action" }, { status: 400 });
}
const userId = action.value;
const actionId = action.action_id;
const responseUrl = payload.response_url;
const userName = payload.user?.name || "Someone";
if (actionId === "remove_user") {
// Delete from Redis
const deleted = await redis.del(`quiz:${userId}`);
// Update the Slack message to show it was removed
if (responseUrl) {
const originalBlocks = payload.message?.blocks || [];
// Keep the info and image blocks, replace the actions block
const updatedBlocks = originalBlocks
.filtnormalizeArchetypeId function · typescript · L12-L14 (3 LOC)app/api/all-cards/route.ts
function normalizeArchetypeId(id: string): string {
return ARCHETYPE_ID_MAP[id] || id;
}OPTIONS function · typescript · L28-L30 (3 LOC)app/api/all-cards/route.ts
export async function OPTIONS() {
return new NextResponse(null, { status: 204, headers: CORS_HEADERS });
}Repobility analyzer · published findings · https://repobility.com
GET function · typescript · L32-L123 (92 LOC)app/api/all-cards/route.ts
export async function GET() {
try {
// Return cached response if fresh
if (cachedResponse && Date.now() - cachedResponse.timestamp < CACHE_TTL_MS) {
return NextResponse.json({ cards: cachedResponse.cards }, { headers: CORS_HEADERS });
}
const baseUrl = process.env.VERCEL_PROJECT_PRODUCTION_URL
? `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`
: "https://campaign-quiz.vercel.app";
const cards: Array<Record<string, unknown>> = [];
let cursor = "0";
do {
const [nextCursor, keys] = await redis.scan(cursor, "MATCH", "quiz:*", "COUNT", 100);
cursor = nextCursor;
if (keys.length > 0) {
const pipeline = redis.pipeline();
for (const key of keys) {
pipeline.get(key);
}
const results = await pipeline.exec();
if (results) {
for (const [err, val] of results) {
if (err || !val) continue;
try {
const data = JSON.parse(val as stOPTIONS function · typescript · L17-L19 (3 LOC)app/api/enrich-linkedin/route.ts
export async function OPTIONS() {
return new NextResponse(null, { status: 204, headers: CORS_HEADERS });
}POST function · typescript · L21-L168 (148 LOC)app/api/enrich-linkedin/route.ts
export async function POST(request: NextRequest) {
try {
const { userId, linkedinUrl } = await request.json();
if (!userId || !linkedinUrl) {
return NextResponse.json(
{ success: false, error: "userId and linkedinUrl are required." },
{ status: 400, headers: CORS_HEADERS }
);
}
// Fetch existing data from Redis
const existing = await redis.get(`quiz:${userId}`);
if (!existing) {
return NextResponse.json(
{ success: false, error: "User not found." },
{ status: 404, headers: CORS_HEADERS }
);
}
const data = JSON.parse(existing);
// If already enriched, verify the headshot blob is still accessible
if (data.firstName && data.headshotUrl && data.enriched) {
let headshotValid = false;
try {
const headCheck = await fetch(data.headshotUrl, { method: 'HEAD' });
headshotValid = headCheck.ok;
} catch {
// Network error - treat as invalid
}
ifOPTIONS function · typescript · L13-L15 (3 LOC)app/api/generate-image/route.ts
export async function OPTIONS() {
return new NextResponse(null, { status: 204, headers: CORS_HEADERS });
}POST function · typescript · L19-L194 (176 LOC)app/api/generate-image/route.ts
export async function POST(request: NextRequest) {
try {
const { userName, archetype, tagline, photoBase64, photoUrl } = await request.json();
const apiKey = process.env.GOOGLE_API_KEY;
if (!apiKey) {
return NextResponse.json(
{ error: "Google API key not configured. Please add GOOGLE_API_KEY to your environment variables." },
{ status: 500, headers: CORS_HEADERS }
);
}
const ai = new GoogleGenAI({ apiKey });
// Resolve photo data: use base64 directly, or download from URL
let resolvedPhotoBase64 = photoBase64;
if (!resolvedPhotoBase64 && photoUrl) {
console.log(`Downloading photo from URL: ${photoUrl.substring(0, 100)}...`);
try {
const imageResponse = await fetch(photoUrl);
if (imageResponse.ok) {
const arrayBuffer = await imageResponse.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);
const contentType = (imageResponse.headers.get('content-type') || 'imagenormalizeArchetypeId function · typescript · L13-L15 (3 LOC)app/api/get-results/route.ts
function normalizeArchetypeId(id: string): string {
return ARCHETYPE_ID_MAP[id] || id;
}OPTIONS function · typescript · L23-L25 (3 LOC)app/api/get-results/route.ts
export async function OPTIONS() {
return new NextResponse(null, { status: 204, headers: CORS_HEADERS });
}GET function · typescript · L27-L112 (86 LOC)app/api/get-results/route.ts
export async function GET(request: NextRequest) {
try {
const userId = request.nextUrl.searchParams.get("userId");
if (!userId) {
return NextResponse.json(
{ success: false, error: "userId query parameter is required." },
{ status: 400, headers: CORS_HEADERS }
);
}
const data = await redis.get(`quiz:${userId}`);
if (!data) {
return NextResponse.json(
{ success: false, error: "Results not found for the given userId." },
{ status: 404, headers: CORS_HEADERS }
);
}
const parsed = JSON.parse(data);
// Normalize old archetype IDs (trendsetter→maverick, etc.) for existing records
if (parsed.archetype?.id) {
parsed.archetype.id = normalizeArchetypeId(parsed.archetype.id);
}
// Resolve base URL for absolute image paths
const baseUrl = process.env.VERCEL_PROJECT_PRODUCTION_URL
? `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`
: "https://campaign-quiz.vercel.apWant this analysis on your repo? https://repobility.com/scan/
estimateAnswerDistributions function · typescript · L25-L28 (4 LOC)app/api/insights/route.ts
function estimateAnswerDistributions(
archetypeByRole: Record<string, Record<string, number>>,
roleCounts: Record<string, number>
): Record<string, Record<string, { answer: string; count: number; pct: number }[]>> {GET function · typescript · L59-L206 (148 LOC)app/api/insights/route.ts
export async function GET() {
try {
let cursor = "0";
const archetypeCounts: Record<string, number> = {};
const roleCounts: Record<string, number> = { ic: 0, manager: 0, executive: 0 };
const archetypeByRole: Record<string, Record<string, number>> = {
ic: {},
manager: {},
executive: {},
};
const dailyCounts: Record<string, number> = {};
const companyCounts: Record<string, number> = {};
const answerCounts: AnswerCounts = { ic: {}, manager: {}, executive: {} };
let answeredSubmissions = 0;
let wantsDemoCount = 0;
let total = 0;
do {
const [nextCursor, keys] = await redis.scan(cursor, "MATCH", "quiz:*", "COUNT", 200);
cursor = nextCursor;
if (keys.length === 0) continue;
const values = await redis.mget(...keys);
for (const val of values) {
if (!val) continue;
let data: Record<string, any>;
try {
data = JSON.parse(val);
} catch {
continue;OPTIONS function · typescript · L12-L14 (3 LOC)app/api/og-image/route.tsx
export async function OPTIONS() {
return new Response(null, { status: 204, headers: CORS_HEADERS });
}loadFonts function · typescript · L19-L32 (14 LOC)app/api/og-image/route.tsx
async function loadFonts(baseUrl: string) {
if (fontCache) return fontCache;
const cdnBase = process.env.VERCEL_PROJECT_PRODUCTION_URL
? `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`
: baseUrl;
const [serrif, serrifItalic, saans, saansMono] = await Promise.all([
fetch(`${cdnBase}/fonts/Serrif-400.ttf`).then((r) => r.arrayBuffer()),
fetch(`${cdnBase}/fonts/Serrif-400-Italic.ttf`).then((r) => r.arrayBuffer()),
fetch(`${cdnBase}/fonts/Saans-Regular.woff`).then((r) => r.arrayBuffer()),
fetch(`${cdnBase}/fonts/SaansMono-Medium.otf`).then((r) => r.arrayBuffer()),
]);
fontCache = { serrif, serrifItalic, saans, saansMono };
return fontCache;
}POST function · typescript · L4-L36 (33 LOC)app/api/save-card-url/route.ts
export async function POST(request: NextRequest) {
try {
const { userId, cardUrl, field } = await request.json();
if (!userId || !cardUrl) {
return NextResponse.json({ error: "Missing userId or cardUrl" }, { status: 400 });
}
// Read existing data, add cardUrl, write back with same TTL
const existing = await redis.get(`quiz:${userId}`);
if (!existing) {
return NextResponse.json({ error: "User not found" }, { status: 404 });
}
const parsed = typeof existing === "string" ? JSON.parse(existing) : existing;
// Use custom field name if provided, otherwise default to cardUrl
const fieldName = field || "cardUrl";
parsed[fieldName] = cardUrl;
// Get remaining TTL and preserve it
const ttl = await redis.ttl(`quiz:${userId}`);
if (ttl > 0) {
await redis.set(`quiz:${userId}`, JSON.stringify(parsed), "EX", ttl);
} else {
await redis.set(`quiz:${userId}`, JSON.stringify(parsed));
}
return NextResponsenormalizeArchetypeId function · typescript · L12-L14 (3 LOC)app/api/share-copy/route.ts
function normalizeArchetypeId(id: string): string {
return ARCHETYPE_ID_MAP[id] || id;
}OPTIONS function · typescript · L32-L34 (3 LOC)app/api/share-copy/route.ts
export async function OPTIONS() {
return new NextResponse(null, { status: 204, headers: CORS_HEADERS });
}GET function · typescript · L36-L118 (83 LOC)app/api/share-copy/route.ts
export async function GET(request: NextRequest) {
try {
const userId = request.nextUrl.searchParams.get("userId");
if (!userId) {
return NextResponse.json(
{ success: false, error: "userId query parameter is required." },
{ status: 400, headers: CORS_HEADERS }
);
}
const data = await redis.get(`quiz:${userId}`);
if (!data) {
return NextResponse.json(
{ success: false, error: "Results not found for the given userId." },
{ status: 404, headers: CORS_HEADERS }
);
}
const parsed = JSON.parse(data);
const archetypeId = normalizeArchetypeId(parsed.archetype?.id || "maverick");
const archetypeName = parsed.archetype?.name || "Champion";
const tagline = parsed.archetype?.tagline || "";
const mostLikelyTo = parsed.bullets?.mostLikelyTo || "";
const typicallySpending = parsed.bullets?.typicallySpending || "";
const favoritePhrase = parsed.bullets?.favoritePhrase || "";
const baProvenance: Repobility (https://repobility.com) — every score reproducible from /scan/
OPTIONS function · typescript · L19-L21 (3 LOC)app/api/submit-quiz/route.ts
export async function OPTIONS() {
return new NextResponse(null, { status: 204, headers: CORS_HEADERS });
}POST function · typescript · L23-L278 (256 LOC)app/api/submit-quiz/route.ts
export async function POST(request: NextRequest) {
try {
const body = await request.json();
let { firstName, lastName, company, title } = body;
const { role, answers, email, headshotUrl, stippleImageUrl, linkedinUrl, wantsDemo } = body;
// Validate role
if (!role || !VALID_ROLES.has(role)) {
return NextResponse.json(
{ success: false, error: `Invalid role. Must be one of: ${[...VALID_ROLES].join(", ")}` },
{ status: 400, headers: CORS_HEADERS }
);
}
// Validate answers
if (!Array.isArray(answers) || answers.length !== REQUIRED_ANSWER_COUNT) {
return NextResponse.json(
{ success: false, error: `Exactly ${REQUIRED_ANSWER_COUNT} answers are required.` },
{ status: 400, headers: CORS_HEADERS }
);
}
for (const ans of answers) {
if (!ans.question || typeof ans.question !== "number" || ans.question < 1 || ans.question > 6) {
return NextResponse.json(
{ success: false, eOPTIONS function · typescript · L10-L12 (3 LOC)app/api/upload-card/route.ts
export async function OPTIONS() {
return new NextResponse(null, { status: 204, headers: CORS_HEADERS });
}POST function · typescript · L14-L51 (38 LOC)app/api/upload-card/route.ts
export async function POST(request: NextRequest) {
try {
const { imageBase64, uniqueId } = await request.json();
if (!imageBase64) {
return NextResponse.json(
{ error: 'No image data provided' },
{ status: 400, headers: CORS_HEADERS }
);
}
// Remove data URL prefix if present (handle all formats)
const base64Data = imageBase64.replace(/^data:[^;]+;base64,/, '');
// Convert base64 to buffer
const buffer = Buffer.from(base64Data, 'base64');
// Generate a unique filename
const filename = `cards/${uniqueId || Date.now()}.png`;
// Upload to Vercel Blob
const blob = await put(filename, buffer, {
access: 'public',
contentType: 'image/png',
});
return NextResponse.json({
success: true,
url: blob.url,
}, { headers: CORS_HEADERS });
} catch (error) {
console.error('Upload error:', error);
return NextResponse.json(
{ error: 'Failed to upload image', details: String(eRootLayout function · typescript · L39-L65 (27 LOC)app/layout.tsx
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en" prefix="og: http://ogp.me/ns#">
<head>
<Script
src="https://www.googletagmanager.com/gtag/js?id=G-41PB5YFX2D"
strategy="afterInteractive"
/>
<Script id="gtag-init" strategy="afterInteractive">
{`window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('js',new Date());gtag('config','G-41PB5YFX2D');`}
</Script>
</head>
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased bg-background text-foreground`}
>
<LogRocketProvider />
<ErrorBoundary>
{children}
</ErrorBoundary>
</body>
</html>
);
}Home function · typescript · L4-L63 (60 LOC)app/page.tsx
export default function Home() {
return (
<div className="min-h-screen relative" style={{ background: 'linear-gradient(180deg, #00CE50 0%, #00250E 31.25%)' }}>
{/* Hero background illustration — pinned to top, centered */}
<img
src="/images/hero-illustration.avif"
alt=""
style={{
position: 'absolute',
top: '-100px',
left: '50%',
transform: 'translateX(-50%)',
width: '1135px',
height: '1135px',
pointerEvents: 'none',
opacity: 0.4,
}}
/>
<div className="relative">
{/* Hero Section */}
<section className="relative pt-24 md:pt-36 pb-16 px-6 overflow-hidden">
<div className="relative max-w-4xl mx-auto text-center">
<p className="text-white/80 text-[24px] md:text-[36px] lg:text-[42px] mb-2 leading-tight" style={{ fontFamily: 'Serrif, serif' }}>
Get your player card
</p>
<h1 PreviewContent function · typescript · L20-L152 (133 LOC)app/preview/page.tsx
function PreviewContent() {
const searchParams = useSearchParams();
const userId = searchParams.get("userId") || "";
const [data, setData] = useState<ResultData | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
if (!userId) {
setError("No userId provided");
setLoading(false);
return;
}
fetch(`/api/get-results?userId=${userId}`)
.then((res) => res.json())
.then((d) => {
if (d.success) setData(d);
else setError(d.error || "Not found");
})
.catch((err) => setError(String(err)))
.finally(() => setLoading(false));
}, [userId]);
if (loading) {
return <p style={{ color: "rgba(255,255,255,0.4)", padding: 48, textAlign: "center" }}>Loading...</p>;
}
if (error || !data) {
return <p style={{ color: "#ff6b6b", padding: 48, textAlign: "center" }}>Error: {error}</p>;
}
const ogImageUrl = `/api/og-image?usePreviewPage function · typescript · L154-L162 (9 LOC)app/preview/page.tsx
export default function PreviewPage() {
return (
<div style={{ minHeight: "100vh", background: "#0a0a0a", color: "white", fontFamily: "system-ui, sans-serif" }}>
<Suspense fallback={<p style={{ color: "rgba(255,255,255,0.4)", padding: 48, textAlign: "center" }}>Loading...</p>}>
<PreviewContent />
</Suspense>
</div>
);
}Repobility · code-quality intelligence · https://repobility.com
generateMetadata function · typescript · L10-L82 (73 LOC)app/results/page.tsx
export async function generateMetadata({ searchParams }: Props): Promise<Metadata> {
const params = await searchParams;
const userId = params.userId;
if (!userId) {
return {
title: "Your Results | Content Engineer Quiz",
description: "Discover your Content Engineer archetype.",
};
}
try {
const data = await redis.get(`quiz:${userId}`);
if (!data) {
return {
title: "Your Results | Content Engineer Quiz",
};
}
const parsed = typeof data === "string" ? JSON.parse(data) : data;
const { firstName, lastName, archetype } = parsed;
const role = parsed.role || "ic";
const archetypeId = archetype?.id || "vision";
const archetypeName = archetype?.name || "Champion";
const tagline = ARCHETYPE_TAGLINES[archetypeId] || "Find your archetype.";
const copy = getShareCopy(archetypeId, role);
const title = firstName
? `${firstName} ${lastName} is The ${archetypeName} — "${tagline}"`
: `I'm The ${ResultsPage function · typescript · L84-L86 (3 LOC)app/results/page.tsx
export default function ResultsPage() {
return <ResultsClient />;
}normalizeArchetypeId function · typescript · L14-L16 (3 LOC)app/share/route.ts
function normalizeArchetypeId(id: string): string {
return ARCHETYPE_ID_MAP[id] || id;
}getBaseUrl function · typescript · L18-L22 (5 LOC)app/share/route.ts
function getBaseUrl() {
return process.env.VERCEL_PROJECT_PRODUCTION_URL
? `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`
: 'https://campaign-quiz.vercel.app';
}getShareBaseUrl function · typescript · L24-L26 (3 LOC)app/share/route.ts
function getShareBaseUrl() {
return process.env.NEXT_PUBLIC_SHARE_BASE_URL || 'https://www.airops.com';
}esc function · typescript · L28-L34 (7 LOC)app/share/route.ts
function esc(s: string): string {
return s
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/</g, '<')
.replace(/>/g, '>');
}GET function · typescript · L36-L129 (94 LOC)app/share/route.ts
export async function GET(request: NextRequest) {
const { searchParams } = request.nextUrl;
const userId = searchParams.get('userId') || '';
const baseUrl = getBaseUrl();
const shareBaseUrl = getShareBaseUrl();
let archetypeId: ArchetypeId = 'vision';
let role = 'ic';
let ogImageUrl: string | null = null;
let firstName = '';
let lastName = '';
if (userId) {
try {
const data = await redis.get(`quiz:${userId}`);
if (data) {
const parsed = JSON.parse(data);
archetypeId = normalizeArchetypeId(parsed.archetype?.id || 'vision') as ArchetypeId;
role = parsed.role || 'ic';
ogImageUrl = parsed.ogImageUrl || parsed.cardUrl || null;
firstName = parsed.firstName || '';
lastName = parsed.lastName || '';
}
} catch {
// fall through to defaults
}
}
if (!ogImageUrl) {
const paramArchetype = searchParams.get('archetype');
const paramCardUrl = searchParams.get('cardUrl');
if (paramACardGrid function · typescript · L298-L414 (117 LOC)components/CardGrid.tsx
export default function CardGrid() {
const [cards, setCards] = useState<CardEntry[]>([]);
const [loading, setLoading] = useState(true);
const [revealed, setRevealed] = useState<Set<string>>(new Set());
const observerRef = useRef<IntersectionObserver | null>(null);
useEffect(() => {
fetch("/api/all-cards")
.then((res) => res.json())
.then((data) => {
setCards(data.cards || []);
setLoading(false);
})
.catch(() => setLoading(false));
}, []);
const cardRef = useCallback(
(node: HTMLAnchorElement | null) => {
if (!node) return;
if (!observerRef.current) {
observerRef.current = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const id = (entry.target as HTMLElement).dataset.cardId;
if (id) {
setRevealed((prev) => new Set(prev).add(id));
observerRef.current?.uRepobility analyzer · published findings · https://repobility.com
ChampionCardFan function · typescript · L13-L56 (44 LOC)components/ChampionCardFan.tsx
export default function ChampionCardFan() {
return (
<section className="relative overflow-hidden py-8 md:py-16 px-4">
<div
className="flex gap-3 md:gap-4 justify-center items-start max-w-[1200px] mx-auto"
>
{cards.map((card, i) => (
<div
key={i}
className="cursor-pointer"
style={{
flex: "1 1 0",
maxWidth: "160px",
minWidth: "0",
transition: "transform 260ms cubic-bezier(0.22, 0.61, 0.36, 1)",
}}
onMouseEnter={(e) => {
e.currentTarget.style.transform = "translateY(-8px)";
e.currentTarget.style.zIndex = "10";
}}
onMouseLeave={(e) => {
e.currentTarget.style.transform = "";
e.currentTarget.style.zIndex = "";
}}
>
<img
src={card.src}
alt={card.alt}
draggable={false}
ErrorBoundary class · typescript · L25-L105 (81 LOC)components/ErrorBoundary.tsx
export class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: any) {
console.error('Error caught by boundary:', error, errorInfo);
// Capture to LogRocket if available
if (captureException) {
captureException(error, {
componentStack: errorInfo.componentStack,
errorBoundary: true,
});
}
this.setState({
errorInfo: errorInfo.componentStack,
});
}
handleReset = () => {
this.setState({ hasError: false, error: undefined, errorInfo: undefined });
};
render() {
if (this.state.hasError) {
if (this.props.fallback) {
return this.props.fallback;
}
return (
<div className="min-h-screen bg-gray-50 flex items-center justify-center p-4">
<div classNaconstructor method · typescript · L26-L29 (4 LOC)components/ErrorBoundary.tsx
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}page 1 / 3next ›