diff --git a/public/feed.xml b/public/feed.xml index c575d12..1f49e57 100644 --- a/public/feed.xml +++ b/public/feed.xml @@ -5,7 +5,7 @@ https://usewraith.xyz/blog Notes on stealth payments, private infrastructure, and the Wraith ecosystem. en-us - Sat, 08 Aug 2026 18:36:39 GMT + Wed, 26 Aug 2026 02:49:58 GMT diff --git a/public/sitemap.xml b/public/sitemap.xml index 839e573..8c72aa5 100644 --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -2,79 +2,97 @@ https://usewraith.xyz - 2026-08-08 + 2026-08-26 daily 1.0 https://usewraith.xyz/faq - 2026-08-08 + 2026-08-26 weekly 0.8 https://usewraith.xyz/privacy - 2026-08-08 + 2026-08-26 weekly 0.8 https://usewraith.xyz/use-cases - 2026-08-08 + 2026-08-26 weekly 0.8 https://usewraith.xyz/roadmap - 2026-08-08 + 2026-08-26 weekly 0.8 https://usewraith.xyz/case-studies - 2026-08-08 + 2026-08-26 weekly 0.8 https://usewraith.xyz/stellar - 2026-08-08 + 2026-08-26 weekly 0.8 https://usewraith.xyz/careers - 2026-08-08 + 2026-08-26 weekly 0.8 https://usewraith.xyz/press - 2026-08-08 + 2026-08-26 + weekly + 0.8 + + + https://usewraith.xyz/grants + 2026-08-26 + weekly + 0.8 + + + https://usewraith.xyz/grants/showcase + 2026-08-26 + weekly + 0.8 + + + https://usewraith.xyz/contributors + 2026-08-26 weekly 0.8 https://usewraith.xyz/case-studies/payroll-processor - 2026-08-08 + 2026-08-26 weekly 0.7 https://usewraith.xyz/blog - 2026-08-08 + 2026-08-26 weekly 0.8 https://usewraith.xyz/compare - 2026-08-08 + 2026-08-26 weekly 0.8 https://usewraith.xyz/newsletter - 2026-08-08 + 2026-08-26 weekly 0.8 diff --git a/scripts/sitemap.ts b/scripts/sitemap.ts index de0b2e3..4cbf677 100644 --- a/scripts/sitemap.ts +++ b/scripts/sitemap.ts @@ -18,6 +18,20 @@ const knownRoutes = [ '/stellar', '/careers', '/press', + '/grants', + '/grants/showcase', + '/contributors', + '/es', + '/es/faq', + '/es/privacy', + '/es/use-cases', + '/es/roadmap', + '/es/case-studies', + '/es/stellar', + '/es/careers', + '/es/grants', + '/es/grants/showcase', + '/es/contributors', ]; function getCaseStudyRoutes(): string[] { diff --git a/src/App.tsx b/src/App.tsx index c8436f2..75f418b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import { lazy, Suspense } from 'react'; +import { lazy, Suspense, useEffect, type ReactNode } from 'react'; import { BrowserRouter, Routes, Route } from 'react-router-dom'; import Header from './components/Header'; import Hero from './components/Hero'; @@ -7,6 +7,8 @@ import Layout from './components/Layout'; import TrustStrip from './components/TrustStrip'; import PartnerStrip from './components/PartnerStrip'; import { ThemeProvider } from './context/ThemeContext'; +import { Seo } from './utils/seo'; +import { changeLocale, type Locale } from './i18n'; // Lazy load below-the-fold homepage components const StealthAnimation = lazy(() => import('./components/StealthAnimation')); @@ -17,6 +19,7 @@ const StellarMetrics = lazy(() => import('./components/StellarMetrics')); const Compare = lazy(() => import('./components/Compare')); const Showcase = lazy(() => import('./components/Showcase')); const CaseStudiesStrip = lazy(() => import('./components/CaseStudiesStrip')); +const FeaturedGrantShowcase = lazy(() => import('./components/FeaturedGrantShowcase')); const EcosystemPartners = lazy(() => import('./components/EcosystemPartners')); const CtaStrip = lazy(() => import('./components/CtaStrip')); const Footer = lazy(() => import('./components/Footer')); @@ -29,6 +32,7 @@ const UseCases = lazy(() => import('./pages/UseCases')); const Stellar = lazy(() => import('./pages/Stellar')); const Roadmap = lazy(() => import('./pages/Roadmap')); const Grants = lazy(() => import('./pages/Grants')); +const GrantShowcase = lazy(() => import('./pages/GrantShowcase')); const CaseStudies = lazy(() => import('./pages/CaseStudies')); const Careers = lazy(() => import('./pages/Careers')); const About = lazy(() => import('./pages/About')); @@ -37,9 +41,21 @@ const NotFound = lazy(() => import('./pages/NotFound')); const Contributors = lazy(() => import('./pages/Contributors')); const Blog = lazy(() => import('./pages/Blog')); +/** Sets the i18n locale on mount for locale-prefixed routes. */ +function LocaleSetter({ locale, children }: { locale: Locale; children: ReactNode }) { + useEffect(() => { + changeLocale(locale); + }, [locale]); + return <>{children}; +} + function Home() { return (
+ Skip to content @@ -57,6 +73,7 @@ function Home() { + @@ -109,6 +126,14 @@ export default function App() { } /> + + + + } + /> } /> + + {/* Spanish locale-prefixed routes */} + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + } + /> + + + + + + } + /> + + + + + + } + /> + + + + + + } + /> + + + + + + } + /> + + + + + + } + /> + + + + + + } + /> + + + + + + } + /> + + + + + + } + /> + } /> diff --git a/src/components/FeaturedGrantShowcase.tsx b/src/components/FeaturedGrantShowcase.tsx new file mode 100644 index 0000000..52399d5 --- /dev/null +++ b/src/components/FeaturedGrantShowcase.tsx @@ -0,0 +1,121 @@ +import { Link } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; +import { entries } from '../data/grant-showcase.json'; +import { filterOptedOutContributors } from '../utils/contributors'; + +type GrantShowcaseEntry = { + id: string; + name: string; + description: string; + wave: string; + contributors: string[]; + status: string; + codeUrl: string; + demoUrl: string; + featured: boolean; +}; + +const showcaseEntries = entries as GrantShowcaseEntry[]; + +const statusStyles: Record = { + live: 'border-tertiary text-tertiary', + 'in progress': 'border-blue text-blue', + shipped: 'border-primary text-primary', +}; + +export default function FeaturedGrantShowcase() { + const { t } = useTranslation(); + + const featured = showcaseEntries.filter((entry) => entry.featured).slice(0, 3); + + if (featured.length === 0) return null; + + return ( +
+
+
+
+ + {t('featuredGrants.eyebrow')} + +

+ {t('featuredGrants.heading')} +

+

+ {t('featuredGrants.description')} +

+
+ + {t('featuredGrants.viewAll')} + + +
+ +
+ {featured.map((entry) => { + const visibleContributors = filterOptedOutContributors(entry.contributors); + const statusClass = statusStyles[entry.status] ?? 'border-outline-variant text-outline'; + + return ( +
+
+
+

+ {entry.name} +

+ + {entry.wave} + +
+ + {entry.status} + +
+ +

+ {entry.description} +

+ + {visibleContributors.length > 0 && ( +
+ {visibleContributors.map((contributor) => ( + + @{contributor} + + ))} +
+ )} + +
+ + {t('featuredGrants.readMore')} + + + → + +
+
+ ); + })} +
+
+
+ ); +} diff --git a/src/data/grant-showcase.json b/src/data/grant-showcase.json new file mode 100644 index 0000000..5a99b8a --- /dev/null +++ b/src/data/grant-showcase.json @@ -0,0 +1,59 @@ +{ + "entries": [ + { + "id": "stealth-wallet-extension", + "name": "Stealth Wallet Extension", + "description": "Browser extension that lets users send and receive stealth payments with one click, no SDK knowledge required.", + "wave": "Wave 1", + "contributors": ["satoshi-dev", "ghost", "crypto-lara"], + "status": "live", + "codeUrl": "https://github.com/wraith-protocol/stealth-wallet-extension", + "demoUrl": "https://wallet.usewraith.xyz", + "featured": true + }, + { + "id": "dao-treasury-shield", + "name": "DAO Treasury Shield", + "description": "Treasury management tool that routes multi-sig payments through stealth addresses, keeping contributor payouts private.", + "wave": "Wave 1", + "contributors": ["defi-builder", "open-source-org"], + "status": "in progress", + "codeUrl": "https://github.com/wraith-protocol/dao-treasury-shield", + "demoUrl": "https://treasury.usewraith.xyz", + "featured": true + }, + { + "id": "cross-chain-stealth-bridge", + "name": "Cross-Chain Stealth Bridge", + "description": "Bridge that moves assets between Horizen and Stellar using stealth addresses so neither side can link the sender to the receiver.", + "wave": "Wave 0", + "contributors": ["bridge-builder", "satoshi-dev"], + "status": "shipped", + "codeUrl": "https://github.com/wraith-protocol/cross-chain-stealth-bridge", + "demoUrl": "https://bridge.usewraith.xyz", + "featured": true + }, + { + "id": "private-payroll-protocol", + "name": "Private Payroll Protocol", + "description": "Payroll system that pays employees via one-time stealth addresses so salary amounts and recipients stay confidential on-chain.", + "wave": "Wave 1", + "contributors": ["payroll-hacker", "crypto-lara"], + "status": "in progress", + "codeUrl": "https://github.com/wraith-protocol/private-payroll-protocol", + "demoUrl": "https://payroll.usewraith.xyz", + "featured": false + }, + { + "id": "stealth-address-indexer", + "name": "Stealth Address Indexer", + "description": "Open-source indexer that scans announcement events across EVM chains and serves them via a fast REST API for stealth-payment clients.", + "wave": "Wave 0", + "contributors": ["indexer-dev", "open-source-org"], + "status": "shipped", + "codeUrl": "https://github.com/wraith-protocol/stealth-address-indexer", + "demoUrl": "https://indexer.usewraith.xyz", + "featured": false + } + ] +} diff --git a/src/i18n/en.json b/src/i18n/en.json index ecaf6d5..03ad983 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -382,5 +382,31 @@ "successShort": "Check your inbox", "errorShort": "Try again" } + }, + "grantShowcase": { + "eyebrow": "GRANT SHOWCASE", + "heading": "Grant-funded projects", + "description": "Explore projects built with Wraith Protocol grant funding. From stealth wallets to cross-chain bridges, see what the community is shipping.", + "totalProjects": "TOTAL PROJECTS", + "project": "project", + "projects": "projects", + "filterByWave": "FILTER BY WAVE", + "allWaves": "All Waves", + "filterByStatus": "FILTER BY STATUS", + "allStatuses": "All Statuses", + "resetFilters": "Reset Filters", + "contributors": "CONTRIBUTORS", + "viewCode": "Code", + "viewDemo": "Demo", + "noResults": "NO PROJECTS FOUND", + "noResultsDescription": "Try selecting different filters.", + "backToGrants": "Back to grants" + }, + "featuredGrants": { + "eyebrow": "GRANT SHOWCASE", + "heading": "Funded projects", + "description": "Projects built with Wraith Protocol grant funding.", + "viewAll": "VIEW ALL", + "readMore": "View Project" } } diff --git a/src/i18n/es.json b/src/i18n/es.json index 4b2fe41..e172535 100644 --- a/src/i18n/es.json +++ b/src/i18n/es.json @@ -368,5 +368,31 @@ "successShort": "Revisa tu bandeja", "errorShort": "Intenta de nuevo" } + }, + "grantShowcase": { + "eyebrow": "VITRINA DE BECAS", + "heading": "Proyectos financiados por becas", + "description": "Explora proyectos construidos con financiación de becas de Wraith Protocol. Desde billeteras ocultas hasta puentes entre cadenas, ve lo que la comunidad está creando.", + "totalProjects": "PROYECTOS TOTALES", + "project": "proyecto", + "projects": "proyectos", + "filterByWave": "FILTRAR POR OLA", + "allWaves": "Todas las Olas", + "filterByStatus": "FILTRAR POR ESTADO", + "allStatuses": "Todos los Estados", + "resetFilters": "Restablecer Filtros", + "contributors": "COLABORADORES", + "viewCode": "Código", + "viewDemo": "Demo", + "noResults": "NO SE ENCONTRARON PROYECTOS", + "noResultsDescription": "Prueba seleccionar diferentes filtros.", + "backToGrants": "Volver a becas" + }, + "featuredGrants": { + "eyebrow": "VITRINA DE BECAS", + "heading": "Proyectos financiados", + "description": "Proyectos construidos con financiación de becas de Wraith Protocol.", + "viewAll": "VER TODOS", + "readMore": "Ver Proyecto" } } diff --git a/src/pages/About.tsx b/src/pages/About.tsx index c536d5a..557660f 100644 --- a/src/pages/About.tsx +++ b/src/pages/About.tsx @@ -1,4 +1,4 @@ -import { Helmet } from 'react-helmet-async'; +import { Seo } from '../utils/seo'; import teamData from '../data/team.json'; const socialIcon = (type: 'github' | 'twitter') => { @@ -19,20 +19,10 @@ const socialIcon = (type: 'github' | 'twitter') => { export default function About() { return ( <> - - About – Wraith Protocol - - - - - - + {/* ── Hero ──────────────────────────────────────────────────────────── */}
diff --git a/src/pages/Blog.tsx b/src/pages/Blog.tsx index 3b5a384..0beb43f 100644 --- a/src/pages/Blog.tsx +++ b/src/pages/Blog.tsx @@ -1,4 +1,4 @@ -import { Helmet } from 'react-helmet-async'; +import { Seo } from '../utils/seo'; import { Link, useParams } from 'react-router-dom'; import { getAllPosts, getPostBySlug } from '../utils/blog'; import BlogToc from '../components/BlogToc'; @@ -8,19 +8,17 @@ function BlogList() { return (
- - Blog – Wraith Protocol - + - +

Blog

@@ -82,9 +80,10 @@ function BlogPostDetail({ slug }: { slug: string }) { if (!post) { return (
- - Post Not Found – Wraith Protocol - +

Post Not Found

The requested blog post could not be found.

@@ -98,10 +97,10 @@ function BlogPostDetail({ slug }: { slug: string }) { return (
- - {post.title} – Wraith Protocol - {post.excerpt && } - +
- - Careers – Wraith Protocol - - - - - - +
diff --git a/src/pages/CaseStudies.tsx b/src/pages/CaseStudies.tsx index 177abba..56512ca 100644 --- a/src/pages/CaseStudies.tsx +++ b/src/pages/CaseStudies.tsx @@ -3,6 +3,7 @@ import { Link, useParams } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { entries } from '../data/case-studies.json'; import Layout from '../components/Layout'; +import { Seo } from '../utils/seo'; type CaseStudy = { id: string; @@ -67,6 +68,11 @@ function CaseStudyDetail({ study }: { study: CaseStudy }) { return ( +