From 1e5719a1da0e08ed71671d3bd2fa8f725ddb2c4b Mon Sep 17 00:00:00 2001 From: jwinterm Date: Sun, 12 Jul 2026 13:47:19 -0400 Subject: [PATCH] services: split the four pillars into dedicated subpages /services becomes a hub (hero, four linked pillar cards, philosophy, recent work, FAQ, CTA) and each pillar gets its own statically-generated page at /services/[pillar] (commerce/games/crypto/education) with distinct SEO title+description+canonical, its own H1, the products behind it, a pillar-scoped FAQ + FAQ JSON-LD, breadcrumb JSON-LD, and 'the other pillars' cross-links. dynamicParams=false so unknown slugs are a static 404. The pillar/proof/FAQ data + colour maps move to lib/services.ts (single source of truth), ProofCard/PillarCards/ServicesCta/EducationCredentials to components/services, so the hub, subpages, home 'What We Do' preview, and sitemap can't drift. Home preview cards now link to their pillar; sitemap gains the four subpage URLs. All pillar copy kept verbatim. Verified: 4 subpages prebuilt, distinct titles/canonicals, right products per page, click-through nav, education credentials block, bad slug -> 404. --- apps/web/src/app/services/[pillar]/page.tsx | 113 +++++++ apps/web/src/app/services/page.tsx | 289 ++---------------- apps/web/src/app/sitemap.ts | 4 + .../components/landing/services-preview.tsx | 85 +++--- .../services/education-credentials.tsx | 21 ++ .../src/components/services/pillar-cards.tsx | 27 ++ .../src/components/services/proof-card.tsx | 58 ++++ .../src/components/services/services-cta.tsx | 26 ++ apps/web/src/lib/services.ts | 156 ++++++++++ 9 files changed, 471 insertions(+), 308 deletions(-) create mode 100644 apps/web/src/app/services/[pillar]/page.tsx create mode 100644 apps/web/src/components/services/education-credentials.tsx create mode 100644 apps/web/src/components/services/pillar-cards.tsx create mode 100644 apps/web/src/components/services/proof-card.tsx create mode 100644 apps/web/src/components/services/services-cta.tsx create mode 100644 apps/web/src/lib/services.ts diff --git a/apps/web/src/app/services/[pillar]/page.tsx b/apps/web/src/app/services/[pillar]/page.tsx new file mode 100644 index 0000000..1a05247 --- /dev/null +++ b/apps/web/src/app/services/[pillar]/page.tsx @@ -0,0 +1,113 @@ +import { DataGrid } from "@repo/ui/procedural/data-grid"; +import { Header } from "@/components/layout/header"; +import { MobileNav } from "@/components/layout/mobile-nav"; +import { ScrollReveal } from "@/components/scroll-reveal"; +import Link from "next/link"; +import { notFound } from "next/navigation"; +import type { Metadata } from "next"; +import { JsonLd, breadcrumbLd, faqLd } from "@/components/seo/json-ld"; +import { ProofCard } from "@/components/services/proof-card"; +import { PillarCards } from "@/components/services/pillar-cards"; +import { ServicesCta } from "@/components/services/services-cta"; +import { EducationCredentials } from "@/components/services/education-credentials"; +import { pillars, pillarBySlug, proofFor, faqs, borderL } from "@/lib/services"; + +type Props = { params: Promise<{ pillar: string }> }; + +// Prebuild the four pillar pages at build time (static); anything else is a static 404 +// rather than an on-demand render. +export const dynamicParams = false; +export function generateStaticParams() { + return pillars.map((p) => ({ pillar: p.slug })); +} + +export async function generateMetadata({ params }: Props): Promise { + const { pillar: slug } = await params; + const pillar = pillarBySlug(slug); + if (!pillar) return {}; + return { + title: pillar.metaTitle, + description: pillar.metaDescription, + alternates: { canonical: `/services/${pillar.slug}` }, + openGraph: { title: pillar.metaTitle, description: pillar.metaDescription, type: "website" }, + }; +} + +export default async function PillarPage({ params }: Props) { + const { pillar: slug } = await params; + const pillar = pillarBySlug(slug); + if (!pillar) notFound(); + + const proof = proofFor(pillar.slug); + const pillarFaqs = faqs.filter((f) => f.pillars.includes(pillar.slug)); + + return ( +
+ + {pillarFaqs.length > 0 && ({ q, a })))} />} + +
+ +
+ {/* Breadcrumb */} + + + {/* Pillar header */} + +
+

{pillar.title}

+

{pillar.lead}

