Files
trumpsignal-frontend/app/layout.tsx
T
k d72323b1c6 Production polish: i18n shelved, PWA icons, SEO/GEO cleanup, UX fixes
Big-picture changes since 01be8e7:

New routes — /trump /btc /kol /trades /analytics /archive plus four
SEO landing pages (/methodology /glossary /case-studies /contact),
all served under /[locale]. Each has dedicated metadata + JSON-LD.

KOL page (new) — DigestWidget + OnchainWidget + TalkVsTradesWidget,
filter by handle/ticker, click-through to per-post detail with the
original AI-extracted ticker/conviction/quote.

BTC page (new) — tabbed: macro-bottom (AHR999 + 200WMA + Pi Cycle)
and funding-rate reversal, with live sparkline + threshold bands.

Telegram card on Settings — wallet-link code generation, status,
disconnect. Preferences moved into the bot itself (/trump /btc etc.)
so the card stays minimal.

SignalMonitor (new) — ETH/LINK Bollinger breakout monitor in its own
component, shares the singleton WsProvider so no second WS opens.

WS singleton refactor (lib/wsContext) — shared WsProvider + useWsSubscribe
hook. Cleanup now actively closes the socket on unmount; previously the
local `ws` couldn't be reached from cleanup and leaked one connection
per StrictMode remount.

OpenPositions polling no longer pops MetaMask in the background —
splits into load('first') for user-initiated and load('poll') that
uses getCachedViewEnvelope without signing.

i18n shelved — proxy.ts (Next 16 middleware rename) wires next-intl
but only Navbar + layout footer have translations. Rest of UI used
isZh ternary scattered across 28 files. All `const isZh = locale === 'zh'`
flipped to `const isZh = false` so every site renders English; Chinese
branches kept as dead code so revival is one regex away.
LanguageSwitch hidden but file kept. zh-CN hreflang removed from
metadata + sitemap to avoid duplicate-content penalties.

Wallet error handling — lib/walletError.ts: isUserRejection walks EIP-1193
code 4001 + .cause chain; previous string-match for "reject"/"denied"
broke for users running MetaMask in non-English UIs. 12 call sites
migrated across 5 components.

PWA icons — app/icon.tsx + app/apple-icon.tsx render the brand "α" via
Next's ImageResponse so no static PNG asset is required. manifest.ts
references /icon and /apple-icon dynamic routes.

OG image + sitemap + robots — dynamic 1200×630 OG card; robots blocks
both /en/settings and /zh/settings; sitemap only emits /en routes;
JSON-LD covers SoftwareApplication + Organization + 10-Q FAQPage.

Landing page polish — Launch Dashboard button stripped of magnetic
hover + shimmer + lift + glow expansion (multiple users found it busy);
hero scramble alphabet swapped to alphanumeric (was block characters);
"15 KOL feeds" copy updated to 19 in 5 places.

PostCards source icons — new entries for btc_bottom_reversal,
funding_reversal, kol_divergence so they no longer fall through to
the generic "first letter" fallback.

Archive page filter — excludes funding_reversal + kol_divergence
(previously only excluded truth + btc_bottom_reversal so new live
signals leaked into the legacy archive).

Cache + skeleton loading — lib/cache.ts SWR module with per-key TTL,
applied across the major pages so navigation feels instant.

SignConfirmSheet — 4 hardcoded Chinese strings translated to English
(English users were seeing zh-only "需要钱包签名" etc).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 00:53:27 +08:00

