Files
zeekay ac64d5d7dd Folds say one line: every first screen keeps its heading and a single lede
The owner's spec for a landing page is the models bento's: monochrome, the
words left and the art right, no extra prose. The folds carried two to four
sentences under each heading, and some a claim, a lede and a list besides.
Each now says one line: ProductLanding the tagline where a page states one
(the lede still describes it to search), a claim alone where the claim is
the line (/payments, /treasury, /zap, the extension), and elsewhere the
sentence that says what the thing is. /philosophy's two points, /dns' claim
that repeated its title, /calculator's capabilities line and the
Spare clauses on /research and /learn go.
2026-10-30 06:42:40 -07:00

133 lines
8.0 KiB
TypeScript

'use client'
import {
BarChart,
Book,
Code,
CreditCard,
Database,
ExternalLink,
GitBranch,
Gift,
Globe,
Layers,
Package,
Server,
Shield,
ShoppingCart,
Tags,
Truck,
Zap,
} from "lucide-react"
import APIEndpoints from "@/components/commerce/APIEndpoints"
import UseCases from "@/components/commerce/UseCases"
import { Cards } from "@/components/product/ProductLanding"
import { Aside } from "@/components/products/Aside"
import { Lede } from "@/components/products/Lede"
import { phrase } from "@hanzo/i18n"
import { Steps } from "@/components/preview/steps"
import { ProductFooter } from "@/components/products/ProductFooter"
import { Start } from "@/components/products/Start"
import { useI18n } from '@hanzo/i18n/react'
const DOCS = "https://docs.hanzo.ai/docs/cli/commerce"
const CONSOLE = "https://platform.hanzo.ai"
/** An order, start to end, one step at a time, walked beside the heading: the page's own words. */
const ORDER = [
{ title: phrase('Product and variant'), body: phrase('A product holds the description; a variant holds the size, the colour and the price.') },
{ title: phrase('Cart'), body: phrase('A cart is a real object with its own id, so someone can leave and come back.') },
{ title: phrase('Authorize'), body: phrase('Hold the money when the order is placed.') },
{ title: phrase('Capture'), body: phrase('Take it when the box ships.') },
{ title: phrase('Refund or return'), body: phrase('A return is a first-class object rather than a note in a support ticket.') },
]
export default function CommerceClient() {
const { t } = useI18n()
return (
<>
<Lede
preview={<Steps title={phrase('An order, start to end')} icon={<ShoppingCart size={12} color="currentColor" />} steps={ORDER} />}
badge={t("Headless E-commerce Platform")}
badgeIcon={ShoppingCart}
title="Hanzo Commerce"
actions={[
{ label: t('Read the docs'), href: DOCS, icon: ExternalLink },
{ label: 'Console', href: CONSOLE },
]}
>
{t('Products, carts, checkout, orders and returns behind an API, with no storefront attached.')}
</Lede>
<Cards
grid={{
title: t('What it keeps track of'),
sub: t('The nouns a shop is made of, each one addressable and none of them assuming what your site looks like.'),
items: [
{ icon: ShoppingCart, title: t('Carts'), body: t('A cart is a real object with its own id, so someone can leave and come back, and you can look at what they left in it.') },
{ icon: Package, title: t('Products and variants'), body: t('A product holds the description; a variant holds the size, the colour and the price. Stock is tracked on the variant, which is the thing people actually buy.') },
{ icon: CreditCard, title: t('Authorize and capture'), body: t('Two steps, not one. Hold the money when the order is placed and take it when the box ships, which is what your accountant and your customer both expect.') },
{ icon: Gift, title: t('Coupons and discounts'), body: t('Applied to a cart or to an invoice, and recorded as their own line. The reason a total came out lower survives the transaction.') },
{ icon: Tags, title: t('Prices per store'), body: t('One catalogue can answer differently for different stores. The product does not have to be duplicated to be priced twice.') },
{ icon: BarChart, title: t('Subscriptions'), body: t('Plans, prices and renewals sit in the same service as the orders, so a customer who buys once and subscribes once is one customer with one history.') },
{ icon: Truck, title: t('Orders, refunds and returns'), body: t('The whole life of an order, including the parts nobody demos. A return is a first-class object rather than a note in a support ticket.') },
{ icon: Globe, title: t('Many stores, one install'), body: t('Stores are scoped by organisation, so an agency or a marketplace runs several without running several copies of this.') },
{ icon: Shield, title: t('It never sees a card'), body: t('Card numbers are tokenized in a separate service and this one only ever holds the token. That is a smaller thing to secure, and a much smaller thing to be audited on.') },
{ icon: Database, title: t('Your data, per tenant'), body: t("Each organisation's records live in its own store. Isolation is a file boundary rather than a WHERE clause somebody has to remember to write.") },
],
}}
/>
<APIEndpoints />
<UseCases />
<Cards
grid={{
title: t('Who takes the money'),
sub: t('The processor is a setting, not an architecture. Each one gets its own webhook endpoint, so adding a second — or leaving the first — is a change here rather than a change in your checkout.'),
items: [
{ title: t('Payment Gateways'), points: ['Stripe', 'PayPal', 'Adyen', 'Square', 'Braintree', 'Klarna', 'Affirm', 'Apple Pay'] },
{ title: t('Marketing & CRM'), points: ['Mailchimp', 'Klaviyo', 'HubSpot', 'Salesforce', 'Segment', 'Meta Pixel', 'Google Analytics', 'Customer.io'] },
{ title: t('Shipping & Fulfillment'), points: ['ShipStation', 'ShipBob', 'EasyPost', 'FedEx', 'UPS', 'USPS', 'DHL', 'AfterShip'] },
{ title: t('Accounting & ERP'), points: ['QuickBooks', 'Xero', 'NetSuite', 'SAP', 'Avalara', 'TaxJar', 'Sage', 'Microsoft Dynamics'] },
],
}}
/>
<Cards
grid={{
title: t('What you are running'),
sub: t('Worth knowing before you put your revenue behind it.'),
items: [
{ icon: Server, title: t('One Go binary'), body: t('A single container with no queue, no cache tier and no companion services to stand up beside it. Run it locally the same way it runs in production.') },
{ icon: Database, title: t('A store per organisation'), body: t("Tenants are separated by where their data lives rather than by a column, so one tenant's query cannot reach another's rows.") },
{ icon: Shield, title: t('Outside the card boundary'), body: t('Card numbers are tokenized by a separate service. This one is connected to that boundary without being inside it, which is the whole point of drawing one.') },
{ icon: Zap, title: t('Identity from Hanzo IAM'), body: t('Sign-in, organisations and tokens come from IAM. There is no second user table here to fall out of step with the first.') },
{ icon: Layers, title: t('Mounts into the cloud binary'), body: t('It runs on its own or as a subsystem inside the unified Hanzo Cloud binary. Same code, same routes, one fewer process to operate.') },
{ icon: GitBranch, title: t('Open source'), body: t('MIT or Apache-2.0, your choice. Read how your money is handled instead of taking our word for it.') },
],
}}
/>
<Cards
grid={{
title: t('Create a product, then sell it'),
sub: t('The whole thing runs from one container. Point your front end at it and take an order.'),
items: [
{ icon: ShoppingCart, title: t('Start Selling'), body: t('Launch your store with our easy-to-use platform'), link: { label: t('Try Hanzo'), href: '/login' } },
{ icon: Book, title: t('Documentation'), body: t('Explore our guides and API references'), link: { label: t('View Docs'), href: DOCS } },
{ icon: Code, title: t('For Developers'), body: t('Integrate our APIs into your applications'), link: { label: t('API Reference'), href: 'https://docs.hanzo.ai/docs' } },
],
}}
/>
<Aside title={t("Need a Custom Solution?")} links={[{ label: t('Contact Sales'), href: '/contact-sales' }]}>
{t('Our team of experts can help you design and implement a tailored e-commerce solution for your unique business needs.')}
</Aside>
<Start title={t("Get started with Commerce")} docs={DOCS} repo="https://github.com/hanzoai" />
<ProductFooter slug="commerce" name="Commerce" />
</>
)
}