+
+
+ + {/* The products behind this pillar */} + +
+ {proof.map((p) => ( + + ))} +
+ {pillar.slug === "education" && } +
+ + {/* Pillar-specific FAQ */} + {pillarFaqs.length > 0 && ( + +
+

Questions

+
+ {pillarFaqs.map((f) => ( +
+

{f.q}

+

{f.a}

+
+ ))} +
+
+
+ )} + + {/* Explore the other pillars */} + + + + + {/* CTA */} + + + +
+ +
+ ); +} diff --git a/apps/web/src/app/services/page.tsx b/apps/web/src/app/services/page.tsx index 3b32d0a..eb305e2 100644 --- a/apps/web/src/app/services/page.tsx +++ b/apps/web/src/app/services/page.tsx @@ -1,241 +1,52 @@ import { DataGrid } from "@repo/ui/procedural/data-grid"; -import { Button } from "@repo/ui/components/button"; import { Header } from "@/components/layout/header"; import { MobileNav } from "@/components/layout/mobile-nav"; import { ScrollReveal } from "@/components/scroll-reveal"; import Image from "next/image"; -import Link from "next/link"; -import { Card } from "@repo/ui/components/card"; import { JsonLd, faqLd } from "@/components/seo/json-ld"; +import { PillarCards } from "@/components/services/pillar-cards"; +import { ServicesCta } from "@/components/services/services-cta"; +import { faqs } from "@/lib/services"; +import { Card } from "@repo/ui/components/card"; import type { Metadata } from "next"; -const faqs = [ - { q: "What does Such Software build?", a: "Four things, from one small team: custom e-commerce and web apps on revenue share, games and mobile apps we ship ourselves, cryptocurrency and payments software (integration only, never custody), and PhD-led radiation-science education. The pillars below break each down with the products behind them." }, - { q: "Do you offer nuclear and radiation education?", a: "Yes. Our founder holds a PhD in radiation-detector materials and spent six years at Lawrence Livermore National Laboratory, plus shielding and spent-fuel work at Holtec. We teach radiation-science fundamentals and Monte Carlo methods, run GEANT4 training, and speak on these topics. Our GEANT4 radiation labs are published open-source (MIT / CC-BY). This is education and published methods." }, - { q: "Where are you based?", a: "We are a software studio in Kennett Square, Pennsylvania, working with clients remotely across the US and beyond." }, - { q: "Do you build for accessibility?", a: "Yes. We engineer front-ends to meet WCAG 2.2 AA and audit against it, alongside Core Web Vitals, as part of every project." }, - { q: "How does a project start?", a: "Reach out through the contact form with what you need. We scope it, propose an approach, and from there it can run as a fixed project or a performance-based revenue-share partnership." }, - { q: "Do you take revenue-share work?", a: "Yes. For a limited number of partners we build and operate products (such as webshops) for a share of revenue instead of a large upfront fee, so our incentives line up with yours." }, -]; - export const metadata: Metadata = { title: "Web, Games, Crypto & Nuclear-Science Education | Such Software", - description: "Four pillars from one studio: custom e-commerce and web apps on revenue share, games and mobile apps, crypto and payments software (non-custodial), and PhD-led radiation-science education and GEANT4 training. Kennett Square, PA.", - alternates: { - canonical: "/services", - }, + description: + "Four pillars from one studio: custom e-commerce and web apps on revenue share, games and mobile apps, crypto and payments software (non-custodial), and PhD-led radiation-science education and GEANT4 training. Kennett Square, PA.", + alternates: { canonical: "/services" }, openGraph: { title: "Web, Games, Crypto & Nuclear-Science Education | Such Software", - description: "Four pillars from one studio: custom e-commerce and web apps on revenue share, games and mobile apps, crypto and payments software (non-custodial), and PhD-led radiation-science education and GEANT4 training.", + description: + "Four pillars from one studio: custom e-commerce and web apps on revenue share, games and mobile apps, crypto and payments software (non-custodial), and PhD-led radiation-science education and GEANT4 training.", type: "website", }, }; -// ---- Pillar model ------------------------------------------------------- - -type Pillar = { - id: string; - label: string; - accent: string; // tailwind colour stem, e.g. "blue" - title: string; - lead: string; -}; - -const pillars: Pillar[] = [ - { - id: "commerce", - label: "Commerce & Web", - accent: "blue", - title: "Commerce & custom web", - lead: "Proprietary, headless commerce and web apps that you own, built to your business logic instead of a template's limits. Often on revenue share: we build, host, and run it, and earn a share once you are live.", - }, - { - id: "games", - label: "Games & Apps", - accent: "purple", - title: "Games & apps", - lead: "We do not just consult on software, we ship it. A growing catalog of games and mobile apps built in-house across iOS, Android, web, and desktop, on Godot and Next.js.", - }, - { - id: "crypto", - label: "Crypto & Payments", - accent: "cyan", - title: "Crypto & payments", - lead: "Software and integration for payments and cryptocurrency. The client, a licensed processor, or the user's own wallet holds the funds; we build the system around it and never take custody.", - }, - { - id: "education", - label: "Education & Science", - accent: "amber", - title: "Education & science", - lead: "PhD-led radiation-science teaching, training, and speaking from years at a national lab, plus learning-through-play games that teach real science and math. We publish our methods open-source.", - }, -]; - -// Border-left colour per accent (literal strings so Tailwind's JIT keeps them). -const borderL: Record = { - blue: "border-l-blue-500", - purple: "border-l-purple-500", - cyan: "border-l-cyan-500", - amber: "border-l-amber-500", -}; -const chipAccent: Record = { - blue: "bg-blue-500/15 text-blue-700 dark:text-blue-300", - purple: "bg-purple-500/15 text-purple-700 dark:text-purple-300", - cyan: "bg-cyan-500/15 text-cyan-700 dark:text-cyan-300", - amber: "bg-amber-500/15 text-amber-700 dark:text-amber-300", -}; -const hoverBorder: Record = { - blue: "hover:border-blue-500/30", - purple: "hover:border-purple-500/30", - cyan: "hover:border-cyan-500/30", - amber: "hover:border-amber-500/30", -}; - -// ---- Proof items (real products behind each pillar) --------------------- - -type Proof = { - title: string; - blurb: string; - img?: string; // /images/products/* - href?: string; // internal detail page or external - tag?: string; // status pill: "Live", "Open source", "Beta", "Early", "Flagship" -}; - -const commerceProof: Proof[] = [ - { title: "Webshops", blurb: "Our multi-tenant commerce platform: fully-themed storefronts, print-on-demand, non-custodial crypto checkout, and automated tax, on revenue share.", img: "/images/products/occupy-wallets.png", href: "/products/webshops", tag: "Flagship" }, - { title: "Custom builds", blurb: "Real-time web apps, multiplayer experiences, and live dashboards on Next.js, Socket.io, and WebRTC.", img: "/images/products/custom-websites.svg", href: "/products/custom-websites", tag: "Live" }, - { title: "Grin BTCPay plugin", blurb: "An open-source BTCPay Server plugin we built to accept Grin (Mimblewimble) payments, including auto-Tor invoice exchange.", tag: "Open source" }, - { title: "Evaluetron", blurb: "A self-hostable AI-compute platform: one core that runs a personal image bot or a paid multi-customer service, with an append-only credit ledger and pricing built in.", tag: "Building" }, -]; - -const gamesProof: Proof[] = [ - { title: "Suchoice", blurb: "Stop overthinking decisions: snap a photo, let AI read the options, spin the wheel. iOS and Android.", img: "/images/products/suchoice.png", href: "/products/suchoice", tag: "Live" }, - { title: "Vegan IQ", blurb: "1,000+ plant-based trivia questions across 8 categories, with a daily challenge and weekly quiz. iOS and Android.", img: "/images/products/vegan-iq.png", href: "/products/vegan-iq", tag: "Live" }, - { title: "Bloomword", blurb: "A daily word game where every word you find grows a living 3D typographic tree. Free at bloomword.earth, launching on mobile.", img: "/images/products/bloomword.svg", href: "/products/bloomword", tag: "Live" }, - { title: "Bauhaus Echo", blurb: "A visual memory puzzle game inspired by Bauhaus design. Android, iOS, and web.", img: "/images/products/bauhaus-echo.png", href: "/products/bauhaus-echo", tag: "Live" }, - { title: "Such Moon Launch", blurb: "Vry rocket, much landing, wow: a Wownero-themed pixel rocket arcade with 11 levels and tilt-to-steer. Everywhere.", img: "/images/products/such-moon-launch.png", href: "/products/such-moon-launch", tag: "Live" }, -]; - -const cryptoProof: Proof[] = [ - { title: "Payments consulting", blurb: "Stripe and multi-processor integrations, reconciliation tooling, Monero and on-chain integration. The processor or wallet moves the money; we wire it in.", tag: "Service" }, - { title: "Smirk Wallet", blurb: "A non-custodial multi-asset browser wallet: send, receive, and tip by username on Telegram and Discord. BTC, LTC, XMR, WOW, GRIN.", img: "/images/products/smirk-wallet.png", href: "/products/smirk-wallet", tag: "Live" }, - { title: "Hash Bags", blurb: "A mobile multi-chain wallet forked from Cake Wallet, tuned for the privacy-coin ecosystem.", tag: "Beta" }, - { title: "Evaluetron", blurb: "Pay-for-compute done right: an append-only credit ledger, a job queue, and an evaluator that lets on-demand work preempt opportunistic work. Customers can never self-credit.", tag: "Building" }, -]; - -const educationProof: Proof[] = [ - { title: "Barns & Neutrons", blurb: "A cozy exploration-puzzle game across the real Table of Nuclides: capture neutrons, coax decays, and learn honest nuclear physics. Our premiere visual work.", img: "/images/products/barns-and-neutrons.svg", href: "/products/barns-and-neutrons", tag: "Coming soon" }, - { title: "Nuclear consulting & training", blurb: "PhD-led radiation-science teaching: Monte Carlo methods with GEANT4, shielding and dose fundamentals, detector physics, and open-source labs.", href: "https://jwinterm.github.io/geant4-radiation-labs/", tag: "Service" }, - { title: "Numchangers", blurb: "A kids math game (ages 5-8) where numbers morph into dots, shapes, and 3D characters, so arithmetic becomes a visible action instead of a quiz. Godot, mobile-first.", tag: "Early" }, -]; - -const tagStyle: Record = { - Flagship: "bg-emerald-500/15 text-emerald-700 dark:text-emerald-300", - Live: "bg-green-500/15 text-green-700 dark:text-green-300", - Service: "bg-sky-500/15 text-sky-700 dark:text-sky-300", - "Open source": "bg-indigo-500/15 text-indigo-700 dark:text-indigo-300", - Beta: "bg-amber-500/15 text-amber-700 dark:text-amber-300", - Building: "bg-amber-500/15 text-amber-700 dark:text-amber-300", - Early: "bg-fuchsia-500/15 text-fuchsia-700 dark:text-fuchsia-300", - "Coming soon": "bg-fuchsia-500/15 text-fuchsia-700 dark:text-fuchsia-300", -}; - -function ProofCard({ p, accent }: { p: Proof; accent: string }) { - const inner = ( - -
- {p.img ? ( - {p.title} - ) : ( - - )} -
-
-