262 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { Metadata, Viewport } from 'next'
import { Geist, Geist_Mono } from 'next/font/google'
import { getLocale } from 'next-intl/server'
import Script from 'next/script'
import './[locale]/globals.css'
const siteTitle = 'Trump Alpha'
const siteTagline = 'Four crypto alpha feeds, one dashboard'
const siteDescription = 'Real-time Trump Truth Social signals, BTC macro-bottom confluence, KOL Substack/podcast signals, and talks-vs-trades divergence — all scored by AI in one live dashboard.'
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL
const geistSans = Geist({
subsets: ['latin'],
variable: '--font-geist-sans',
})
const geistMono = Geist_Mono({
subsets: ['latin'],
variable: '--font-geist-mono',
})
export const metadata: Metadata = {
metadataBase: siteUrl ? new URL(siteUrl) : new URL('https://trumpsignal.com'),
title: {
default: `${siteTitle} | ${siteTagline}`,
template: `%s | ${siteTitle}`,
},
description: siteDescription,
applicationName: siteTitle,
keywords: [
'Trump Alpha',
'TrumpSignal',
'crypto signals',
'crypto alpha dashboard',
'BTC bottom reversal',
'Bitcoin macro bottom',
'AHR999',
'Pi Cycle Bottom',
'KOL crypto signals',
'Arthur Hayes signals',
'Delphi Digital',
'Bankless',
'KOL on-chain tracking',
'talks vs trades divergence',
'smart-money divergence',
'AI trading dashboard',
'Trump Truth Social signal',
'Hyperliquid trading bot',
'crypto auto-trader',
'crypto intelligence platform',
'funding rate reversal',
'Bitcoin cycle bottom',
],
authors: [{ name: 'Trump Alpha' }],
creator: 'Trump Alpha',
publisher: 'Trump Alpha',
category: 'Finance',
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
'max-video-preview': -1,
'max-image-preview': 'large',
'max-snippet': -1,
},
},
alternates: {
canonical: siteUrl || 'https://trumpsignal.com',
languages: {
'en': `${siteUrl || 'https://trumpsignal.com'}/en`,
'x-default': siteUrl || 'https://trumpsignal.com',
},
},
openGraph: {
title: `${siteTitle} | ${siteTagline}`,
description: siteDescription,
siteName: siteTitle,
type: 'website',
locale: 'en_US',
url: siteUrl || 'https://trumpsignal.com',
images: [
{
url: '/opengraph-image',
width: 1200,
height: 630,
alt: `${siteTitle}${siteTagline}`,
type: 'image/png',
},
],
},
twitter: {
card: 'summary_large_image',
title: `${siteTitle} | ${siteTagline}`,
description: siteDescription,
images: ['/opengraph-image'],
},
verification: {
// Add your Google Search Console verification token here
// google: 'YOUR_GOOGLE_VERIFICATION_TOKEN',
},
}
export const viewport: Viewport = {
themeColor: '#0f0d0a',
width: 'device-width',
initialScale: 1,
viewportFit: 'cover',
}
const jsonLd = {
'@context': 'https://schema.org',
'@graph': [
{
'@type': 'SoftwareApplication',
name: 'Trump Alpha',
alternateName: 'TrumpSignal',
url: siteUrl || 'https://trumpsignal.com',
applicationCategory: 'FinanceApplication',
operatingSystem: 'Web',
description: siteDescription,
datePublished: '2025-01-01',
dateModified: new Date().toISOString().slice(0, 10),
inLanguage: ['en'],
offers: {
'@type': 'Offer',
price: '0',
priceCurrency: 'USD',
description: 'Free to read all signals. Optional Hyperliquid integration for auto-trading.',
},
featureList: [
'Real-time Trump Truth Social sentiment scoring',
'BTC macro-bottom confluence detection (AHR999 + 200-week MA + Pi Cycle Bottom)',
'KOL Substack and podcast signal extraction',
'Talks-vs-trades divergence detection',
'Hyperliquid auto-trader integration',
],
},
{
'@type': 'Organization',
name: 'Trump Alpha',
url: siteUrl || 'https://trumpsignal.com',
description: 'AI-powered crypto intelligence platform tracking Trump posts, on-chain signals, and KOL sentiment.',
},
{
'@type': 'FAQPage',
mainEntity: [
{
'@type': 'Question',
name: 'What is Trump Alpha?',
acceptedAnswer: {
'@type': 'Answer',
text: 'Trump Alpha is an AI-powered crypto intelligence dashboard that monitors four signal sources: Trump Truth Social posts, BTC macro-bottom confluence signals, KOL Substack and podcast essays, and talks-vs-trades divergence between public commentary and on-chain behavior.',
},
},
{
'@type': 'Question',
name: 'How does the Trump signal engine work?',
acceptedAnswer: {
'@type': 'Answer',
text: 'The engine scrapes Trump\'s Truth Social feed continuously. Each post is sent to an AI model that classifies it as LONG (bullish crypto), SHORT (bearish), or NOISE (off-topic). If the confidence score exceeds your threshold, the engine optionally places an isolated-margin trade on Hyperliquid. The entire pipeline runs in under 3 seconds from post to position.',
},
},
{
'@type': 'Question',
name: 'What is the BTC bottom reversal signal?',
acceptedAnswer: {
'@type': 'Answer',
text: 'The BTC bottom reversal module is a long-only macro-bottom scanner. It fires when at least two of three classic bottom signals agree: AHR999 deep-value zone, price near the 200-week moving average, and Pi Cycle Bottom. These signals are intentionally rare and aimed at cycle-level reversals rather than short-term swings.',
},
},
{
'@type': 'Question',
name: 'What is talks-vs-trades divergence?',
acceptedAnswer: {
'@type': 'Answer',
text: 'Talks-vs-trades divergence compares what a crypto KOL says publicly (e.g., "I\'m bullish on ETH") against what their on-chain wallet actually does within a 7-day window. When a KOL is publicly bullish but their wallet is selling, Trump Alpha flags it as a divergence signal — the on-chain action is treated as ground truth, making the divergence one of the highest-conviction alpha signals on the platform.',
},
},
{
'@type': 'Question',
name: 'Which KOLs does Trump Alpha track?',
acceptedAnswer: {
'@type': 'Answer',
text: 'Trump Alpha tracks 19 KOL feeds including Arthur Hayes (BitMEX), Delphi Digital, Dragonfly Capital, Pomp, and major crypto podcasts (Empire, Bankless, Unchained, 0xResearch, Lightspeed). Posts and episodes are processed daily; AI extracts ticker calls, direction (bullish/bearish/buy/sell), and conviction scores.',
},
},
{
'@type': 'Question',
name: 'Is Trump Alpha free?',
acceptedAnswer: {
'@type': 'Answer',
text: 'Yes. All four signal dashboards (Trump, BTC bottom, KOL, talks-vs-trades) are free to read. The optional Hyperliquid auto-trader requires your own Hyperliquid account and API key. Trump Alpha never takes custody of your funds — your API key can open and close positions but cannot withdraw.',
},
},
{
'@type': 'Question',
name: 'How do I set up the Hyperliquid auto-trader?',
acceptedAnswer: {
'@type': 'Answer',
text: 'Create a Hyperliquid account at app.hyperliquid.xyz, generate an API key with trade-only permissions (no withdrawal), and paste it into the Trump Alpha settings page. Configure your leverage (default 3×), position size, TP/SL levels, daily budget cap, and active trading hours. The bot only trades when all your conditions are met.',
},
},
{
'@type': 'Question',
name: 'What safety features does the auto-trader have?',
acceptedAnswer: {
'@type': 'Answer',
text: 'The Trump Alpha auto-trader has six safety layers: (1) minimum confidence threshold before any trade fires, (2) isolated margin so a bad trade cannot drain other positions, (3) automatic take-profit and stop-loss on every open position, (4) daily budget cap — it stops trading once the cap is hit, (5) active hours window so it only trades when you choose, (6) per-trade position size cap.',
},
},
{
'@type': 'Question',
name: 'What is the BTC macro-bottom scanner looking for?',
acceptedAnswer: {
'@type': 'Answer',
text: 'It is looking for rare macro-bottom environments rather than trying to pick intraday reversals. The live signal requires 2-of-3 agreement across AHR999, the 200-week moving average, and Pi Cycle Bottom, then manages the position with staged de-risking, profit-floor ratchets, and an 18-month backstop.',
},
},
{
'@type': 'Question',
name: 'Does Trump Alpha store my trading keys?',
acceptedAnswer: {
'@type': 'Answer',
text: 'Your Hyperliquid API key is stored encrypted in your browser\'s local settings and sent only to the Trump Alpha backend to execute trades. The key is scoped to trade-only permissions — it cannot withdraw funds. We never ask for your MetaMask seed phrase or any wallet private key.',
},
},
],
},
],
}
export default async function RootLayout({ children }: { children: React.ReactNode }) {
let locale = 'en'
try {
locale = await getLocale()
} catch {
locale = 'en'
}
return (
<html lang={locale === 'zh' ? 'zh-CN' : 'en'}>
<head>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
</head>
<body className={`${geistSans.variable} ${geistMono.variable}`}>
{/* Umami analytics — loaded after interactive so it never blocks render */}
<Script
src="https://stats.bitnews.day/script.js"
data-website-id="708f06cc-3bd0-4b49-8e81-69289b7f1b42"
strategy="afterInteractive"
/>
{children}
</body>
</html>
)
}