pendulum-chain / pendulum-chain/vortex
Make Vortex site discoverable in search and AI crawlers
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 6
- Forks
- 5
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 33
Description
As a prospective Vortex customer searching Google, ChatGPT, Claude, or Perplexity for cross-border crypto-fiat payment solutions - particularly in Brazil, Colombia, Argentina, the US, and Europe
I want to find vortexfinance.co content cited in search results and AI answers for "buy crypto" / "sell crypto" intents in my market
So that organic search and AI-mediated discovery become viable acquisition channels in our core operating jurisdictions - today the site is functionally invisible to all crawlers
Context
A full SEO audit was first run on 2026-05-11 and returned a Health Score of 20/100 — Critical.
The root cause is that https://www.vortexfinance.co/ is a pure client-side React SPA. Every URL (homepage, /business, /contact, /privacy-policy, /terms-and-conditions, /pt-BR/*) returns the identical 1,971-byte HTML shell containing only <title>Vortex</title>, a Google Tag Manager script, and <div id="app"></div>. Verified via curl — identical ETag (8aafe548fb71601e123130ba5c48d931-ssl) across all five tested routes. Googlebot indexes blank pages in its first pass; GPTBot, ClaudeBot, PerplexityBot, and Bing's AI crawler never execute JavaScript and see nothing at all.
Score breakdown
| Category | Weight | Score |
|---|---|---|
| Technical SEO | 25% | 24 |
| Content Quality | 25% | 28 |
| On-Page SEO | 20% | 15 |
| Schema / Structured Data | 10% | 0 |
| Performance (CWV) | 10% | 25 |
| Images | 5% | 30 |
| AI Search Readiness | 5% | 4 |
Top critical findings (unchanged since May 11)
- Pure CSR — empty HTML shell on every URL; no SSR or prerendering.
- No meta description, Open Graph, Twitter Card, or canonical in static HTML.
- Bare
<title>Vortex</title>on every page. - Zero structured data (no
Organization,FinancialService,BreadcrumbList,FAQPage). - Live legal placeholder
[●]in the governing-law clause of/terms-and-conditions— a YMYL trust failure. - JS bundle is 7.8 MB uncompressed on a single chunk → LCP estimated 3.5–5s p75 on mobile.
/pt-BR/now returns HTTP 200 (one delta vs. May 11) but serves the same empty shell./es/,/pt/,/fr/still 404 despite robots.txt referencing them.- robots.txt drift —
Disallow: /es/widget,/pt/widget,/fr/widgetreference paths that 404. - No hreflang tags despite multi-locale routing now partially in place.
- Asset cache headers missing
immutable— content-hashed Vite bundles served withcache-control: public, max-age=0, must-revalidate.
Live SERP visibility check (target markets, 2026-05-21)
| Market | Query tested | Top organic competitors | Vortex |
|---|---|---|---|
| 🇧🇷 Brazil | "buy crypto PIX" / "comprar cripto PIX" | BingX, Switchere, BitPay+Ramp, CEX.io, Ledger, Paybis, Gate.com, Symlix | Not in top 100 |
| 🇦🇷 Argentina | "comprar bitcoin Argentina" | LiteFinance, Criptonoticias, Coinbase, Transak, Ripio, Lemon, Buenbit, Onramp Money | Not in top 100 |
| 🇨🇴 Colombia | "comprar crypto COP" / "comprar USDC Colombia" | Wenia (Bancolombia), DolarApp, ChangeNOW, Coinbase, CriptoYa | Not in top 100 |
| 🇪🇺 Europe | "buy USDC EURC SEPA" | Guardarian, Mt Pelerin, Bleap, Circle, RampNow, MoonPay | Not in top 100 |
| 🇺🇸 United States | "buy USDC ACH" | Coinbase, Kraken, MoonPay, Transak, Ramp Network | Not in top 100 |
Vortex appears in none of the target-market SERPs. Until acceptance criterion #1 ships, this will not change.
Acceptance Criteria
Critical (blocking — fix immediately)
- A prerendering strategy is chosen and deployed (
vite-plugin-ssg, Netlify Edge prerendering, or equivalent compatible with TanStack Router) — verified bycurl -sL https://www.vortexfinance.co/businessreturning rendered HTML with visible body content, not just<div id="app"></div> - Each indexable route has a unique
<title>and<meta name="description">in the static HTML response — verified per URL via curl. Defaults must include target keywords ("buy crypto", "sell crypto", "non-custodial", payment-method names). - Each route has
<link rel="canonical">, Open Graph (og:title,og:description,og:image,og:url), and Twitter Card metadata in static HTML -
OrganizationandFinancialServiceJSON-LD are present in static<head>of every page, includingareaServed,currenciesAccepted,paymentAccepted,sameAsproperties, and validate cleanly in Google's Rich Results Test - The
[●]placeholder in/terms-and-conditionsgoverning-law clause is replaced with the actual governing jurisdiction
High (fix before geo-content work begins)
- Locale URL structure decided and implemented as subdirectories:
/pt-BR/,/es-AR/,/es-CO/,/es-MX/,/en-EU/,/en-US/. Each locale root returns HTTP 200 with prerendered content matching the locale. -
<link rel="alternate" hreflang>tags for every supported locale plusx-defaultare present on every page in static HTML -
WebSite+SearchActionJSON-LD on the homepage to enable sitelinks search box -
apps/frontend/public/robots.txtmatches the actual route structure (currently drifts vs. production). RemoveDisallowentries for 404 paths. Decide whether/widgetisnoindex(meta) instead ofDisallow(robots.txt) so link equity flows. - Security headers added via
netlify.toml:Content-Security-Policy,X-Content-Type-Options: nosniff,Referrer-Policy: strict-origin-when-cross-origin,Permissions-Policy,X-Frame-Options, and HSTS upgraded withincludeSubDomains; preload -
/assets/*hashed bundles returnCache-Control: public, max-age=31536000, immutable - JS bundle is code-split — initial entry chunk under 200 KB gzip (currently single 7.8 MB chunk = ~1.8 MB gzip). Marketing surface must not load the ramp-widget chunk (Polkadot.js, Wagmi, XState).
- E-E-A-T pages exist with prerendered content and named individuals:
/about(founders, jurisdiction, year founded),/team(LinkedIn links, credentials),/security(non-custodial architecture, Nabla AMM audit links),/compliance(regulatory status or explicit disclosure of partner-license model),/licenses. YMYL non-negotiable for US/EU ranking.
Medium (geo-targeted content — once prerendering and locale structure are in place)
- Brazil (pt-BR) market pages shipped at 800–1,800 words each, all with
FAQPageJSON-LD:/pt-BR/comprar-cripto-com-pix(1,800w)/pt-BR/vender-cripto-pix(1,600w)/pt-BR/comprar-usdc-com-pix(1,500w)/pt-BR/como-funciona(1,200w)/pt-BR/taxas(800w)
- Argentina (es-AR) market pages shipped:
/es-AR/comprar-cripto-con-pesos(1,800w)/es-AR/vender-usdc-ars(1,600w)/es-AR/comprar-usdc-argentina(1,500w)/es-AR/como-funciona(1,200w)/es-AR/comisiones(800w)
- Colombia (es-CO) market pages shipped:
/es-CO/comprar-cripto-con-pesos-colombianos(1,800w)/es-CO/vender-cripto-cop(1,600w)/es-CO/comprar-usdc-colombia(1,500w)/es-CO/onramp-cop(1,200w)/es-CO/comisiones(800w)
- Europe (en-EU) market pages shipped:
/europe/buy-eurc-sepa(2,000w)/europe/sell-crypto-sepa(1,800w)/europe/buy-usdc-europe(1,600w)/europe/non-custodial-onramp(1,400w)/europe/fees(800w)
- United States (en-US) market pages shipped:
/usa/buy-usdc(2,000w)/usa/sell-crypto-usd(1,800w)/usa/non-custodial-crypto-onramp(1,600w)/usa/fees(800w)
-
BreadcrumbListJSON-LD per route on every non-homepage page and locale equivalents - Each market page includes a 60–80 word "what is" definitional opener (AI citation snippet format), a comparison table with explicit column headers (LLM-extractable), and 5–8
FAQPageQ&A pairs (primary AI-citation lever) - Existing pages expanded to minimum word counts:
/(600w),/business(1,000w),/contact(200w with physical/registered address),/privacy-policy(800w covering LGPD + GDPR),/terms-and-conditions(1,200w),/terms-and-conditions-full(2,000w) - Sitemap expanded to include all locale URLs with
<lastmod>per entry and<xhtml:link rel="alternate">hreflang annotations per entry - TrustedBy logo strip replaced with linked, dated partnership/coverage references; CoinDesk removed unless properly cited as editorial coverage
-
modulepreloadfor the entry JS chunk,dns-prefetchforgoogletagmanager.com, Red Hat Display self-hosted (ordisplay=optional)
Verification
- SEO Health Score re-audit shows ≥70/100 after Critical + High work is shipped
- Google Search Console "URL Inspection" tool shows rendered HTML matching the user-visible page for at least the homepage,
/business, and one localized page per target market - Schema validators (Schema.org validator + Google Rich Results Test) return no errors on the homepage and one localized page per target market
- Page 1 SERP impressions for at least one "buy crypto + market" long-tail query within 60 days of market-page content shipping (tracked via Google Search Console)
Definition of Done
- Code Produced (all todos completed)
- Code Documented
- Builds without errors
- Unit Tests written and passing
- Deployed to TEST environment and passed system tests
- Remaining hours for tasks set to 0 and all tasks are closed
Additional Context
- Affected surfaces:
apps/frontend/index.html,apps/frontend/public/robots.txt,apps/frontend/public/sitemap.xml, Netlify configuration (netlify.tomlif absent, must be created),apps/frontend/vite.config.ts(for SSG/SSR plugin),/terms-and-conditionssource content, new locale route files underapps/frontend/src/pages/per locale, i18n catalog expansion fores-AR,es-CO,es-MX,en-EU. - Tech constraints: Bun monorepo using React 19 + Vite + TanStack Router with i18n (currently en/pt-BR). Prerendering must be compatible with TanStack Router's route tree. Heavy deps (Polkadot.js, Wagmi, XState) drive bundle size — code-splitting needs to keep the marketing surface independent of the ramp widget bundle.
- Recommended schema priorities:
- Tier 1 (every page):
Organization+FinancialService,WebSite+SearchAction(homepage only) - Tier 2 (market pages):
FAQPage(primary AI-citation lever — Google restricted FAQ rich results to gov/health sites but GPTBot/ClaudeBot/PerplexityBot still parse and cite them heavily),Serviceper corridor,BreadcrumbList - Tier 3 (when content exists):
Article/BlogPostingfor educational corridor guides - Skip:
HowTo(removed from Google rich results Sep 2023),SpecialAnnouncement(deprecated Jul 2025)
- Tier 1 (every page):
- Demo plan: show before/after
curl -sL <url>output for the homepage,/business, and/pt-BR/comprar-cripto-com-pix; show Google Search Console rendered HTML before and after; show Rich Results Test passing; show updated SEO Health Score; show first SERP impression in Google Search Console for any target-market keyword. - Out of scope (separate issues): content engine for
/blog, link-building/PR strategy,aggregateRatingschema integration with Trustpilot (once reviews accumulate), IndexNow integration for Bing/Yandex, Mexico (/es-MX/) market pages (covered by criteria but deferred to phase 2 since out of the May 21 target-market scope).
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with apps/frontend/index.html, apps/frontend/vite.config.ts, public/robots.txt, public/sitemap.xml, and netlify.toml; first run curl against the homepage and /business to confirm the empty shell. Trace the existing TanStack Router and i18n setup before choosing the prerendering and locale approach. Done means the critical and high acceptance checks pass, including rendered HTML, metadata, structured data, routes, headers, and bundle behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bun, react, typescript, vite
- Domain
- frontend, internationalization, performance, web-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100