{p.title}

- {p.tag && ( - - {p.tag} - - )} -
-

{p.blurb}

- {p.href && ( - - Learn more → - - )} -
-
-
- ); - - if (!p.href) return
{inner}
; - const external = p.href.startsWith("http"); - return external ? ( - - {inner} - - ) : ( - - {inner} - - ); -} - -function proofFor(id: string): Proof[] { - if (id === "commerce") return commerceProof; - if (id === "games") return gamesProof; - if (id === "crypto") return cryptoProof; - return educationProof; -} - export default function ServicesPage() { return (
- + ({ q, a })))} />
- {/* Page Header */} + {/* Page header */}

Four things, done well

Commerce and custom web, games and apps, crypto and payments, and - PhD-led radiation-science education. Each pillar comes with the - products behind it. + PhD-led radiation-science education. Pick a pillar to see the products + behind it.

- {/* Pillar sub-nav: jump links so the page reads as four clear areas */} - + {/* The four pillars, each its own page */} + + + {/* Philosophy */} @@ -248,55 +59,7 @@ export default function ServicesPage() {
- {/* Pillars */} - {pillars.map((pillar) => ( -
- -
-

- {pillar.title} -

-

- {pillar.lead} -

-
-
- -
- {proofFor(pillar.id).map((p) => ( - - ))} -
-
- - {/* Education pillar carries the founder credentials inline */} - {pillar.id === "education" && ( - - -

Why us, on the science

-
    -
  • PhD in radiation-detector materials, UT-Dallas (2014)
  • -
  • Lawrence Livermore National Laboratory (2015-2021): detector systems, radioisotope battery program, MCNP5 publications
  • -
  • Holtec International: radiation shielding and spent-fuel-to-dry-cask optimization
  • -
  • College-level instructor: author of open-source GEANT4 radiation labs
  • -
-

- This is education and published open-source methods, not for-hire controlled - modeling. We are not a licensed professional-engineering (PE) firm and provide no - stamped engineering deliverables. -

-
-
- )} -
- ))} - - {/* Recent Work */} + {/* Recent work */}

Recent work

@@ -332,7 +95,7 @@ export default function ServicesPage() { {/* FAQ */} - +

Frequently asked questions

@@ -347,18 +110,8 @@ export default function ServicesPage() { {/* CTA */} - -
-

Let's build together

-

- We take on a limited number of revenue-share build partners. Tell us what you're - building and we'll run a scope review. -

- - - + +
diff --git a/apps/web/src/app/sitemap.ts b/apps/web/src/app/sitemap.ts index 32096b5..48868c1 100644 --- a/apps/web/src/app/sitemap.ts +++ b/apps/web/src/app/sitemap.ts @@ -29,6 +29,10 @@ export default function sitemap(): MetadataRoute.Sitemap { { url: `${base}/products/meatspace`, lastModified: updated, changeFrequency: "weekly", priority: 0.7 }, { url: `${base}/products/mushroom-capital`, lastModified: updated, changeFrequency: "weekly", priority: 0.7 }, { url: `${base}/services`, lastModified: updated, changeFrequency: "monthly", priority: 0.9 }, + { url: `${base}/services/commerce`, lastModified: updated, changeFrequency: "monthly", priority: 0.8 }, + { url: `${base}/services/games`, lastModified: updated, changeFrequency: "monthly", priority: 0.8 }, + { url: `${base}/services/crypto`, lastModified: updated, changeFrequency: "monthly", priority: 0.8 }, + { url: `${base}/services/education`, lastModified: updated, changeFrequency: "monthly", priority: 0.8 }, { url: `${base}/about`, lastModified: updated, changeFrequency: "monthly", priority: 0.7 }, { url: `${base}/support`, lastModified: updated, changeFrequency: "monthly", priority: 0.5 }, { url: `${base}/privacy`, lastModified: updated, changeFrequency: "yearly", priority: 0.3 }, diff --git a/apps/web/src/components/landing/services-preview.tsx b/apps/web/src/components/landing/services-preview.tsx index 13a8d65..fb1fd3d 100644 --- a/apps/web/src/components/landing/services-preview.tsx +++ b/apps/web/src/components/landing/services-preview.tsx @@ -1,49 +1,54 @@ import { Card } from "@repo/ui/components/card"; +import Link from "next/link"; + +// The four "What We Do" cards on the home page, each linking to its /services/ pillar page. +const previews = [ + { + href: "/services/commerce", + title: "E-Commerce & Hosting", + body: "Headless storefronts on Medusa and Next.js, built fast and hosted on our own infrastructure. Stripe Connect with a revenue-share model: you stay the merchant of record, and crypto settles straight to your own wallets.", + }, + { + href: "/services/games", + title: "Custom App Development", + body: "Cross-platform mobile and web apps built to spec. We handle architecture, deployment, and ongoing support so you can focus on your business.", + }, + { + href: "/services/crypto", + title: "Crypto & Payment Integration", + body: "Software and integration for multi-currency checkout and non-custodial crypto payments, in production since 2014. You or a licensed provider hold the funds; we never take custody.", + }, + { + href: "/services/education", + title: "Nuclear & Radiation Education", + body: "Training, talks, and open-source GEANT4 labs on radiation transport and semiconductor detectors, led by a PhD with a Lawrence Livermore background. Published methods and teaching.", + }, +]; export function ServicesPreview() { return (
-
-

What We Do

-

- We build and host custom e-commerce stores, develop apps to spec, and ship our own - titles and games. We handle your project end to end, from architecture to deployment. -

-
+
+

What We Do

+

+ We build and host custom e-commerce stores, develop apps to spec, and ship our own + titles and games. We handle your project end to end, from architecture to deployment. +

+
-
- -

E-Commerce & Hosting

-

- Headless storefronts on Medusa and Next.js, built fast and hosted on our own - infrastructure. Stripe Connect with a revenue-share model: you stay the merchant - of record, and crypto settles straight to your own wallets. -

+
+ {previews.map((p) => ( + + +

{p.title}

+

{p.body}

+ + Learn more → +
- -

Custom App Development

-

- Cross-platform mobile and web apps built to spec. We handle architecture, - deployment, and ongoing support so you can focus on your business. -

-
- -

Crypto & Payment Integration

-

- Software and integration for multi-currency checkout and non-custodial crypto - payments, in production since 2014. You or a licensed provider hold the funds; - we never take custody. -

-
- -

Nuclear & Radiation Education

-

- Training, talks, and open-source GEANT4 labs on radiation transport and - semiconductor detectors, led by a PhD with a Lawrence Livermore background. - Published methods and teaching. -

-
-
+ + ))} +
- ) + ); } diff --git a/apps/web/src/components/services/education-credentials.tsx b/apps/web/src/components/services/education-credentials.tsx new file mode 100644 index 0000000..a4dfbd1 --- /dev/null +++ b/apps/web/src/components/services/education-credentials.tsx @@ -0,0 +1,21 @@ +import { Card } from "@repo/ui/components/card"; + +// Founder science credentials, shown on the Education & Science pillar page. +export function EducationCredentials() { + return ( + +

Why us, on the science

+
    +
  • PhD in radiation-detector materials, UT-Dallas (2014)
  • +
  • Lawrence Livermore National Laboratory (2015-2021): detector systems, radioisotope battery program, MCNP5 publications
  • +
  • Holtec International: radiation shielding and spent-fuel-to-dry-cask optimization
  • +
  • College-level instructor: author of open-source GEANT4 radiation labs
  • +
+

+ This is education and published open-source methods, not for-hire controlled + modeling. We are not a licensed professional-engineering (PE) firm and provide no + stamped engineering deliverables. +

+
+ ); +} diff --git a/apps/web/src/components/services/pillar-cards.tsx b/apps/web/src/components/services/pillar-cards.tsx new file mode 100644 index 0000000..1e1d4b8 --- /dev/null +++ b/apps/web/src/components/services/pillar-cards.tsx @@ -0,0 +1,27 @@ +import { Card } from "@repo/ui/components/card"; +import Link from "next/link"; +import { pillars, borderL, hoverBorder } from "@/lib/services"; + +// The four pillar cards, each linking to its /services/ subpage. Used as the hub's +// primary nav and, with `exclude`, as the "explore the other pillars" block on a subpage. +export function PillarCards({ exclude, heading }: { exclude?: string; heading?: string }) { + const shown = pillars.filter((p) => p.slug !== exclude); + return ( +
+ {heading &&

{heading}

} +
+ {shown.map((p) => ( + + +

{p.title}

+

{p.card}

+ + Explore {p.label} → + +
+ + ))} +
+
+ ); +} diff --git a/apps/web/src/components/services/proof-card.tsx b/apps/web/src/components/services/proof-card.tsx new file mode 100644 index 0000000..d1d7efa --- /dev/null +++ b/apps/web/src/components/services/proof-card.tsx @@ -0,0 +1,58 @@ +import { Card } from "@repo/ui/components/card"; +import Image from "next/image"; +import Link from "next/link"; +import { chipAccent, hoverBorder, tagStyle, type Proof } from "@/lib/services"; + +// One "real product behind a pillar" card. Used on the hub and on every /services/[pillar] page. +export function ProofCard({ p, accent }: { p: Proof; accent: string }) { + const inner = ( + +
+ {p.img ? ( + {p.title} + ) : ( + + )} +
+
+

