Skip to content
Merged
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ NEXT_PUBLIC_SITE_URL=https://your-store.com
NEXT_PUBLIC_STORE_NAME=Spree Store
NEXT_PUBLIC_STORE_DESCRIPTION=A modern e-commerce storefront powered by Spree Commerce and Next.js.

# Demo-only: external links for hero CTAs and footer (remove for production)
NEXT_PUBLIC_GITHUB_URL=https://github.com/spree/storefront
Comment thread
damianlegawiec marked this conversation as resolved.
Resolved
NEXT_PUBLIC_QUICKSTART_URL=https://spreecommerce.org/docs/developer/storefront/nextjs/quickstart
NEXT_PUBLIC_LEARN_MORE_URL=https://spreecommerce.org
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

Comment thread
damianlegawiec marked this conversation as resolved.
Resolved
# Store SEO settings
STORE_SEO_TITLE=
STORE_META_DESCRIPTION=
Expand Down
16 changes: 11 additions & 5 deletions messages/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@
"myAccount": "Mein Konto"
},
"footer": {
"description": "Ein moderner E-Commerce-Shop, betrieben von Spree Commerce und Next.js.",
"description": "Open-Source-E-Commerce basierend auf Spree REST API, TypeScript SDK und Next.js. Selbst hosten. Eigene Daten. Keine Plattformgebühren.",
"testCardNote": "Testen Sie den Checkout mit der Karte {testCard} (beliebiges Ablaufdatum, beliebiger CVC).",
"forkOnGithub": "Diesen Storefront auf GitHub forken",
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
"quickstartGuide": "Schnellstartanleitung",
"learnMore": "Mehr über Spree Commerce erfahren",
"shop": "Shop",
"allProducts": "Alle Produkte",
"categories": "Kategorien",
Expand All @@ -53,10 +57,12 @@
"copyright": "© {year} {storeName}. Unterstützt durch Spree Commerce."
},
"home": {
"welcome": "Willkommen bei {storeName}",
"heroDescription": "Entdecken Sie großartige Produkte mit unserem modernen E-Commerce-Erlebnis, betrieben von Spree Commerce.",
"shopNow": "Jetzt einkaufen",
"browseCategories": "Kategorien durchsuchen",
"welcome": "{storeName} Next.js Storefront",
"heroDescription": "Ein produktionsreifer, quelloffener Storefront mit Next.js, React und dem Spree TypeScript SDK. Selbst hosten. Eigener Stack. Kein Vendor Lock-in. Keine Plattformgebühren.",
"heroDemoNote": "Dies ist eine Live-Demo. Produkte durchstöbern, in den Warenkorb legen und mit Testkarte {testCard} bezahlen (beliebiges Ablaufdatum, beliebiger CVC).",
"shopNow": "Demo erkunden",
"forkOnGithub": "Auf GitHub forken",
"quickstartGuide": "Schnellstartanleitung",
"featuredProducts": "Ausgewählte Produkte",
"viewAll": "Alle ansehen",
"qualityProducts": "Qualitätsprodukte",
Expand Down
16 changes: 11 additions & 5 deletions messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@
"myAccount": "My Account"
},
"footer": {
"description": "A modern e-commerce storefront powered by Spree Commerce and Next.js.",
"description": "Open-source ecommerce powered by Spree REST API, TypeScript SDK, and Next.js. Self-host it. Own your data. Zero platform fees.",
"testCardNote": "Test checkout with card {testCard} (any future expiry, any CVC).",
"forkOnGithub": "Fork this storefront on GitHub",
"quickstartGuide": "Quickstart guide",
"learnMore": "Learn more about Spree Commerce",
"shop": "Shop",
"allProducts": "All Products",
"categories": "Categories",
Expand All @@ -53,10 +57,12 @@
"copyright": "© {year} {storeName}. Powered by Spree Commerce."
},
"home": {
"welcome": "Welcome to {storeName}",
"heroDescription": "Discover amazing products with our modern e-commerce experience powered by Spree Commerce.",
"shopNow": "Shop Now",
"browseCategories": "Browse Categories",
"welcome": "{storeName} Next.js Storefront",
"heroDescription": "A production-ready, open-source storefront built with Next.js, React, and the Spree TypeScript SDK. Self-host it. Own your stack. No vendor lock-in. Zero platform fees.",
"heroDemoNote": "This is a live demo. Browse products, add to cart, and check out with test card {testCard} (any future expiry, any CVC).",
"shopNow": "Shop the Demo",
"forkOnGithub": "Fork on GitHub",
"quickstartGuide": "Quickstart Guide",
"featuredProducts": "Featured Products",
"viewAll": "View all",
"qualityProducts": "Quality Products",
Expand Down
16 changes: 11 additions & 5 deletions messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@
"myAccount": "Mi cuenta"
},
"footer": {
"description": "Una tienda en linea moderna impulsada por Spree Commerce y Next.js.",
"description": "Comercio electrónico de código abierto basado en Spree REST API, TypeScript SDK y Next.js. Alójalo tú mismo. Tus datos. Sin comisiones de plataforma.",
"testCardNote": "Prueba el checkout con la tarjeta {testCard} (cualquier fecha de expiración futura, cualquier CVC).",
"forkOnGithub": "Haz un fork de esta tienda en GitHub",
"quickstartGuide": "Guía de inicio rápido",
"learnMore": "Más información sobre Spree Commerce",
"shop": "Tienda",
"allProducts": "Todos los productos",
"categories": "Categorias",
Expand All @@ -53,10 +57,12 @@
"copyright": "\u00a9 {year} {storeName}. Impulsado por Spree Commerce."
},
"home": {
"welcome": "Bienvenido a {storeName}",
"heroDescription": "Descubre productos increibles con nuestra experiencia de comercio electronico moderna impulsada por Spree Commerce.",
"shopNow": "Comprar ahora",
"browseCategories": "Explorar categorias",
"welcome": "{storeName} Next.js Storefront",
"heroDescription": "Un storefront de código abierto listo para producción, construido con Next.js, React y el SDK TypeScript de Spree. Alójalo tú mismo. Tu stack. Sin dependencia de proveedores. Sin comisiones de plataforma.",
"heroDemoNote": "Esta es una demo en vivo. Explora productos, añade al carrito y paga con la tarjeta de prueba {testCard} (cualquier fecha de expiración futura, cualquier CVC).",
"shopNow": "Explorar la demo",
"forkOnGithub": "Fork en GitHub",
"quickstartGuide": "Guía de inicio rápido",
"featuredProducts": "Productos destacados",
"viewAll": "Ver todo",
"qualityProducts": "Productos de calidad",
Expand Down
16 changes: 11 additions & 5 deletions messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@
"myAccount": "Mon compte"
},
"footer": {
"description": "Une boutique en ligne moderne propulsee par Spree Commerce et Next.js.",
"description": "E-commerce open source basé sur Spree REST API, TypeScript SDK et Next.js. Auto-hébergé. Vos données. Zéro frais de plateforme.",
"testCardNote": "Testez le paiement avec la carte {testCard} (n'importe quelle date d'expiration future, n'importe quel CVC).",
"forkOnGithub": "Forker cette boutique sur GitHub",
"quickstartGuide": "Guide de démarrage rapide",
"learnMore": "En savoir plus sur Spree Commerce",
"shop": "Boutique",
"allProducts": "Tous les produits",
"categories": "Categories",
Expand All @@ -53,10 +57,12 @@
"copyright": "\u00a9 {year} {storeName}. Propulse par Spree Commerce."
},
"home": {
"welcome": "Bienvenue chez {storeName}",
"heroDescription": "Decouvrez des produits exceptionnels avec notre experience e-commerce moderne propulsee par Spree Commerce.",
"shopNow": "Acheter maintenant",
"browseCategories": "Parcourir les categories",
"welcome": "{storeName} Next.js Storefront",
"heroDescription": "Un storefront open source prêt pour la production, construit avec Next.js, React et le SDK TypeScript Spree. Auto-hébergé. Votre stack. Pas de dépendance fournisseur. Zéro frais de plateforme.",
"heroDemoNote": "Ceci est une démo en direct. Parcourez les produits, ajoutez au panier et payez avec la carte de test {testCard} (n'importe quelle date d'expiration future, n'importe quel CVC).",
"shopNow": "Explorer la démo",
"forkOnGithub": "Forker sur GitHub",
"quickstartGuide": "Guide de démarrage rapide",
"featuredProducts": "Produits en vedette",
"viewAll": "Voir tout",
"qualityProducts": "Produits de qualite",
Expand Down
16 changes: 11 additions & 5 deletions messages/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@
"myAccount": "Moje konto"
},
"footer": {
"description": "Nowoczesny sklep internetowy oparty na Spree Commerce i Next.js.",
"description": "Sklep e-commerce open source oparty na Spree REST API, TypeScript SDK i Next.js. Hostuj samodzielnie. Twoje dane. Zero opłat platformowych.",
"testCardNote": "Przetestuj checkout kartą {testCard} (dowolna przyszła data ważności, dowolny CVC).",
"forkOnGithub": "Forkuj ten sklep na GitHubie",
"quickstartGuide": "Przewodnik szybkiego startu",
"learnMore": "Dowiedz się więcej o Spree Commerce",
"shop": "Sklep",
"allProducts": "Wszystkie produkty",
"categories": "Kategorie",
Expand All @@ -53,10 +57,12 @@
"copyright": "© {year} {storeName}. Zasilany przez Spree Commerce."
},
"home": {
"welcome": "Witaj w {storeName}",
"heroDescription": "Odkryj niesamowite produkty dzięki nowoczesnemu sklepowi internetowemu opartemu na Spree Commerce.",
"shopNow": "Kup teraz",
"browseCategories": "Przeglądaj kategorie",
"welcome": "{storeName} Next.js Storefront",
"heroDescription": "Gotowy do produkcji, otwartoźródłowy storefront zbudowany z Next.js, React i Spree TypeScript SDK. Hostuj samodzielnie. Twój stack. Brak vendor lock-in. Zero opłat platformowych.",
"heroDemoNote": "To jest demo na żywo. Przeglądaj produkty, dodawaj do koszyka i płać kartą testową {testCard} (dowolna przyszła data ważności, dowolny CVC).",
"shopNow": "Poznaj demo",
"forkOnGithub": "Forkuj na GitHubie",
"quickstartGuide": "Przewodnik szybkiego startu",
"featuredProducts": "Polecane produkty",
"viewAll": "Zobacz wszystkie",
"qualityProducts": "Produkty wysokiej jakości",
Expand Down
34 changes: 28 additions & 6 deletions src/app/[country]/[locale]/(storefront)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { getTranslations } from "next-intl/server";
import { ProductCarousel } from "@/components/products/ProductCarousel";
import { Button } from "@/components/ui/button";
import { generateHomeMetadata } from "@/lib/metadata/home";
import { getStoreName } from "@/lib/store";
import { getSpreeDemoData, getStoreName } from "@/lib/store";

interface HomePageProps {
params: Promise<{
Expand All @@ -29,25 +29,47 @@ export default async function HomePage({ params }: HomePageProps) {
});
const storeName = getStoreName();

/* Demo-only: Remove this entire block for production. */
const { githubUrl, quickstartUrl } = getSpreeDemoData();
return (
<div>
{/* Hero Section */}
<section className="border-b border-gray-200">
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-24">
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-24">
<div className="text-center">
<h1 className="text-4xl md:text-5xl font-bold tracking-tight text-gray-900">
{t("welcome", { storeName })}
</h1>
<p className="mt-4 text-xl text-gray-500 max-w-2xl mx-auto">
<p className="mt-4 text-lg text-gray-600 max-w-2xl mx-auto">
{t("heroDescription")}
</p>
<div className="mt-8 flex justify-center gap-4">
{/* Demo-only: Remove for production. */}
<p className="mt-3 text-sm text-gray-400 max-w-xl mx-auto">
{t("heroDemoNote", {
testCard: "4242 4242 4242 4242",
})}
</p>
<div className="mt-8 flex justify-center gap-4 flex-wrap">
<Button size="lg" asChild>
<Link href={`${basePath}/products`}>{t("shopNow")}</Link>
</Button>
{/* Demo-only: Remove for production. */}
<Button variant="outline" size="lg" asChild>
<Link
href={githubUrl}
target="_blank"
rel="noopener noreferrer"
>
{t("forkOnGithub")}
</Link>
</Button>
<Button variant="outline" size="lg" asChild>
<Link href={`${basePath}/products`}>
{t("browseCategories")}
<Link
href={quickstartUrl}
target="_blank"
rel="noopener noreferrer"
>
{t("quickstartGuide")} &rarr;
</Link>
</Button>
</div>
Expand Down
43 changes: 42 additions & 1 deletion src/components/layout/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@ import type { Category } from "@spree/sdk";
import Link from "next/link";
import { getTranslations } from "next-intl/server";
import { POLICY_LINKS } from "@/lib/constants/policies";
import { getStoreDescription, getStoreName } from "@/lib/store";
import {
getSpreeDemoData,
getStoreDescription,
getStoreName,
} from "@/lib/store";

const storeName = getStoreName();
const storeDescription = getStoreDescription();

// Demo-only: Remove for production.
const { githubUrl, quickstartUrl, learnMoreUrl } = getSpreeDemoData();

Comment thread
damianlegawiec marked this conversation as resolved.
Resolved
interface FooterProps {
rootCategories: Category[];
basePath: string;
Expand All @@ -25,12 +32,46 @@ export async function Footer({
<footer className="bg-primary text-gray-300">
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-12">
<div className="grid grid-cols-1 gap-8 md:grid-cols-5">
{/* Demo-only: Remove for production. */}
{/* Brand */}
<div className="col-span-1 md:col-span-2">
<span className="text-xl font-bold text-white">{storeName}</span>
<p className="mt-4 text-sm text-neutral-400">
{t("description") || storeDescription}
</p>
{/* Demo-only: Remove for production. */}
<p className="mt-2 text-xs text-neutral-500">
{t("testCardNote", {
testCard: "4242 4242 4242 4242",
})}
</p>
{/* Demo-only: Remove for production. */}
<div className="mt-4 flex flex-col gap-2">
<Link
href={githubUrl}
target="_blank"
rel="noopener noreferrer"
className="text-sm text-white hover:text-neutral-200 transition-colors font-medium"
>
{t("forkOnGithub")} &rarr;
</Link>
<Link
href={quickstartUrl}
target="_blank"
rel="noopener noreferrer"
className="text-sm text-neutral-400 hover:text-neutral-200 transition-colors"
>
{t("quickstartGuide")}
</Link>
<Link
href={learnMoreUrl}
target="_blank"
rel="noopener noreferrer"
className="text-sm text-neutral-400 hover:text-neutral-200 transition-colors"
>
{t("learnMore")}
</Link>
</div>
</div>

{/* Links */}
Expand Down
28 changes: 28 additions & 0 deletions src/lib/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,31 @@ export function getStoreEmailFrom(): string {
export function isStoreEmailFromFallback(): boolean {
return !process.env.EMAIL_FROM;
}

// Demo-only: Remove for production.

export interface SpreeDemoData {
githubUrl: string;
quickstartUrl: string;
learnMoreUrl: string;
}

/**
* Demo-only: Remove for production.
* Returns external URLs for demo CTAs and footer links.
*/
export function getSpreeDemoData(): SpreeDemoData {
Comment thread
damianlegawiec marked this conversation as resolved.
Resolved
return {
githubUrl: ensureProtocol(
process.env.NEXT_PUBLIC_GITHUB_URL ||
"https://github.com/spree/storefront",
),
quickstartUrl: ensureProtocol(
process.env.NEXT_PUBLIC_QUICKSTART_URL ||
"https://spreecommerce.org/docs/developer/storefront/nextjs/quickstart",
),
learnMoreUrl: ensureProtocol(
process.env.NEXT_PUBLIC_LEARN_MORE_URL || "https://spreecommerce.org",
),
Comment thread
Cichorek marked this conversation as resolved.
Resolved
};
}
Loading