be151edf6e
SEO fixes:
- canonical on trump/macro/kol pages now hardcodes /en/ instead of
/${locale}/ — prevents /zh/* routes (i18n shelved, routes still resolve)
from generating duplicate-content signals pointing to /zh/ canonicals
- OG image: "15 KOL feeds" → "19" (matches kol_substack.py KOL_FEEDS count)
- FAQ JSON-LD: corrected API key storage description ("stored encrypted in
your browser's local settings" was wrong — key is server-side encrypted,
not stored in the browser)
GEO (Generative Engine Optimization):
- llms.txt fully rewritten: +full KOL list (all 19 named), +explicit
differentiation section, +who-this-is-for, +technology stack detail
(model names, price sources, DB), +Hyperliquid and isolated-margin
definitions. AI crawlers (Perplexity, ChatGPT, Claude) use this file
directly when answering questions about the product.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
172 lines
4.6 KiB
TypeScript
172 lines
4.6 KiB
TypeScript
import { ImageResponse } from 'next/og'
|
|
|
|
export const runtime = 'edge'
|
|
export const alt = 'Trump Alpha — Four crypto alpha feeds, one dashboard'
|
|
export const size = { width: 1200, height: 630 }
|
|
export const contentType = 'image/png'
|
|
|
|
export default function OGImage() {
|
|
return new ImageResponse(
|
|
(
|
|
<div
|
|
style={{
|
|
width: '100%',
|
|
height: '100%',
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
alignItems: 'flex-start',
|
|
justifyContent: 'flex-end',
|
|
padding: '64px 72px',
|
|
background: '#0a0907',
|
|
position: 'relative',
|
|
overflow: 'hidden',
|
|
fontFamily: 'system-ui, sans-serif',
|
|
}}
|
|
>
|
|
{/* Background grid */}
|
|
<div
|
|
style={{
|
|
position: 'absolute',
|
|
inset: 0,
|
|
backgroundImage:
|
|
'linear-gradient(rgba(245,165,36,0.04) 1px, transparent 1px), linear-gradient(90deg, rgba(245,165,36,0.04) 1px, transparent 1px)',
|
|
backgroundSize: '48px 48px',
|
|
}}
|
|
/>
|
|
|
|
{/* Ambient glow */}
|
|
<div
|
|
style={{
|
|
position: 'absolute',
|
|
top: -200,
|
|
left: -200,
|
|
width: 800,
|
|
height: 800,
|
|
borderRadius: '50%',
|
|
background: 'radial-gradient(circle, rgba(245,165,36,0.12) 0%, transparent 70%)',
|
|
}}
|
|
/>
|
|
|
|
{/* Top-right corner badge */}
|
|
<div
|
|
style={{
|
|
position: 'absolute',
|
|
top: 48,
|
|
right: 72,
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: 8,
|
|
padding: '6px 14px',
|
|
borderRadius: 999,
|
|
background: 'rgba(245,165,36,0.12)',
|
|
border: '1px solid rgba(245,165,36,0.3)',
|
|
}}
|
|
>
|
|
<div
|
|
style={{
|
|
width: 8,
|
|
height: 8,
|
|
borderRadius: '50%',
|
|
background: '#22c55e',
|
|
}}
|
|
/>
|
|
<span style={{ fontSize: 14, color: '#f5a524', fontWeight: 700, letterSpacing: '0.06em' }}>
|
|
LIVE
|
|
</span>
|
|
</div>
|
|
|
|
{/* Four signal pills */}
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
gap: 12,
|
|
marginBottom: 40,
|
|
flexWrap: 'wrap',
|
|
}}
|
|
>
|
|
{[
|
|
{ label: 'Trump · Truth Social', color: '#f5a524' },
|
|
{ label: 'Macro Vibes', color: '#a78bfa' },
|
|
{ label: 'KOL Signal', color: '#22c55e' },
|
|
{ label: 'Talks vs Trades', color: '#ef4444' },
|
|
].map((p) => (
|
|
<div
|
|
key={p.label}
|
|
style={{
|
|
display: 'flex',
|
|
padding: '7px 16px',
|
|
borderRadius: 6,
|
|
background: 'rgba(255,255,255,0.05)',
|
|
border: `1px solid ${p.color}40`,
|
|
fontSize: 13,
|
|
fontWeight: 600,
|
|
color: p.color,
|
|
letterSpacing: '0.02em',
|
|
}}
|
|
>
|
|
{p.label}
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Main title */}
|
|
<div
|
|
style={{
|
|
fontSize: 72,
|
|
fontWeight: 800,
|
|
lineHeight: 1.05,
|
|
color: '#f5f2ea',
|
|
marginBottom: 24,
|
|
letterSpacing: '-0.03em',
|
|
}}
|
|
>
|
|
Trump Alpha
|
|
</div>
|
|
|
|
{/* Sub */}
|
|
<div
|
|
style={{
|
|
fontSize: 24,
|
|
color: '#8a8578',
|
|
fontWeight: 400,
|
|
lineHeight: 1.5,
|
|
maxWidth: 700,
|
|
marginBottom: 0,
|
|
}}
|
|
>
|
|
Four crypto alpha feeds. AI-scored in real time.
|
|
<br />
|
|
One dashboard — zero noise.
|
|
</div>
|
|
|
|
{/* Bottom right stat strip */}
|
|
<div
|
|
style={{
|
|
position: 'absolute',
|
|
bottom: 52,
|
|
right: 72,
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
alignItems: 'flex-end',
|
|
gap: 6,
|
|
}}
|
|
>
|
|
{[
|
|
{ v: '<3s', l: 'post → position' },
|
|
{ v: '19', l: 'KOL feeds' },
|
|
{ v: '$0', l: 'platform fee' },
|
|
].map((s) => (
|
|
<div key={s.l} style={{ display: 'flex', gap: 10, alignItems: 'baseline' }}>
|
|
<span style={{ fontSize: 22, fontWeight: 700, color: '#f5a524', fontFamily: 'monospace' }}>
|
|
{s.v}
|
|
</span>
|
|
<span style={{ fontSize: 13, color: '#5c584e' }}>{s.l}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
),
|
|
{ ...size },
|
|
)
|
|
}
|