{p.title}

+ {p.tag && ( + + {p.tag} + + )} +
+

{p.blurb}

+ {p.href && ( + + Learn more → + + )} +
+
+
+ ); + + if (!p.href) return
{inner}
; + const external = p.href.startsWith("http"); + return external ? ( + + {inner} + + ) : ( + + {inner} + + ); +} diff --git a/apps/web/src/components/services/services-cta.tsx b/apps/web/src/components/services/services-cta.tsx new file mode 100644 index 0000000..aa23871 --- /dev/null +++ b/apps/web/src/components/services/services-cta.tsx @@ -0,0 +1,26 @@ +import { Button } from "@repo/ui/components/button"; +import Link from "next/link"; + +// Shared closing CTA for the services hub and every pillar subpage. +export function ServicesCta({ + title = "Let's build together", + blurb = "We take on a limited number of revenue-share build partners. Tell us what you're building and we'll run a scope review.", +}: { + title?: string; + blurb?: string; +}) { + return ( +
+
+

{title}

+

+ {blurb} +

+ + + +
+ ); +} diff --git a/apps/web/src/lib/services.ts b/apps/web/src/lib/services.ts new file mode 100644 index 0000000..0cef58a --- /dev/null +++ b/apps/web/src/lib/services.ts @@ -0,0 +1,156 @@ +// Single source of truth for the Services pillars + the real products behind each. +// Consumed by the /services hub, the /services/[pillar] subpages, the home "What We Do" +// preview, and the sitemap, so the four pillars can never drift between those surfaces. + +export type Pillar = { + slug: "commerce" | "games" | "crypto" | "education"; + label: string; // short nav label + accent: string; // tailwind colour stem, e.g. "blue" + title: string; // on-page H1 / section heading + lead: string; // the pillar's paragraph + // Per-subpage SEO. Kept distinct so each /services/ ranks for its own terms. + metaTitle: string; + metaDescription: string; + // One line for the hub card, tighter than the lead. + card: string; +}; + +export const pillars: Pillar[] = [ + { + slug: "commerce", + label: "Commerce & Web", + accent: "blue", + title: "Commerce & custom web", + lead: "Proprietary, headless commerce and web apps that you own, built to your business logic instead of a template's limits. Often on revenue share: we build, host, and run it, and earn a share once you are live.", + card: "Headless commerce and custom web apps you own, often on revenue share.", + metaTitle: "Custom E-Commerce & Web App Development | Such Software", + metaDescription: + "Headless, proprietary commerce and web apps built to your business logic on Medusa and Next.js, hosted on our infrastructure, often on a revenue-share partnership. Kennett Square, PA.", + }, + { + slug: "games", + label: "Games & Apps", + accent: "purple", + title: "Games & apps", + lead: "We do not just consult on software, we ship it. A growing catalog of games and mobile apps built in-house across iOS, Android, web, and desktop, on Godot and Next.js.", + card: "A growing catalog of games and mobile apps we build and ship in-house.", + metaTitle: "Games & Mobile App Development | Such Software", + metaDescription: + "A studio that ships its own titles: games and cross-platform mobile apps built in-house on Godot and Next.js for iOS, Android, web, and desktop. Kennett Square, PA.", + }, + { + slug: "crypto", + label: "Crypto & Payments", + accent: "cyan", + title: "Crypto & payments", + lead: "Software and integration for payments and cryptocurrency. The client, a licensed processor, or the user's own wallet holds the funds; we build the system around it and never take custody.", + card: "Payments and cryptocurrency integration. We never take custody of funds.", + metaTitle: "Crypto & Payments Integration Software (Non-Custodial) | Such Software", + metaDescription: + "Non-custodial payments and cryptocurrency software: Stripe and multi-processor integration, Monero and on-chain checkout, in production since 2014. The processor or wallet holds the funds. Kennett Square, PA.", + }, + { + slug: "education", + label: "Education & Science", + accent: "amber", + title: "Education & science", + lead: "PhD-led radiation-science teaching, training, and speaking from years at a national lab, plus learning-through-play games that teach real science and math. We publish our methods open-source.", + card: "PhD-led radiation-science teaching and games that teach real science.", + metaTitle: "Nuclear & Radiation-Science Education, GEANT4 Training | Such Software", + metaDescription: + "PhD-led radiation-science education: Monte Carlo methods with GEANT4, shielding and detector physics, open-source labs, plus learning-through-play science and math games. Lawrence Livermore background.", + }, +]; + +export function pillarBySlug(slug: string): Pillar | undefined { + return pillars.find((p) => p.slug === slug); +} + +// ---- Proof items (real products behind each pillar) --------------------- + +export type Proof = { + title: string; + blurb: string; + img?: string; // /images/products/* + href?: string; // internal detail page or external + tag?: string; // status pill +}; + +const commerceProof: Proof[] = [ + { title: "Webshops", blurb: "Our multi-tenant commerce platform: fully-themed storefronts, print-on-demand, non-custodial crypto checkout, and automated tax, on revenue share.", img: "/images/products/occupy-wallets.png", href: "/products/webshops", tag: "Flagship" }, + { title: "Custom builds", blurb: "Real-time web apps, multiplayer experiences, and live dashboards on Next.js, Socket.io, and WebRTC.", img: "/images/products/custom-websites.svg", href: "/products/custom-websites", tag: "Live" }, + { title: "Grin BTCPay plugin", blurb: "An open-source BTCPay Server plugin we built to accept Grin (Mimblewimble) payments, including auto-Tor invoice exchange.", tag: "Open source" }, + { title: "Evaluetron", blurb: "A self-hostable AI-compute platform: one core that runs a personal image bot or a paid multi-customer service, with an append-only credit ledger and pricing built in.", tag: "Building" }, +]; + +const gamesProof: Proof[] = [ + { title: "Suchoice", blurb: "Stop overthinking decisions: snap a photo, let AI read the options, spin the wheel. iOS and Android.", img: "/images/products/suchoice.png", href: "/products/suchoice", tag: "Live" }, + { title: "Vegan IQ", blurb: "1,000+ plant-based trivia questions across 8 categories, with a daily challenge and weekly quiz. iOS and Android.", img: "/images/products/vegan-iq.png", href: "/products/vegan-iq", tag: "Live" }, + { title: "Bloomword", blurb: "A daily word game where every word you find grows a living 3D typographic tree. Free at bloomword.earth, launching on mobile.", img: "/images/products/bloomword.svg", href: "/products/bloomword", tag: "Live" }, + { title: "Bauhaus Echo", blurb: "A visual memory puzzle game inspired by Bauhaus design. Android, iOS, and web.", img: "/images/products/bauhaus-echo.png", href: "/products/bauhaus-echo", tag: "Live" }, + { title: "Such Moon Launch", blurb: "Vry rocket, much landing, wow: a Wownero-themed pixel rocket arcade with 11 levels and tilt-to-steer. Everywhere.", img: "/images/products/such-moon-launch.png", href: "/products/such-moon-launch", tag: "Live" }, +]; + +const cryptoProof: Proof[] = [ + { title: "Payments consulting", blurb: "Stripe and multi-processor integrations, reconciliation tooling, Monero and on-chain integration. The processor or wallet moves the money; we wire it in.", tag: "Service" }, + { title: "Smirk Wallet", blurb: "A non-custodial multi-asset browser wallet: send, receive, and tip by username on Telegram and Discord. BTC, LTC, XMR, WOW, GRIN.", img: "/images/products/smirk-wallet.png", href: "/products/smirk-wallet", tag: "Live" }, + { title: "Hash Bags", blurb: "A mobile multi-chain wallet forked from Cake Wallet, tuned for the privacy-coin ecosystem.", tag: "Beta" }, + { title: "Evaluetron", blurb: "Pay-for-compute done right: an append-only credit ledger, a job queue, and an evaluator that lets on-demand work preempt opportunistic work. Customers can never self-credit.", tag: "Building" }, +]; + +const educationProof: Proof[] = [ + { title: "Barns & Neutrons", blurb: "A cozy exploration-puzzle game across the real Table of Nuclides: capture neutrons, coax decays, and learn honest nuclear physics. Our premiere visual work.", img: "/images/products/barns-and-neutrons.svg", href: "/products/barns-and-neutrons", tag: "Coming soon" }, + { title: "Nuclear consulting & training", blurb: "PhD-led radiation-science teaching: Monte Carlo methods with GEANT4, shielding and dose fundamentals, detector physics, and open-source labs.", href: "https://jwinterm.github.io/geant4-radiation-labs/", tag: "Service" }, + { title: "Numchangers", blurb: "A kids math game (ages 5-8) where numbers morph into dots, shapes, and 3D characters, so arithmetic becomes a visible action instead of a quiz. Godot, mobile-first.", tag: "Early" }, +]; + +export function proofFor(slug: string): Proof[] { + if (slug === "commerce") return commerceProof; + if (slug === "games") return gamesProof; + if (slug === "crypto") return cryptoProof; + return educationProof; +} + +// ---- FAQ, tagged by pillar so each subpage shows the relevant ones ------- + +export type Faq = { q: string; a: string; pillars: Pillar["slug"][] }; + +export const faqs: Faq[] = [ + { q: "What does Such Software build?", a: "Four things, from one small team: custom e-commerce and web apps on revenue share, games and mobile apps we ship ourselves, cryptocurrency and payments software (integration only, never custody), and PhD-led radiation-science education. The pillars below break each down with the products behind them.", pillars: ["commerce", "games", "crypto", "education"] }, + { q: "Do you take revenue-share work?", a: "Yes. For a limited number of partners we build and operate products (such as webshops) for a share of revenue instead of a large upfront fee, so our incentives line up with yours.", pillars: ["commerce"] }, + { q: "Do you build for accessibility?", a: "Yes. We engineer front-ends to meet WCAG 2.2 AA and audit against it, alongside Core Web Vitals, as part of every project.", pillars: ["commerce", "games"] }, + { q: "Do you offer nuclear and radiation education?", a: "Yes. Our founder holds a PhD in radiation-detector materials and spent six years at Lawrence Livermore National Laboratory, plus shielding and spent-fuel work at Holtec. We teach radiation-science fundamentals and Monte Carlo methods, run GEANT4 training, and speak on these topics. Our GEANT4 radiation labs are published open-source (MIT / CC-BY). This is education and published methods.", pillars: ["education"] }, + { q: "Where are you based?", a: "We are a software studio in Kennett Square, Pennsylvania, working with clients remotely across the US and beyond.", pillars: ["commerce", "games", "crypto", "education"] }, + { q: "How does a project start?", a: "Reach out through the contact form with what you need. We scope it, propose an approach, and from there it can run as a fixed project or a performance-based revenue-share partnership.", pillars: ["commerce", "crypto"] }, +]; + +// ---- Shared colour maps (literal strings so Tailwind's JIT keeps them) --- + +export const borderL: Record = { + blue: "border-l-blue-500", + purple: "border-l-purple-500", + cyan: "border-l-cyan-500", + amber: "border-l-amber-500", +}; +export const chipAccent: Record = { + blue: "bg-blue-500/15 text-blue-700 dark:text-blue-300", + purple: "bg-purple-500/15 text-purple-700 dark:text-purple-300", + cyan: "bg-cyan-500/15 text-cyan-700 dark:text-cyan-300", + amber: "bg-amber-500/15 text-amber-700 dark:text-amber-300", +}; +export const hoverBorder: Record = { + blue: "hover:border-blue-500/30", + purple: "hover:border-purple-500/30", + cyan: "hover:border-cyan-500/30", + amber: "hover:border-amber-500/30", +}; +export const tagStyle: Record = { + Flagship: "bg-emerald-500/15 text-emerald-700 dark:text-emerald-300", + Live: "bg-green-500/15 text-green-700 dark:text-green-300", + Service: "bg-sky-500/15 text-sky-700 dark:text-sky-300", + "Open source": "bg-indigo-500/15 text-indigo-700 dark:text-indigo-300", + Beta: "bg-amber-500/15 text-amber-700 dark:text-amber-300", + Building: "bg-amber-500/15 text-amber-700 dark:text-amber-300", + Early: "bg-fuchsia-500/15 text-fuchsia-700 dark:text-fuchsia-300", + "Coming soon": "bg-fuchsia-500/15 text-fuchsia-700 dark:text-fuchsia-300", +};