profileShare

rasmusjy / roundtable

Read-only snapshot

No repository description.

main default branch 181 files Expires Sep 13, 2026, 9:06 AM
opengraph-image.tsx 5,394 bytes
1 import { ImageResponse } from 'next/og';
2 import { loadDebateByShareToken } from '@/db/repositories';
3 import { truncate } from '@/lib/utils';
4
5 export const alt = 'A shared Roundtable verdict';
6 export const size = { width: 1200, height: 630 };
7 export const contentType = 'image/png';
8 export const dynamic = 'force-dynamic';
9
10 export default async function SharedVerdictImage({
11 params,
12 }: {
13 params: Promise<{ token: string }>;
14 }) {
15 const { token } = await params;
16 const result = await loadDebateByShareToken(token).catch(() => null);
17 const question = truncate(result?.config.question ?? 'A question put to the Roundtable', 160);
18 const verdict = truncate(
19 result?.synthesis?.finalAnswer ??
20 'Several independent AI opinions were compared, challenged, and combined into one clear recommendation.',
21 300,
22 );
23 const opinionCount = result?.participants.length ?? 3;
24
25 return new ImageResponse(
26 (
27 <div
28 style={{
29 position: 'relative',
30 display: 'flex',
31 height: '100%',
32 width: '100%',
33 overflow: 'hidden',
34 background: '#f7f8fc',
35 color: '#171a2b',
36 fontFamily: 'Arial, sans-serif',
37 padding: '58px 64px',
38 }}
39 >
40 <div
41 style={{
42 position: 'absolute',
43 right: '-180px',
44 top: '-230px',
45 display: 'flex',
46 height: '620px',
47 width: '620px',
48 border: '2px solid rgba(79, 94, 232, 0.12)',
49 borderRadius: '50%',
50 }}
51 />
52 <div
53 style={{
54 position: 'absolute',
55 right: '-80px',
56 top: '-130px',
57 display: 'flex',
58 height: '420px',
59 width: '420px',
60 border: '2px solid rgba(79, 94, 232, 0.12)',
61 borderRadius: '50%',
62 }}
63 />
64
65 <div
66 style={{ position: 'relative', display: 'flex', width: '100%', flexDirection: 'column' }}
67 >
68 <div style={{ display: 'flex', alignItems: 'center', gap: '14px' }}>
69 <div
70 style={{
71 display: 'flex',
72 height: '42px',
73 width: '42px',
74 alignItems: 'center',
75 justifyContent: 'center',
76 borderRadius: '12px',
77 background: '#4f5ee8',
78 color: 'white',
79 fontSize: '20px',
80 fontWeight: 800,
81 }}
82 >
83 R
84 </div>
85 <div style={{ display: 'flex', fontSize: '21px', fontWeight: 800 }}>Roundtable</div>
86 <div
87 style={{
88 display: 'flex',
89 marginLeft: '10px',
90 borderRadius: '999px',
91 background: '#e9ebf8',
92 color: '#596078',
93 padding: '8px 13px',
94 fontSize: '12px',
95 fontWeight: 700,
96 letterSpacing: '0.08em',
97 }}
98 >
99 SHARED VERDICT
100 </div>
101 </div>
102
103 <div
104 style={{
105 display: 'flex',
106 marginTop: '46px',
107 maxWidth: '1000px',
108 fontSize: question.length > 110 ? '38px' : '46px',
109 fontWeight: 800,
110 lineHeight: 1.12,
111 letterSpacing: '-0.035em',
112 }}
113 >
114 {question}
115 </div>
116
117 <div
118 style={{
119 display: 'flex',
120 marginTop: 'auto',
121 border: '2px solid rgba(23, 164, 118, 0.2)',
122 borderRadius: '20px',
123 background: '#edf9f4',
124 padding: '22px 26px',
125 }}
126 >
127 <div
128 style={{
129 display: 'flex',
130 height: '36px',
131 width: '36px',
132 flexShrink: 0,
133 alignItems: 'center',
134 justifyContent: 'center',
135 borderRadius: '10px',
136 background: '#17a476',
137 color: 'white',
138 fontSize: '20px',
139 fontWeight: 800,
140 }}
141 >
142 V
143 </div>
144 <div style={{ display: 'flex', marginLeft: '16px', flexDirection: 'column' }}>
145 <div
146 style={{
147 display: 'flex',
148 color: '#117357',
149 fontSize: '12px',
150 fontWeight: 800,
151 letterSpacing: '0.1em',
152 }}
153 >
154 THE VERDICT
155 </div>
156 <div
157 style={{ display: 'flex', marginTop: '7px', fontSize: '19px', lineHeight: 1.35 }}
158 >
159 {verdict}
160 </div>
161 </div>
162 </div>
163
164 <div
165 style={{
166 display: 'flex',
167 marginTop: '18px',
168 justifyContent: 'space-between',
169 color: '#676d82',
170 fontSize: '13px',
171 fontWeight: 700,
172 }}
173 >
174 <div style={{ display: 'flex' }}>{opinionCount} INDEPENDENT OPINIONS</div>
175 <div style={{ display: 'flex' }}>SEVERAL OPINIONS. ONE CLEAR VERDICT.</div>
176 </div>
177 </div>
178 </div>
179 ),
180 size,
181 );
182 }
183