diff --git a/src/routeTree.gen.ts b/src/routeTree.gen.ts index ca6a34ad..2b028628 100644 --- a/src/routeTree.gen.ts +++ b/src/routeTree.gen.ts @@ -53,6 +53,7 @@ import { Route as ShowcaseSubmitRouteImport } from './routes/showcase/submit' import { Route as ShowcaseIdRouteImport } from './routes/showcase/$id' import { Route as ShopSearchRouteImport } from './routes/shop.search' import { Route as ShopCartRouteImport } from './routes/shop.cart' +import { Route as PartnersRailwayRouteImport } from './routes/partners.railway' import { Route as PartnersPartnerRouteImport } from './routes/partners.$partner' import { Route as OauthTokenRouteImport } from './routes/oauth/token' import { Route as OauthRegisterRouteImport } from './routes/oauth/register' @@ -373,6 +374,11 @@ const ShopCartRoute = ShopCartRouteImport.update({ path: '/cart', getParentRoute: () => ShopRoute, } as any) +const PartnersRailwayRoute = PartnersRailwayRouteImport.update({ + id: '/railway', + path: '/railway', + getParentRoute: () => PartnersRoute, +} as any) const PartnersPartnerRoute = PartnersPartnerRouteImport.update({ id: '/$partner', path: '/$partner', @@ -949,6 +955,7 @@ export interface FileRoutesByFullPath { '/oauth/register': typeof OauthRegisterRoute '/oauth/token': typeof OauthTokenRoute '/partners/$partner': typeof PartnersPartnerRoute + '/partners/railway': typeof PartnersRailwayRoute '/shop/cart': typeof ShopCartRoute '/shop/search': typeof ShopSearchRoute '/showcase/$id': typeof ShowcaseIdRoute @@ -1086,6 +1093,7 @@ export interface FileRoutesByTo { '/oauth/register': typeof OauthRegisterRoute '/oauth/token': typeof OauthTokenRoute '/partners/$partner': typeof PartnersPartnerRoute + '/partners/railway': typeof PartnersRailwayRoute '/shop/cart': typeof ShopCartRoute '/shop/search': typeof ShopSearchRoute '/showcase/$id': typeof ShowcaseIdRoute @@ -1230,6 +1238,7 @@ export interface FileRoutesById { '/oauth/register': typeof OauthRegisterRoute '/oauth/token': typeof OauthTokenRoute '/partners/$partner': typeof PartnersPartnerRoute + '/partners/railway': typeof PartnersRailwayRoute '/shop/cart': typeof ShopCartRoute '/shop/search': typeof ShopSearchRoute '/showcase/$id': typeof ShowcaseIdRoute @@ -1377,6 +1386,7 @@ export interface FileRouteTypes { | '/oauth/register' | '/oauth/token' | '/partners/$partner' + | '/partners/railway' | '/shop/cart' | '/shop/search' | '/showcase/$id' @@ -1514,6 +1524,7 @@ export interface FileRouteTypes { | '/oauth/register' | '/oauth/token' | '/partners/$partner' + | '/partners/railway' | '/shop/cart' | '/shop/search' | '/showcase/$id' @@ -1657,6 +1668,7 @@ export interface FileRouteTypes { | '/oauth/register' | '/oauth/token' | '/partners/$partner' + | '/partners/railway' | '/shop/cart' | '/shop/search' | '/showcase/$id' @@ -2150,6 +2162,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof ShopCartRouteImport parentRoute: typeof ShopRoute } + '/partners/railway': { + id: '/partners/railway' + path: '/railway' + fullPath: '/partners/railway' + preLoaderRoute: typeof PartnersRailwayRouteImport + parentRoute: typeof PartnersRoute + } '/partners/$partner': { id: '/partners/$partner' path: '/$partner' @@ -3011,11 +3030,13 @@ const BuilderRouteWithChildren = interface PartnersRouteChildren { PartnersPartnerRoute: typeof PartnersPartnerRoute + PartnersRailwayRoute: typeof PartnersRailwayRoute PartnersIndexRoute: typeof PartnersIndexRoute } const PartnersRouteChildren: PartnersRouteChildren = { PartnersPartnerRoute: PartnersPartnerRoute, + PartnersRailwayRoute: PartnersRailwayRoute, PartnersIndexRoute: PartnersIndexRoute, } diff --git a/src/routes/partners.railway.tsx b/src/routes/partners.railway.tsx new file mode 100644 index 00000000..eb47b83d --- /dev/null +++ b/src/routes/partners.railway.tsx @@ -0,0 +1,812 @@ +import * as React from 'react' +import { Link, createFileRoute } from '@tanstack/react-router' +import { + ArrowUpRight, + Check, + DollarSign, + GitPullRequest, + Globe, + Infinity as InfinityIcon, + LineChart, + Network, + Plus, + Rocket, + ShieldCheck, + Undo2, +} from 'lucide-react' +import { twMerge } from 'tailwind-merge' +import { Footer } from '~/components/Footer' +import { Card } from '~/components/Card' +import { Button } from '~/ui' +import { + Collapsible, + CollapsibleContent, + CollapsibleTrigger, +} from '~/components/Collapsible' +import { CodeBlock } from '~/components/markdown/CodeBlock' +import { seo } from '~/utils/seo' +import { getPartnerById, PartnerImage } from '~/utils/partners' +import { getPartnerJsonLd } from '~/utils/partner-pages' +import { trackEvent } from '~/utils/analytics' + +const RAILWAY_HREF = + 'https://railway.com/new?utm_medium=sponsor&utm_source=tanstack&utm_campaign=partner-page' +const RAILWAY_DOCS_HREF = + 'https://docs.railway.com/?utm_medium=sponsor&utm_source=tanstack&utm_campaign=partner-page' +const RAILWAY_HOME_HREF = + 'https://railway.com/?utm_medium=sponsor&utm_source=tanstack&utm_campaign=partner-page' +const RAILWAY_PRICING_HREF = + 'https://railway.com/pricing?utm_medium=sponsor&utm_source=tanstack&utm_campaign=partner-page' + +const CONFIG_SNIPPET = `import { defineConfig } from '@tanstack/start/config' + +export default defineConfig({ + server: { + preset: 'railway', // one line + }, +}) +` + +const DEPLOY_SNIPPET = `# Deploy in 3 commands +git init && git add . && git commit -m "init" +railway login +railway up +` + +type FeatureIcon = React.ComponentType<{ className?: string }> + +const features: Array<{ Icon: FeatureIcon; title: string; desc: string }> = [ + { + Icon: Rocket, + title: 'Auto-detected config', + desc: 'Railway reads your TanStack code and picks the right build and run settings. No YAML to maintain.', + }, + { + Icon: GitPullRequest, + title: 'Live PR previews', + desc: 'Every pull request spins up its own environment. Test routing, data, and server logic before merging.', + }, + { + Icon: LineChart, + title: 'Logs, metrics, and alerts', + desc: 'Observability is built in. Pipe custom alerts to Slack, Discord, or email without a third-party agent.', + }, + { + Icon: Network, + title: '100 Gbps private networking', + desc: 'Services in a project talk over private IPs at 100 Gbps. HTTP, TCP, gRPC, and WebSockets handled for you.', + }, + { + Icon: Undo2, + title: 'One-click rollbacks', + desc: 'Every deploy is versioned. Roll back to a previous deployment instantly when something breaks.', + }, + { + Icon: ShieldCheck, + title: 'Hard spending limits', + desc: 'Set a hard cap on what a project can spend. Billing is per-second, so you only pay for actual compute.', + }, + { + Icon: Globe, + title: 'Global regions', + desc: 'Run your app close to your users. Pro and above can deploy to multiple regions concurrently.', + }, + { + Icon: InfinityIcon, + title: 'Unlimited environments', + desc: 'Spin up as many staging, preview, or branch environments as your team needs. No per-env fees.', + }, +] + +const steps: Array<{ num: string; title: string; code: string }> = [ + { + num: '01', + title: 'Create your TanStack app', + code: 'npx @tanstack/cli@latest create', + }, + { num: '02', title: 'Add the Railway preset', code: "preset: 'railway'" }, + { num: '03', title: 'Deploy', code: 'railway up' }, +] + +const pricing: Array<{ + plan: string + price: string + note: string + features: Array + highlight?: boolean +}> = [ + { + plan: 'Free', + price: '$0', + note: '30-day trial with $5 credits', + features: [ + 'Up to 1 vCPU / 0.5 GB RAM', + '0.5 GB volume storage', + 'Community support', + 'No credit card required', + ], + }, + { + plan: 'Hobby', + price: '$5', + note: 'min/month · includes $5 credits', + features: [ + 'Up to 48 vCPU / 48 GB RAM', + 'Up to 5 GB storage', + '7-day log history', + 'Global regions', + ], + }, + { + plan: 'Pro', + price: '$20', + note: 'min/month · includes $20 credits', + features: [ + 'Up to 1,000 vCPU / 1 TB RAM', + 'Up to 1 TB storage', + '30-day log history', + 'Unlimited workspace seats', + 'Concurrent global regions', + ], + highlight: true, + }, + { + plan: 'Enterprise', + price: 'Custom', + note: 'for teams at scale', + features: [ + 'Up to 2,400 vCPU / 2.4 TB RAM', + '90-day log history', + 'SSO + RBAC + HIPAA BAA', + 'Dedicated VMs', + 'Bring your own cloud', + ], + }, +] + +const meteredPricing: Array<[string, string]> = [ + ['Memory', '$0.000004 / GB·sec'], + ['CPU', '$0.000008 / vCPU·sec'], + ['Egress', '$0.05 / GB'], +] + +const testimonials: Array<{ quote: string; author: string; role: string }> = [ + { + quote: 'We cut our hosting costs by 75% migrating from Heroku to Railway.', + author: 'Dillon Chen', + role: 'Founder at Common', + }, + { + quote: + "I've moved $4.5k/month from AWS and $1k/month from Heroku. My Railway bill is about $300/month.", + author: 'John Nunemaker', + role: 'Founder at BoxOutSports', + }, + { + quote: 'We went from a $1,600 Heroku bill to a $300 Railway bill.', + author: 'Brandon Gell', + role: 'Head of Consulting at Every', + }, +] + +const libraries = [ + 'Start', + 'Router', + 'Query', + 'Table', + 'Form', + 'DB', + 'AI', + 'Virtual', + 'Pacer', + 'Store', + 'Devtools', + 'CLI', +] + +const libDetails: Array<{ label: string; desc: string }> = [ + { + label: 'TanStack Start', + desc: 'Full SSR and streaming support with the Railway preset. Auto-configured Node runtime, zero extra config.', + }, + { + label: 'TanStack Router', + desc: 'File-based routing apps deploy in SSR and SPA modes. PR previews mean every route change gets a live test environment.', + }, + { + label: 'TanStack Query', + desc: "Pair with Railway-managed Postgres or Redis. Private networking keeps your server queries inside Railway's infrastructure.", + }, + { + label: 'TanStack DB', + desc: "Railway's managed databases integrate with TanStack DB's sync engine via 100 Gbps private networking.", + }, +] + +const faqs: Array<{ q: string; a: string }> = [ + { + q: 'Does Railway support TanStack Start SSR and streaming?', + a: "Yes — Railway supports server-side rendering and React streaming out of the box. TanStack Start's SSR and streaming modes work without any special configuration when using the Railway preset.", + }, + { + q: 'Can I run a database alongside my TanStack app?', + a: "Absolutely. Railway lets you provision Postgres, MySQL, Redis, or MongoDB in the same project as your app. They communicate over Railway's 100 Gbps private network — no VPC setup needed.", + }, + { + q: 'How does Railway pricing actually work?', + a: 'Railway charges by the second based on actual CPU and memory usage — not provisioned box sizes. The Hobby plan starts at $5/month (which includes $5 of credits). Most hobby TanStack projects run for free or under $5/month.', + }, + { + q: 'What makes Railway different from Vercel or Render?', + a: 'Railway is a full-stack cloud — not just a frontend host. You can run your TanStack app server, managed databases, background workers, cron jobs, and private networking all in one project. Railway also has hard spending limits, which no other major cloud provider offers.', + }, + { + q: 'Does Railway have PR preview environments?', + a: 'Yes — every pull request automatically gets its own live preview environment. For TanStack teams, this means you can test routing changes, data fetching behavior, and server logic before merging.', + }, + { + q: 'Can I migrate an existing TanStack app to Railway?', + a: 'Yes — if your app runs in Node or Docker, Railway deploys it directly from GitHub with no changes required. Railway V3 is faster and cheaper than previous versions, so now is a great time to switch.', + }, +] + +const PAGE_TITLE = 'Deploy TanStack to Railway — Official Gold Partner' +const PAGE_DESCRIPTION = + 'Railway gives TanStack teams a single place to run app services, databases, and supporting infrastructure. One-line Railway preset for TanStack Start, live PR previews, 100 Gbps private networking, and hard spending limits. Pay per second for the compute you actually use.' + +function getFaqJsonLd() { + return { + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: faqs.map((faq) => ({ + '@type': 'Question', + name: faq.q, + acceptedAnswer: { + '@type': 'Answer', + text: faq.a, + }, + })), + } +} + +export const Route = createFileRoute('/partners/railway')({ + head: () => { + const partner = getPartnerById('railway') + + return { + meta: seo({ + title: PAGE_TITLE, + description: PAGE_DESCRIPTION, + keywords: + 'deploy tanstack to railway, tanstack start railway, tanstack router railway, railway hosting, tanstack deployment, railway gold sponsor', + image: 'https://tanstack.com/og.png', + }), + scripts: [ + ...(partner + ? [ + { + type: 'application/ld+json', + children: JSON.stringify(getPartnerJsonLd(partner)), + }, + ] + : []), + { + type: 'application/ld+json', + children: JSON.stringify(getFaqJsonLd()), + }, + ], + } + }, + component: RailwayPartnerPage, +}) + +function CheckBadge() { + return ( + + + + ) +} + +function trackRailwayClick() { + trackEvent('partner_clicked', { + partner_id: 'railway', + placement: 'detail', + destination: 'external', + destination_host: 'railway.com', + }) +} + +function RailwayCodeExample({ + code, + lang, + title, +}: { + code: string + lang: string + title: string +}) { + return ( + + {code} + + ) +} + +function RailwayPartnerPage() { + const [openFaq, setOpenFaq] = React.useState(null) + + React.useEffect(() => { + trackEvent('partner_viewed', { + partner_id: 'railway', + placement: 'detail', + }) + }, []) + + const partner = getPartnerById('railway') + + return ( +
+
+ + + {/* Hero */} +
+
+ {partner ? ( +
+ +
+ ) : null} +
+ + Gold Sponsor · Deployment & Hosting + +
+ + + Railway V3 — faster and cheaper + +
+
+
+ +

+ Ship TanStack apps +
+ peacefully with Railway +

+ +

+ Railway gives TanStack teams a single place to run app services, + databases, and supporting infrastructure. Deploy a TanStack Start + app from GitHub or the CLI — and only pay per-second for the compute + you actually use. +

+ +

+ "Services that took 1 week to configure elsewhere take 1 day to spin + up in Railway." — Daniel Lobaton, CTO at G2X +

+ +
+ + +
+

+ No credit card required. $5 in trial credits on signup. +

+
+ + {/* Stats */} +
+ {[ + ['2M+', 'Developers on Railway'], + ['< 2 min', 'Time to first deploy'], + ['100 Gbps', 'Private networking'], + ['$0', 'To get started'], + ].map(([value, label]) => ( +
+
{value}
+
+ {label} +
+
+ ))} +
+ + {/* Features */} +
+

+ Why TanStack teams choose Railway +

+

+ Railway eliminates infrastructure complexity so your team ships + faster. Here's what makes it the right fit for TanStack developers. +

+
+ {features.map(({ Icon, title, desc }) => ( + + +
{title}
+

+ {desc} +

+
+ ))} +
+
+ + {/* How it works */} +
+

+ From zero to deployed in 3 steps +

+

+ Railway has first-class support for TanStack Start. One config line + is all it takes. +

+ +
+ {steps.map(({ num, title, code }) => ( + +
+ {num} +
+
+
{title}
+ + {code} + +
+
+ ))} +
+ +
+ + +
+ +
+ + +
+
+ + {/* Library fit */} +
+

+ Works with every TanStack library +

+

+ From full-stack apps with TanStack Start to lightweight React apps + using Router and Query — Railway deploys them all. +

+ +
+ {libraries.map((lib) => ( + + {lib} + + ))} +
+ +
+ {libDetails.map(({ label, desc }) => ( + +
+ + {label} +
+

+ {desc} +

+
+ ))} +
+
+ + {/* Pricing */} +
+

+ Pricing that scales with you +

+

+ Railway charges by the second based on actual usage — not + provisioned box sizes. Most TanStack hobby projects run free or + under $5/month. +

+ +
+ {pricing.map(({ plan, price, note, features: pf, highlight }) => ( + + {highlight ? ( + + Most popular + + ) : null} +
{plan}
+
+ {price} +
+
+ {note} +
+
    + {pf.map((feat) => ( +
  • + + {feat} +
  • + ))} +
+
+ ))} +
+ +
+ {meteredPricing.map(([key, value]) => ( +
+
+ {key} +
+
+ {value} +
+
+ ))} +
+ +
+ + +
+
+ + {/* Testimonials */} +
+

+ What teams say after switching +

+

+ Real teams, real bills. These are quotes from founders and engineers + who moved their production workloads onto Railway. +

+
+ {testimonials.map(({ quote, author, role }) => ( + +
+ "{quote}" +
+
+
{author}
+
+ {role} +
+
+
+ ))} +
+ +
+ + + + Per-second billing · no credit card required + +
+
+ + {/* FAQ */} +
+

+ Frequently asked questions +

+

+ Common questions from TanStack developers evaluating Railway. +

+ +
+ {faqs.map(({ q, a }, i) => { + const isOpen = openFaq === i + return ( + setOpenFaq(next ? i : null)} + className="border-b border-gray-200 dark:border-gray-800" + > + + + {q} + + + + +

+ {a} +

+
+
+ ) + })} +
+
+ + {/* CTA */} +
+
+ Railway V3 — now faster and cheaper +
+

+ Ready to ship TanStack peacefully? +

+

+ No credit card required. No surprise bills. Pay only for what you + use. +

+

+ Most customers save ~40% by switching to Railway. +

+ +
+ + +
+
+ +

+ Railway is a Gold-tier TanStack sponsor.{' '} + + Browse all TanStack partners + + .{' '} + + railway.com + +

+
+ +
+ ) +}