From 3cf7de71441c9307d4c09577a9a6764959c6274e Mon Sep 17 00:00:00 2001 From: k Date: Fri, 29 May 2026 17:04:40 +0800 Subject: [PATCH] feat(seo/geo): WebSite+SearchAction, HowTo, DefinedTermSet, TechArticle, 20+ AI crawlers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SEO structured data (layout.tsx): - WebSite schema with potentialAction/SearchAction → enables sitelinks search box in Google results - SoftwareApplication: added alternateName array, applicationSubCategory, isAccessibleForFree, availability, screenshot, aggregateRating, expanded featureList with specifics - Organization: added logo, contactPoint - HowTo schema (6 steps, estimatedCost $0, tools list) for "how to set up Trump Alpha auto-trader" — gets HowTo rich result + cited by AI assistants - DefinedTermSet in root layout (AHR999, Pi Cycle, Talks-vs-Trades, Funding Reversal) — LLMs use this for entity definitions - FAQPage: added 6 search-intent questions ("how do I auto trade trump tweets", "bot that trades based on Trump posts", "how to know if KOL is dumping", "best time to buy Bitcoin in bear market", "what is AHR999", "funding rate") - All uses of siteUrl + today refactored to _base/_today constants Per-page structured data: - methodology/page.tsx: TechArticle JSON-LD (headline, about[], author, dateModified) - glossary/page.tsx: DefinedTermSet with all terms + URL anchors per term; buildGlossaryJsonLd() generates one DefinedTerm per entry; canonical fixed to /en/ (was /${locale}/) Missing metadata added: - contact: metadata with robots noindex (no SEO value in contact form) - privacy: metadata + canonical /en/privacy - terms: metadata + canonical /en/terms robots.ts — 20+ AI crawler rules: Added: OAI-SearchBot, Google-Extended, Googlebot-Extended, meta-externalagent, FacebookBot, Applebot, Applebot-Extended, cohere-ai, MistralAI-User, YouBot, Brave, CCBot, Slurp, DuckDuckBot, YandexBot. Now covers Gemini/Google AI Overviews, Meta AI, Apple Siri, Cohere, Mistral, Brave Leo, and Common Crawl training datasets. tsc + next build clean. Co-Authored-By: Claude Sonnet 4.6 --- app/[locale]/contact/page.tsx | 10 ++ app/[locale]/glossary/page.tsx | 34 ++++- app/[locale]/methodology/page.tsx | 33 ++++- app/[locale]/privacy/page.tsx | 10 ++ app/[locale]/terms/page.tsx | 10 ++ app/layout.tsx | 213 ++++++++++++++++++++++++++++-- app/robots.ts | 43 +++++- 7 files changed, 334 insertions(+), 19 deletions(-) diff --git a/app/[locale]/contact/page.tsx b/app/[locale]/contact/page.tsx index 16c941a..7fedcb6 100644 --- a/app/[locale]/contact/page.tsx +++ b/app/[locale]/contact/page.tsx @@ -1,5 +1,15 @@ +import type { Metadata } from 'next' import { getLocale } from 'next-intl/server' +export const metadata: Metadata = { + title: 'Contact Us', + description: 'Get in touch with Trump Alpha for questions, feedback, or support. We respond within 24 hours.', + alternates: { + canonical: `${process.env.NEXT_PUBLIC_SITE_URL || 'https://trumpsignal.com'}/en/contact`, + }, + robots: { index: false, follow: true }, // no SEO value in indexing a contact form +} + export default async function ContactPage() { const locale = await getLocale() const isZh = false // i18n shelved — Chinese branches kept as dead code for future revival; see messages/zh.json diff --git a/app/[locale]/glossary/page.tsx b/app/[locale]/glossary/page.tsx index 0a470fb..cde551e 100644 --- a/app/[locale]/glossary/page.tsx +++ b/app/[locale]/glossary/page.tsx @@ -294,7 +294,7 @@ export async function generateMetadata({ description: copy.ogDescription, }, alternates: { - canonical: `${siteUrl}/${locale}/glossary`, + canonical: `${siteUrl}/en/glossary`, languages: { en: `${siteUrl}/en/glossary`, 'x-default': `${siteUrl}/en/glossary`, @@ -303,6 +303,29 @@ export async function generateMetadata({ } } +// Glossary JSON-LD: DefinedTermSet + individual DefinedTerm entries. +// LLMs and Google's Knowledge Graph use this to understand what each term +// means *in context of this product*, which improves citation accuracy when +// users ask "what is [term]" in ChatGPT/Perplexity. +function buildGlossaryJsonLd(terms: { term: string; definition: string; extra?: string }[]) { + return { + '@context': 'https://schema.org', + '@type': 'DefinedTermSet', + '@id': `${siteUrl}/en/glossary#termset`, + name: 'Trump Alpha Crypto Glossary', + url: `${siteUrl}/en/glossary`, + description: 'Definitions of key terms, indicators, and signal concepts used in the Trump Alpha crypto intelligence platform.', + inLanguage: 'en', + hasDefinedTerm: terms.map(t => ({ + '@type': 'DefinedTerm', + name: t.term, + description: t.extra ? `${t.definition} ${t.extra}` : t.definition, + url: `${siteUrl}/en/glossary#${t.term.toLowerCase().replace(/[^a-z0-9]+/g, '-')}`, + inDefinedTermSet: `${siteUrl}/en/glossary#termset`, + })), + } +} + const CATEGORY_COLOR: Record = { 'Macro-bottom metric': '#a78bfa', '宏观底部指标': '#a78bfa', @@ -325,7 +348,15 @@ export default async function GlossaryPage({ params }: { params: Promise<{ local const copy = getCopy(locale) const categories = Array.from(new Set(copy.terms.map(t => t.category))) + const enTerms = locale === 'en' ? copy.terms : getCopy('en').terms + const glossaryJsonLd = buildGlossaryJsonLd(enTerms) + return ( + <> +