feat(webshops): refresh demo shots (now genuinely distinct) + varied surfaces gallery + booking callout
The five demo storefronts were re-themed to look like different companies (distinct hero styles, card styles, density, grid, and homepage composition), so re-snap the hero cards and regenerate the theming-morph reel from the fresh shots. Add a "Every surface, not just the homepage" gallery: six live surfaces across different shops (yoga + coaching booking calendars, an editorial product page, a dense catalog grid, a crypto product, a themed cart) so the page shows platform depth the homepage crops hide. Call out booking/scheduling explicitly: a new "Booking & Scheduling" feature card, a booking FAQ (feeds FAQ JSON-LD), and a booking-calendar line in the surfaces lead. Demo images downsized to lean 1280w JPGs (png -> jpg).
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 556 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 648 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 778 KiB |
|
After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 132 KiB |
|
Before Width: | Height: | Size: 700 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 676 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 75 KiB |
@@ -1,6 +1,7 @@
|
||||
import { Header } from "@/components/layout/header";
|
||||
import { MobileNav } from "@/components/layout/mobile-nav";
|
||||
import { DemosGallery } from "@/components/products/demos-gallery";
|
||||
import { SurfacesGallery } from "@/components/products/surfaces-gallery";
|
||||
import { ShowcaseVideo } from "@/components/showcase/showcase-video";
|
||||
import { BrowserFrame } from "@/components/showcase/browser-frame";
|
||||
import { Card } from "@repo/ui/components/card";
|
||||
@@ -33,6 +34,7 @@ const faqs = [
|
||||
{ q: "Do I own my data?", a: "Yes. Unlike hosted platforms, you own your customer data, product catalog, and order history outright. There is no platform lock-in." },
|
||||
{ q: "Which payment methods are supported?", a: "Stripe via Stripe Connect (you stay the merchant of record and settle directly) and non-custodial cryptocurrency, Bitcoin, Litecoin, Monero, Wownero, and Grin. Crypto payments land straight in your own wallet; we never take custody of funds." },
|
||||
{ q: "Can you handle print-on-demand or dropshipping?", a: "Yes. We integrate Printful for print-on-demand and dropship fulfillment, so you can sell apparel and merch without holding inventory, orders route to production and ship automatically." },
|
||||
{ q: "Can I sell services or appointments, not just physical products?", a: "Yes. Appointment-based items get a themed booking calendar on the product page, with no shipping step and appointment details sent after checkout. It is the same engine behind the yoga studio's class booking and the coaching site's discovery calls in our live demos, so classes, sessions, consultations, and passes all work out of the box." },
|
||||
{ q: "What about sales tax?", a: "Tax is automated. We support Stripe Tax for full multi-state calculation and filing, or a self-hosted single-state estimator for sub-nexus tenants, routed per tenant so you collect the right amount at checkout." },
|
||||
{ q: "Can you migrate my existing store?", a: "Yes. We can migrate catalogs, customers, and order history from Shopify, WooCommerce, and other platforms." },
|
||||
];
|
||||
@@ -64,6 +66,10 @@ const features: Feature[] = [
|
||||
title: "Wallet & Web3 Login",
|
||||
body: "Optional Sign-In-With-Ethereum and wallet-based login alongside email, backed by a three-tier auth model, the operator chooses which methods each tenant offers, and each tenant's customers sign in their way.",
|
||||
},
|
||||
{
|
||||
title: "Booking & Scheduling",
|
||||
body: "Sell services, not just products: appointment-based items get a themed scheduling calendar at checkout, with no shipping step and appointment details sent after purchase. Classes, sessions, consultations, and passes work out of the box.",
|
||||
},
|
||||
{
|
||||
title: "Order Notifications",
|
||||
body: "Get pinged the moment a sale lands. Telegram and email notifications keep you and your team on top of new orders without babysitting a dashboard.",
|
||||
@@ -158,6 +164,22 @@ export default function WebshopsPage() {
|
||||
<DemosGallery />
|
||||
</section>
|
||||
|
||||
{/* Surfaces, it is not just the homepage that is themed */}
|
||||
<section aria-labelledby="surfaces-heading" className="mb-16">
|
||||
<h2 id="surfaces-heading" className="text-2xl md:text-3xl font-bold mb-2">
|
||||
Every surface, not just the homepage
|
||||
</h2>
|
||||
<p className="text-muted-foreground mb-8 max-w-3xl">
|
||||
Theming runs all the way down: product pages, catalog grids, cart, and checkout each
|
||||
carry the shop's palette, type, and layout. And the platform is more than a catalog,
|
||||
service shops get a real{" "}
|
||||
<span className="font-medium text-foreground">booking calendar</span>: yoga classes
|
||||
and coaching calls are scheduled right on the product page, themed to match. Here is a
|
||||
spread of live surfaces across five different shops.
|
||||
</p>
|
||||
<SurfacesGallery />
|
||||
</section>
|
||||
|
||||
{/* Feature grid, the real platform capabilities */}
|
||||
<section aria-labelledby="features-heading" className="mb-16">
|
||||
<h2 id="features-heading" className="text-2xl md:text-3xl font-bold mb-8">
|
||||
|
||||
@@ -76,10 +76,10 @@ function DemoCard({ demo }: { demo: Demo }) {
|
||||
cropped to the hero/nav (the most brand-distinctive region). */}
|
||||
<div className="h-40 w-full overflow-hidden">
|
||||
<Image
|
||||
src={`/images/demos/${demo.slug}.png`}
|
||||
src={`/images/demos/${demo.slug}.jpg`}
|
||||
alt={`${demo.name} demo storefront`}
|
||||
width={1280}
|
||||
height={800}
|
||||
height={720}
|
||||
className="h-40 w-full object-cover object-top transition-transform duration-700 group-hover:scale-[1.03]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
import Image from "next/image";
|
||||
import { Card } from "@repo/ui/components/card";
|
||||
|
||||
// Literal class strings per accent so Tailwind's JIT keeps them.
|
||||
const border: Record<string, string> = {
|
||||
violet: "border-violet-500/20 hover:border-violet-500/50",
|
||||
cyan: "border-cyan-500/20 hover:border-cyan-500/50",
|
||||
amber: "border-amber-500/20 hover:border-amber-500/50",
|
||||
blue: "border-blue-500/20 hover:border-blue-500/50",
|
||||
emerald: "border-emerald-500/20 hover:border-emerald-500/50",
|
||||
};
|
||||
const chip: Record<string, string> = {
|
||||
violet: "bg-violet-500/15 text-violet-700 dark:text-violet-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",
|
||||
blue: "bg-blue-500/15 text-blue-700 dark:text-blue-300",
|
||||
emerald: "bg-emerald-500/15 text-emerald-700 dark:text-emerald-300",
|
||||
};
|
||||
|
||||
type Surface = {
|
||||
img: string;
|
||||
title: string;
|
||||
blurb: string;
|
||||
shop: string;
|
||||
color: keyof typeof chip;
|
||||
href: string;
|
||||
};
|
||||
|
||||
// Deliberately varied surfaces across DIFFERENT shops: the point is to show
|
||||
// depth the homepage crops hide (booking calendars especially) and that every
|
||||
// surface is themed, not just the landing page.
|
||||
const surfaces: Surface[] = [
|
||||
{
|
||||
img: "yoga-booking",
|
||||
title: "Book a class on a themed calendar",
|
||||
blurb: "Service products get a real scheduling calendar, no shipping, appointment details after checkout.",
|
||||
shop: "Sage & Sun (yoga)",
|
||||
color: "violet",
|
||||
href: "https://yoga-demo.such.software/us/products/beginner-class",
|
||||
},
|
||||
{
|
||||
img: "coaching-booking",
|
||||
title: "Schedule a discovery call inline",
|
||||
blurb: "Same booking engine, different brand: sessions and packages scheduled right on the product page.",
|
||||
shop: "Compass (coaching)",
|
||||
color: "cyan",
|
||||
href: "https://coaching-demo.such.software/us/products/discovery-call",
|
||||
},
|
||||
{
|
||||
img: "artisan-product",
|
||||
title: "Editorial product pages",
|
||||
blurb: "Big imagery, calm type, expandable product and shipping details, tuned to the shop's personality.",
|
||||
shop: "Honeyglow (artisan)",
|
||||
color: "amber",
|
||||
href: "https://artisan-demo.such.software/us/products/beeswax-pillar",
|
||||
},
|
||||
{
|
||||
img: "merch-store",
|
||||
title: "Dense catalog with overlay cards",
|
||||
blurb: "A four-up grid with image-forward overlay cards, a different card style and density per tenant.",
|
||||
shop: "Aurora Print (merch)",
|
||||
color: "blue",
|
||||
href: "https://merch-demo.such.software/us/store",
|
||||
},
|
||||
{
|
||||
img: "crypto-product",
|
||||
title: "Digital goods, crypto checkout",
|
||||
blurb: "A dark gallery skin for downloads and prints, payable in Bitcoin, Monero, Wownero, or Grin.",
|
||||
shop: "0xCanvas (crypto)",
|
||||
color: "emerald",
|
||||
href: "https://crypto-demo.such.software/us/products/pixel-sunrise",
|
||||
},
|
||||
{
|
||||
img: "artisan-cart",
|
||||
title: "Cart and checkout in-brand",
|
||||
blurb: "The cart, summary, and checkout carry the shop's palette and type all the way to payment.",
|
||||
shop: "Honeyglow (artisan)",
|
||||
color: "amber",
|
||||
href: "https://artisan-demo.such.software/us/store",
|
||||
},
|
||||
];
|
||||
|
||||
function SurfaceCard({ s }: { s: Surface }) {
|
||||
return (
|
||||
<a
|
||||
href={s.href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="block group focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background rounded-[2rem]"
|
||||
aria-label={`Open the ${s.shop} demo (${s.title}) in a new tab`}
|
||||
>
|
||||
<Card className={`glass-card h-full !p-0 overflow-hidden cursor-pointer transition-colors ${border[s.color]}`}>
|
||||
<div className="aspect-[16/10] w-full overflow-hidden">
|
||||
<Image
|
||||
src={`/images/demos/${s.img}.jpg`}
|
||||
alt={`${s.shop}: ${s.title}`}
|
||||
width={1280}
|
||||
height={800}
|
||||
className="h-full w-full object-cover object-top transition-transform duration-700 group-hover:scale-[1.03]"
|
||||
/>
|
||||
</div>
|
||||
<div className="p-6">
|
||||
<span className={`inline-block text-xs font-medium px-2 py-0.5 rounded-full mb-3 ${chip[s.color]}`}>
|
||||
{s.shop}
|
||||
</span>
|
||||
<h3 className="text-lg font-bold mb-2 text-foreground">{s.title}</h3>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed">{s.blurb}</p>
|
||||
</div>
|
||||
</Card>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
export function SurfacesGallery() {
|
||||
return (
|
||||
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{surfaces.map((s) => (
|
||||
<SurfaceCard key={s.img} s={s} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||