add nextjs style routes
This commit is contained in:
@@ -1,17 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { useParams } from "next/navigation";
|
||||
import { Render } from "@reacteditor/core";
|
||||
import { appConfig } from "@/editor.config";
|
||||
import resolveRoute from "@/lib/resolve-route";
|
||||
import schema from "@/app.schema.json";
|
||||
import globals from "@/app.globals.json";
|
||||
|
||||
export default function Page() {
|
||||
const params = useParams();
|
||||
const segments = Array.isArray(params?.slug) ? (params.slug as string[]) : [];
|
||||
const { key } = resolveRoute(segments);
|
||||
const { root, content } = (schema as any)[key] ?? {};
|
||||
const data = { root, content, globals };
|
||||
return <Render config={appConfig as any} data={data} />;
|
||||
}
|
||||
6
app/about/editor/page.tsx
Normal file
6
app/about/editor/page.tsx
Normal file
@@ -0,0 +1,6 @@
|
||||
import PageEditor from "@/components/page-editor";
|
||||
import page from "../page.json";
|
||||
|
||||
export default function EditorPage() {
|
||||
return <PageEditor page={page} routeKey="/app/about" />;
|
||||
}
|
||||
214
app/about/page.json
Normal file
214
app/about/page.json
Normal file
@@ -0,0 +1,214 @@
|
||||
{
|
||||
"root": {
|
||||
"props": {
|
||||
"title": "About — Pulse",
|
||||
"headerFont": "Archivo Black",
|
||||
"headerFontWeight": "400",
|
||||
"bodyFont": "Inter",
|
||||
"primaryColor": "#111111",
|
||||
"secondaryColor": "#707072",
|
||||
"accentColor": "#f5f5f5",
|
||||
"bgColor": "#ffffff",
|
||||
"fgColor": "#111111",
|
||||
"mutedColor": "#f5f5f5",
|
||||
"radius": "xl",
|
||||
"buttonRadius": "full",
|
||||
"shadow": "none",
|
||||
"maxWidth": "2xl"
|
||||
}
|
||||
},
|
||||
"content": [
|
||||
{
|
||||
"type": "navigation",
|
||||
"props": {
|
||||
"id": "nav-about",
|
||||
"brand": "PULSE",
|
||||
"links": [
|
||||
{
|
||||
"label": "Run",
|
||||
"href": "/collections/run"
|
||||
},
|
||||
{
|
||||
"label": "Train",
|
||||
"href": "/collections/train"
|
||||
},
|
||||
{
|
||||
"label": "Recover",
|
||||
"href": "/collections/recover"
|
||||
},
|
||||
{
|
||||
"label": "Sale",
|
||||
"href": "/collections/sale"
|
||||
},
|
||||
{
|
||||
"label": "About",
|
||||
"href": "/about"
|
||||
}
|
||||
],
|
||||
"showSearch": "yes",
|
||||
"showAccount": "yes",
|
||||
"showCart": "yes",
|
||||
"sticky": "yes",
|
||||
"tone": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "hero",
|
||||
"props": {
|
||||
"id": "hero-about",
|
||||
"tagline": "The lab",
|
||||
"heading": "We don't make activewear.",
|
||||
"subheading": "Pulse started in a converted warehouse with three coaches, two athletes, and a whiteboard full of things they wished worked better. Eight years later, the whiteboard is still there. So is the standard.",
|
||||
"buttons": [
|
||||
{
|
||||
"label": "Shop the kit",
|
||||
"href": "/search",
|
||||
"variant": "primary"
|
||||
}
|
||||
],
|
||||
"imageUrl": "https://supabase.frontend-ai.com/storage/v1/object/public/assets/themes/pulse-nike/hero-about.png",
|
||||
"align": "left",
|
||||
"height": "lg",
|
||||
"tone": "light"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "features",
|
||||
"props": {
|
||||
"id": "features-about",
|
||||
"tagline": "What we believe",
|
||||
"heading": "Three rules. No exceptions.",
|
||||
"subheading": "",
|
||||
"columns": "3",
|
||||
"items": [
|
||||
{
|
||||
"title": "Engineered",
|
||||
"body": "Every fabric, every seam, every fit decision starts with athletes on a track. Lab work comes after, if at all."
|
||||
},
|
||||
{
|
||||
"title": "Field tested",
|
||||
"body": "Twelve weeks of training. Two race blocks. One full season. Nothing leaves the lab without that on the record."
|
||||
},
|
||||
{
|
||||
"title": "Guaranteed",
|
||||
"body": "If it fails before its time, we replace it. If it fails on race day, we apologize and replace it. That's the deal."
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "hero",
|
||||
"props": {
|
||||
"id": "cover-about-performance",
|
||||
"tagline": "Used up is the goal",
|
||||
"heading": "Designed to be worn out, not preserved.",
|
||||
"subheading": "If you're babying your kit, we did something wrong. Bring it back when it's done — we'll send the next one.",
|
||||
"buttons": [],
|
||||
"imageUrl": "https://supabase.frontend-ai.com/storage/v1/object/public/assets/themes/pulse-nike/cover-performance.jpeg",
|
||||
"align": "left",
|
||||
"height": "lg",
|
||||
"tone": "light"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "newsletter-cta",
|
||||
"props": {
|
||||
"id": "newsletter-about",
|
||||
"tagline": "Field notes",
|
||||
"heading": "Weekly notes from the lab.",
|
||||
"subheading": "Test results, training blocks, gear we cut and gear we kept. Every Monday at 5:30am.",
|
||||
"buttonLabel": "Subscribe",
|
||||
"endpoint": "",
|
||||
"imageUrl": "https://supabase.frontend-ai.com/storage/v1/object/public/assets/themes/pulse-nike/newsletter.png",
|
||||
"layout": "split"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "footer",
|
||||
"props": {
|
||||
"id": "footer-about",
|
||||
"brand": "PULSE",
|
||||
"tagline": "Performance gear for athletes who break their kit before they break themselves.",
|
||||
"columns": [
|
||||
{
|
||||
"title": "Shop",
|
||||
"links": [
|
||||
{
|
||||
"label": "All gear",
|
||||
"href": "/search"
|
||||
},
|
||||
{
|
||||
"label": "New",
|
||||
"href": "/collections/new"
|
||||
},
|
||||
{
|
||||
"label": "Run",
|
||||
"href": "/collections/run"
|
||||
},
|
||||
{
|
||||
"label": "Train",
|
||||
"href": "/collections/train"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "About",
|
||||
"links": [
|
||||
{
|
||||
"label": "Our story",
|
||||
"href": "/about"
|
||||
},
|
||||
{
|
||||
"label": "The lab",
|
||||
"href": "/lab"
|
||||
},
|
||||
{
|
||||
"label": "Athletes",
|
||||
"href": "/athletes"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Help",
|
||||
"links": [
|
||||
{
|
||||
"label": "Shipping",
|
||||
"href": "/help/shipping"
|
||||
},
|
||||
{
|
||||
"label": "Returns",
|
||||
"href": "/help/returns"
|
||||
},
|
||||
{
|
||||
"label": "Lifetime guarantee",
|
||||
"href": "/help/guarantee"
|
||||
},
|
||||
{
|
||||
"label": "Contact",
|
||||
"href": "/contact"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"social": [
|
||||
{
|
||||
"label": "Instagram",
|
||||
"href": "#"
|
||||
},
|
||||
{
|
||||
"label": "Strava",
|
||||
"href": "#"
|
||||
},
|
||||
{
|
||||
"label": "YouTube",
|
||||
"href": "#"
|
||||
}
|
||||
],
|
||||
"showNewsletter": "no",
|
||||
"newsletterHeading": "",
|
||||
"newsletterEndpoint": "",
|
||||
"copyright": "© 2026 Pulse. Built to be replaced when used up."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
6
app/about/page.tsx
Normal file
6
app/about/page.tsx
Normal file
@@ -0,0 +1,6 @@
|
||||
import PageRender from "@/components/page-render";
|
||||
import page from "./page.json";
|
||||
|
||||
export default function Page() {
|
||||
return <PageRender page={page} />;
|
||||
}
|
||||
6
app/collections/[handle]/editor/page.tsx
Normal file
6
app/collections/[handle]/editor/page.tsx
Normal file
@@ -0,0 +1,6 @@
|
||||
import PageEditor from "@/components/page-editor";
|
||||
import page from "../page.json";
|
||||
|
||||
export default function EditorPage() {
|
||||
return <PageEditor page={page} routeKey="/app/collections/[handle]" />;
|
||||
}
|
||||
195
app/collections/[handle]/page.json
Normal file
195
app/collections/[handle]/page.json
Normal file
@@ -0,0 +1,195 @@
|
||||
{
|
||||
"root": {
|
||||
"props": {
|
||||
"title": "Collection — Pulse",
|
||||
"headerFont": "Archivo Black",
|
||||
"headerFontWeight": "400",
|
||||
"bodyFont": "Inter",
|
||||
"primaryColor": "#111111",
|
||||
"secondaryColor": "#707072",
|
||||
"accentColor": "#f5f5f5",
|
||||
"bgColor": "#ffffff",
|
||||
"fgColor": "#111111",
|
||||
"mutedColor": "#f5f5f5",
|
||||
"radius": "xl",
|
||||
"buttonRadius": "full",
|
||||
"shadow": "none",
|
||||
"maxWidth": "2xl"
|
||||
}
|
||||
},
|
||||
"content": [
|
||||
{
|
||||
"type": "navigation",
|
||||
"props": {
|
||||
"id": "nav-collection",
|
||||
"brand": "PULSE",
|
||||
"links": [
|
||||
{
|
||||
"label": "Run",
|
||||
"href": "/collections/run"
|
||||
},
|
||||
{
|
||||
"label": "Train",
|
||||
"href": "/collections/train"
|
||||
},
|
||||
{
|
||||
"label": "Recover",
|
||||
"href": "/collections/recover"
|
||||
},
|
||||
{
|
||||
"label": "Sale",
|
||||
"href": "/collections/sale"
|
||||
},
|
||||
{
|
||||
"label": "About",
|
||||
"href": "/about"
|
||||
}
|
||||
],
|
||||
"showSearch": "yes",
|
||||
"showAccount": "yes",
|
||||
"showCart": "yes",
|
||||
"sticky": "yes",
|
||||
"tone": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "collection",
|
||||
"props": {
|
||||
"id": "collection-detail",
|
||||
"collection": null,
|
||||
"showDescription": "yes",
|
||||
"showCoverImage": "yes",
|
||||
"customCoverImage": "",
|
||||
"columns": "4",
|
||||
"limit": 24,
|
||||
"defaultSort": "BEST_SELLING",
|
||||
"showAvailability": "yes",
|
||||
"showPriceRange": "yes",
|
||||
"showProductType": "yes",
|
||||
"productTypeOptions": [
|
||||
{
|
||||
"label": "Tops"
|
||||
},
|
||||
{
|
||||
"label": "Shorts"
|
||||
},
|
||||
{
|
||||
"label": "Tights"
|
||||
},
|
||||
{
|
||||
"label": "Outerwear"
|
||||
},
|
||||
{
|
||||
"label": "Shoes"
|
||||
},
|
||||
{
|
||||
"label": "Accessories"
|
||||
}
|
||||
],
|
||||
"showVendor": "no",
|
||||
"vendorOptions": [],
|
||||
"showTags": "no",
|
||||
"tagOptions": [],
|
||||
"showColor": "yes",
|
||||
"colorOptions": [
|
||||
{
|
||||
"label": "Black",
|
||||
"color": "#111111"
|
||||
},
|
||||
{
|
||||
"label": "White",
|
||||
"color": "#ffffff"
|
||||
},
|
||||
{
|
||||
"label": "Grey",
|
||||
"color": "#707072"
|
||||
},
|
||||
{
|
||||
"label": "Volt",
|
||||
"color": "#d6ff3f"
|
||||
},
|
||||
{
|
||||
"label": "Sodium",
|
||||
"color": "#fa5400"
|
||||
}
|
||||
],
|
||||
"showStyle": "no",
|
||||
"styleOptions": [],
|
||||
"showSize": "yes",
|
||||
"sizeOptions": [
|
||||
{
|
||||
"label": "XS"
|
||||
},
|
||||
{
|
||||
"label": "S"
|
||||
},
|
||||
{
|
||||
"label": "M"
|
||||
},
|
||||
{
|
||||
"label": "L"
|
||||
},
|
||||
{
|
||||
"label": "XL"
|
||||
},
|
||||
{
|
||||
"label": "XXL"
|
||||
}
|
||||
],
|
||||
"showMaterial": "no",
|
||||
"materialOptions": [],
|
||||
"metafieldFilters": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "footer",
|
||||
"props": {
|
||||
"id": "footer-collection",
|
||||
"brand": "PULSE",
|
||||
"tagline": "Performance gear for athletes who break their kit before they break themselves.",
|
||||
"columns": [
|
||||
{
|
||||
"title": "Shop",
|
||||
"links": [
|
||||
{
|
||||
"label": "All gear",
|
||||
"href": "/search"
|
||||
},
|
||||
{
|
||||
"label": "New",
|
||||
"href": "/collections/new"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Help",
|
||||
"links": [
|
||||
{
|
||||
"label": "Shipping",
|
||||
"href": "/help/shipping"
|
||||
},
|
||||
{
|
||||
"label": "Returns",
|
||||
"href": "/help/returns"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"social": [
|
||||
{
|
||||
"label": "Instagram",
|
||||
"href": "#"
|
||||
},
|
||||
{
|
||||
"label": "Strava",
|
||||
"href": "#"
|
||||
}
|
||||
],
|
||||
"showNewsletter": "no",
|
||||
"newsletterHeading": "",
|
||||
"newsletterEndpoint": "",
|
||||
"copyright": "© 2026 Pulse. Built to be replaced when used up."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
6
app/collections/[handle]/page.tsx
Normal file
6
app/collections/[handle]/page.tsx
Normal file
@@ -0,0 +1,6 @@
|
||||
import PageRender from "@/components/page-render";
|
||||
import page from "./page.json";
|
||||
|
||||
export default function Page() {
|
||||
return <PageRender page={page} />;
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { useMemo } from "react";
|
||||
import { useParams } from "next/navigation";
|
||||
import { Editor, blocksPlugin, outlinePlugin } from "@reacteditor/core";
|
||||
import createTailwindCdnPlugin from "@reacteditor/plugin-tailwind-cdn";
|
||||
import { createShopifyPlugin } from "@reacteditor/plugin-shopify";
|
||||
import { mediaPlugin } from "@reacteditor/plugin-media";
|
||||
import { mediaAdapter } from "@/lib/adapters/media-adapter";
|
||||
import { appConfig } from "@/editor.config";
|
||||
import resolveRoute from "@/lib/resolve-route";
|
||||
import schema from "@/app.schema.json";
|
||||
import globals from "@/app.globals.json";
|
||||
|
||||
export default function EditorPage() {
|
||||
const params = useParams();
|
||||
const segments = Array.isArray(params?.slug) ? (params.slug as string[]) : [];
|
||||
const { key, path, params: routeParams } = resolveRoute(segments);
|
||||
const { root, content } = (schema as any)[key] ?? {};
|
||||
const data = { root, content, globals };
|
||||
|
||||
const plugins = useMemo(
|
||||
() => [
|
||||
blocksPlugin(),
|
||||
outlinePlugin(),
|
||||
mediaPlugin({
|
||||
adapter: mediaAdapter,
|
||||
}),
|
||||
createTailwindCdnPlugin(),
|
||||
createShopifyPlugin({
|
||||
storeDomain: process.env.NEXT_PUBLIC_SHOPIFY_DOMAIN ?? "mock.shop",
|
||||
publicAccessToken:
|
||||
process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN,
|
||||
}),
|
||||
],
|
||||
[],
|
||||
);
|
||||
|
||||
const handlePublish = async (nextData: any, route?: any) => {
|
||||
const resolved = route ?? { key };
|
||||
if (typeof window !== "undefined" && window.parent !== window) {
|
||||
window.parent.postMessage(
|
||||
{ type: "PUBLISH", data: { data: nextData, route: resolved } },
|
||||
"*",
|
||||
);
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="h-screen w-screen">
|
||||
<Editor
|
||||
config={appConfig as any}
|
||||
data={data}
|
||||
route={{ key, path, params: routeParams }}
|
||||
plugins={plugins}
|
||||
onPublish={handlePublish}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
6
app/editor/page.tsx
Normal file
6
app/editor/page.tsx
Normal file
@@ -0,0 +1,6 @@
|
||||
import PageEditor from "@/components/page-editor";
|
||||
import page from "../page.json";
|
||||
|
||||
export default function EditorPage() {
|
||||
return <PageEditor page={page} routeKey="/app" />;
|
||||
}
|
||||
302
app/page.json
Normal file
302
app/page.json
Normal file
@@ -0,0 +1,302 @@
|
||||
{
|
||||
"root": {
|
||||
"props": {
|
||||
"title": "Pulse — Made to Move",
|
||||
"headerFont": "Archivo Black",
|
||||
"headerFontWeight": "400",
|
||||
"bodyFont": "Inter",
|
||||
"primaryColor": "#111111",
|
||||
"secondaryColor": "#707072",
|
||||
"accentColor": "#f5f5f5",
|
||||
"bgColor": "#ffffff",
|
||||
"fgColor": "#111111",
|
||||
"mutedColor": "#f5f5f5",
|
||||
"radius": "xl",
|
||||
"buttonRadius": "full",
|
||||
"shadow": "none",
|
||||
"maxWidth": "2xl"
|
||||
}
|
||||
},
|
||||
"content": [
|
||||
{
|
||||
"type": "navigation",
|
||||
"props": {
|
||||
"id": "nav-home",
|
||||
"brand": "PULSE",
|
||||
"links": [
|
||||
{
|
||||
"label": "Run",
|
||||
"href": "/collections/run"
|
||||
},
|
||||
{
|
||||
"label": "Train",
|
||||
"href": "/collections/train"
|
||||
},
|
||||
{
|
||||
"label": "Recover",
|
||||
"href": "/collections/recover"
|
||||
},
|
||||
{
|
||||
"label": "Sale",
|
||||
"href": "/collections/sale"
|
||||
},
|
||||
{
|
||||
"label": "About",
|
||||
"href": "/about"
|
||||
}
|
||||
],
|
||||
"showSearch": "yes",
|
||||
"showAccount": "yes",
|
||||
"showCart": "yes",
|
||||
"sticky": "yes",
|
||||
"tone": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "hero",
|
||||
"props": {
|
||||
"id": "hero-home",
|
||||
"tagline": "Spring 2026",
|
||||
"heading": "Made to move.",
|
||||
"subheading": "Performance gear engineered for athletes who train like they mean it. Built light. Built honest. Built for the next mile.",
|
||||
"buttons": [
|
||||
{
|
||||
"label": "Shop the kit",
|
||||
"href": "/search",
|
||||
"variant": "primary"
|
||||
},
|
||||
{
|
||||
"label": "Our story",
|
||||
"href": "/about",
|
||||
"variant": "secondary"
|
||||
}
|
||||
],
|
||||
"imageUrl": "https://supabase.frontend-ai.com/storage/v1/object/public/assets/themes/pulse-nike/athletic-assortment.jpeg",
|
||||
"align": "left",
|
||||
"height": "lg",
|
||||
"tone": "light"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "products-carousel",
|
||||
"props": {
|
||||
"id": "carousel-home",
|
||||
"tagline": "Just dropped",
|
||||
"heading": "New arrivals",
|
||||
"subheading": "Fresh kit for the season ahead.",
|
||||
"limit": 12,
|
||||
"slidesPerView": "4",
|
||||
"ctaLabel": "Shop new",
|
||||
"ctaHref": "/collections/new"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "hero",
|
||||
"props": {
|
||||
"id": "cover-home-performance",
|
||||
"tagline": "Performance Series",
|
||||
"heading": "Engineered to outlast you.",
|
||||
"subheading": "Tested on track, trail, and treadmill. Every piece earns its place.",
|
||||
"buttons": [],
|
||||
"imageUrl": "https://supabase.frontend-ai.com/storage/v1/object/public/assets/themes/pulse-nike/cover-performance.jpeg",
|
||||
"align": "left",
|
||||
"height": "lg",
|
||||
"tone": "light"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "features",
|
||||
"props": {
|
||||
"id": "features-home",
|
||||
"tagline": "Why Pulse",
|
||||
"heading": "Three rules. No exceptions.",
|
||||
"subheading": "",
|
||||
"columns": "3",
|
||||
"items": [
|
||||
{
|
||||
"title": "Engineered",
|
||||
"body": "Every fabric, every seam, every fit decision starts with athletes on a track. Lab work comes after."
|
||||
},
|
||||
{
|
||||
"title": "Field tested",
|
||||
"body": "Twelve weeks. Two race blocks. One full season. Nothing ships without that on the record."
|
||||
},
|
||||
{
|
||||
"title": "Guaranteed",
|
||||
"body": "If it fails before its time, we replace it. If it fails on race day, we apologize and replace it."
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "hero",
|
||||
"props": {
|
||||
"id": "cover-home-discipline",
|
||||
"tagline": "Discipline",
|
||||
"heading": "The work happens before sunrise.",
|
||||
"subheading": "We make the kit. You do the work. Five-thirty isn't early — it's the only honest hour.",
|
||||
"buttons": [],
|
||||
"imageUrl": "https://supabase.frontend-ai.com/storage/v1/object/public/assets/themes/pulse-nike/cover-discipline.jpeg",
|
||||
"align": "left",
|
||||
"height": "lg",
|
||||
"tone": "light"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "collection-grid",
|
||||
"props": {
|
||||
"id": "collections-home",
|
||||
"tagline": "Shop by sport",
|
||||
"heading": "Built for what you actually do.",
|
||||
"subheading": "",
|
||||
"layout": "tiles",
|
||||
"limit": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "testimonials",
|
||||
"props": {
|
||||
"id": "testimonials-home",
|
||||
"tagline": "From the field",
|
||||
"heading": "Athletes on Pulse",
|
||||
"items": [
|
||||
{
|
||||
"quote": "Took the shell to Chamonix and back. Still smells, still works, still cheaper than therapy.",
|
||||
"author": "Mateo S.",
|
||||
"role": "Sub-3 marathoner / Boulder",
|
||||
"avatar": ""
|
||||
},
|
||||
{
|
||||
"quote": "I have one drawer of running gear. The Pulse half is the half I actually wear.",
|
||||
"author": "Priya N.",
|
||||
"role": "Ultra runner / Portland",
|
||||
"avatar": ""
|
||||
},
|
||||
{
|
||||
"quote": "Wore the shorts for an entire 16-week block. They held. That's the whole review.",
|
||||
"author": "Jonas R.",
|
||||
"role": "Track coach / Berlin",
|
||||
"avatar": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "newsletter-cta",
|
||||
"props": {
|
||||
"id": "newsletter-home",
|
||||
"tagline": "Field notes",
|
||||
"heading": "Weekly notes from the lab.",
|
||||
"subheading": "Test results, training blocks, gear we cut and gear we kept. Every Monday at 5:30am.",
|
||||
"buttonLabel": "Subscribe",
|
||||
"endpoint": "",
|
||||
"imageUrl": "https://supabase.frontend-ai.com/storage/v1/object/public/assets/themes/pulse-nike/newsletter.png",
|
||||
"layout": "split"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "footer",
|
||||
"props": {
|
||||
"id": "footer-home",
|
||||
"brand": "PULSE",
|
||||
"tagline": "Performance gear for athletes who break their kit before they break themselves.",
|
||||
"columns": [
|
||||
{
|
||||
"title": "Shop",
|
||||
"links": [
|
||||
{
|
||||
"label": "All gear",
|
||||
"href": "/search"
|
||||
},
|
||||
{
|
||||
"label": "New",
|
||||
"href": "/collections/new"
|
||||
},
|
||||
{
|
||||
"label": "Run",
|
||||
"href": "/collections/run"
|
||||
},
|
||||
{
|
||||
"label": "Train",
|
||||
"href": "/collections/train"
|
||||
},
|
||||
{
|
||||
"label": "Sale",
|
||||
"href": "/collections/sale"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "About",
|
||||
"links": [
|
||||
{
|
||||
"label": "Our story",
|
||||
"href": "/about"
|
||||
},
|
||||
{
|
||||
"label": "The lab",
|
||||
"href": "/lab"
|
||||
},
|
||||
{
|
||||
"label": "Athletes",
|
||||
"href": "/athletes"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Help",
|
||||
"links": [
|
||||
{
|
||||
"label": "Shipping",
|
||||
"href": "/help/shipping"
|
||||
},
|
||||
{
|
||||
"label": "Returns",
|
||||
"href": "/help/returns"
|
||||
},
|
||||
{
|
||||
"label": "Lifetime guarantee",
|
||||
"href": "/help/guarantee"
|
||||
},
|
||||
{
|
||||
"label": "Contact",
|
||||
"href": "/contact"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Legal",
|
||||
"links": [
|
||||
{
|
||||
"label": "Terms",
|
||||
"href": "/terms"
|
||||
},
|
||||
{
|
||||
"label": "Privacy",
|
||||
"href": "/privacy"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"social": [
|
||||
{
|
||||
"label": "Instagram",
|
||||
"href": "#"
|
||||
},
|
||||
{
|
||||
"label": "Strava",
|
||||
"href": "#"
|
||||
},
|
||||
{
|
||||
"label": "YouTube",
|
||||
"href": "#"
|
||||
}
|
||||
],
|
||||
"showNewsletter": "no",
|
||||
"newsletterHeading": "",
|
||||
"newsletterEndpoint": "",
|
||||
"copyright": "© 2026 Pulse. Built to be replaced when used up."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
6
app/page.tsx
Normal file
6
app/page.tsx
Normal file
@@ -0,0 +1,6 @@
|
||||
import PageRender from "@/components/page-render";
|
||||
import page from "./page.json";
|
||||
|
||||
export default function Page() {
|
||||
return <PageRender page={page} />;
|
||||
}
|
||||
6
app/products/[handle]/editor/page.tsx
Normal file
6
app/products/[handle]/editor/page.tsx
Normal file
@@ -0,0 +1,6 @@
|
||||
import PageEditor from "@/components/page-editor";
|
||||
import page from "../page.json";
|
||||
|
||||
export default function EditorPage() {
|
||||
return <PageEditor page={page} routeKey="/app/products/[handle]" />;
|
||||
}
|
||||
129
app/products/[handle]/page.json
Normal file
129
app/products/[handle]/page.json
Normal file
@@ -0,0 +1,129 @@
|
||||
{
|
||||
"root": {
|
||||
"props": {
|
||||
"title": "Pulse",
|
||||
"headerFont": "Archivo Black",
|
||||
"headerFontWeight": "400",
|
||||
"bodyFont": "Inter",
|
||||
"primaryColor": "#111111",
|
||||
"secondaryColor": "#707072",
|
||||
"accentColor": "#f5f5f5",
|
||||
"bgColor": "#ffffff",
|
||||
"fgColor": "#111111",
|
||||
"mutedColor": "#f5f5f5",
|
||||
"radius": "xl",
|
||||
"buttonRadius": "full",
|
||||
"shadow": "none",
|
||||
"maxWidth": "2xl"
|
||||
}
|
||||
},
|
||||
"content": [
|
||||
{
|
||||
"type": "navigation",
|
||||
"props": {
|
||||
"id": "nav-product",
|
||||
"brand": "PULSE",
|
||||
"links": [
|
||||
{
|
||||
"label": "Run",
|
||||
"href": "/collections/run"
|
||||
},
|
||||
{
|
||||
"label": "Train",
|
||||
"href": "/collections/train"
|
||||
},
|
||||
{
|
||||
"label": "Recover",
|
||||
"href": "/collections/recover"
|
||||
},
|
||||
{
|
||||
"label": "Sale",
|
||||
"href": "/collections/sale"
|
||||
},
|
||||
{
|
||||
"label": "About",
|
||||
"href": "/about"
|
||||
}
|
||||
],
|
||||
"showSearch": "yes",
|
||||
"showAccount": "yes",
|
||||
"showCart": "yes",
|
||||
"sticky": "yes",
|
||||
"tone": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "product-details",
|
||||
"props": {
|
||||
"id": "product-details",
|
||||
"product": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "products-carousel",
|
||||
"props": {
|
||||
"id": "carousel-related",
|
||||
"tagline": "Pairs well with",
|
||||
"heading": "Complete the kit",
|
||||
"limit": 8,
|
||||
"slidesPerView": "4",
|
||||
"ctaLabel": "Shop all",
|
||||
"ctaHref": "/collections"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "footer",
|
||||
"props": {
|
||||
"id": "footer-product",
|
||||
"brand": "PULSE",
|
||||
"tagline": "Performance gear for athletes who break their kit before they break themselves.",
|
||||
"columns": [
|
||||
{
|
||||
"title": "Shop",
|
||||
"links": [
|
||||
{
|
||||
"label": "All gear",
|
||||
"href": "/search"
|
||||
},
|
||||
{
|
||||
"label": "New",
|
||||
"href": "/collections/new"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Help",
|
||||
"links": [
|
||||
{
|
||||
"label": "Shipping",
|
||||
"href": "/help/shipping"
|
||||
},
|
||||
{
|
||||
"label": "Returns",
|
||||
"href": "/help/returns"
|
||||
},
|
||||
{
|
||||
"label": "Lifetime guarantee",
|
||||
"href": "/help/guarantee"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"social": [
|
||||
{
|
||||
"label": "Instagram",
|
||||
"href": "#"
|
||||
},
|
||||
{
|
||||
"label": "Strava",
|
||||
"href": "#"
|
||||
}
|
||||
],
|
||||
"showNewsletter": "no",
|
||||
"newsletterHeading": "",
|
||||
"newsletterEndpoint": "",
|
||||
"copyright": "© 2026 Pulse. Built to be replaced when used up."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
6
app/products/[handle]/page.tsx
Normal file
6
app/products/[handle]/page.tsx
Normal file
@@ -0,0 +1,6 @@
|
||||
import PageRender from "@/components/page-render";
|
||||
import page from "./page.json";
|
||||
|
||||
export default function Page() {
|
||||
return <PageRender page={page} />;
|
||||
}
|
||||
6
app/search/editor/page.tsx
Normal file
6
app/search/editor/page.tsx
Normal file
@@ -0,0 +1,6 @@
|
||||
import PageEditor from "@/components/page-editor";
|
||||
import page from "../page.json";
|
||||
|
||||
export default function EditorPage() {
|
||||
return <PageEditor page={page} routeKey="/app/search" />;
|
||||
}
|
||||
162
app/search/page.json
Normal file
162
app/search/page.json
Normal file
@@ -0,0 +1,162 @@
|
||||
{
|
||||
"root": {
|
||||
"props": {
|
||||
"title": "Shop — Pulse",
|
||||
"headerFont": "Archivo Black",
|
||||
"headerFontWeight": "400",
|
||||
"bodyFont": "Inter",
|
||||
"primaryColor": "#111111",
|
||||
"secondaryColor": "#707072",
|
||||
"accentColor": "#f5f5f5",
|
||||
"bgColor": "#ffffff",
|
||||
"fgColor": "#111111",
|
||||
"mutedColor": "#f5f5f5",
|
||||
"radius": "xl",
|
||||
"buttonRadius": "full",
|
||||
"shadow": "none",
|
||||
"maxWidth": "2xl"
|
||||
}
|
||||
},
|
||||
"content": [
|
||||
{
|
||||
"type": "navigation",
|
||||
"props": {
|
||||
"id": "nav-search",
|
||||
"brand": "PULSE",
|
||||
"links": [
|
||||
{
|
||||
"label": "Run",
|
||||
"href": "/collections/run"
|
||||
},
|
||||
{
|
||||
"label": "Train",
|
||||
"href": "/collections/train"
|
||||
},
|
||||
{
|
||||
"label": "Recover",
|
||||
"href": "/collections/recover"
|
||||
},
|
||||
{
|
||||
"label": "Sale",
|
||||
"href": "/collections/sale"
|
||||
},
|
||||
{
|
||||
"label": "About",
|
||||
"href": "/about"
|
||||
}
|
||||
],
|
||||
"showSearch": "yes",
|
||||
"showAccount": "yes",
|
||||
"showCart": "yes",
|
||||
"sticky": "yes",
|
||||
"tone": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "search-products",
|
||||
"props": {
|
||||
"id": "search-products",
|
||||
"heading": "All gear.",
|
||||
"subheading": "Filter by sport, fabric, fit, color. Or sort by what's been beaten the hardest.",
|
||||
"columns": "4",
|
||||
"limit": 24,
|
||||
"showAvailability": "yes",
|
||||
"showPriceRange": "yes",
|
||||
"showProductType": "yes",
|
||||
"showVendor": "no",
|
||||
"showTags": "yes",
|
||||
"metafieldFilters": [],
|
||||
"defaultSort": "BEST_SELLING",
|
||||
"productTypeOptions": [
|
||||
{
|
||||
"label": "Tops"
|
||||
},
|
||||
{
|
||||
"label": "Shorts"
|
||||
},
|
||||
{
|
||||
"label": "Tights"
|
||||
},
|
||||
{
|
||||
"label": "Outerwear"
|
||||
},
|
||||
{
|
||||
"label": "Shoes"
|
||||
},
|
||||
{
|
||||
"label": "Accessories"
|
||||
}
|
||||
],
|
||||
"vendorOptions": [],
|
||||
"tagOptions": [
|
||||
{
|
||||
"label": "New"
|
||||
},
|
||||
{
|
||||
"label": "Race day"
|
||||
},
|
||||
{
|
||||
"label": "Field tested"
|
||||
},
|
||||
{
|
||||
"label": "Sale"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "footer",
|
||||
"props": {
|
||||
"id": "footer-search",
|
||||
"brand": "PULSE",
|
||||
"tagline": "Performance gear for athletes who break their kit before they break themselves.",
|
||||
"columns": [
|
||||
{
|
||||
"title": "Shop",
|
||||
"links": [
|
||||
{
|
||||
"label": "All gear",
|
||||
"href": "/search"
|
||||
},
|
||||
{
|
||||
"label": "Run",
|
||||
"href": "/collections/run"
|
||||
},
|
||||
{
|
||||
"label": "Train",
|
||||
"href": "/collections/train"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Help",
|
||||
"links": [
|
||||
{
|
||||
"label": "Shipping",
|
||||
"href": "/help/shipping"
|
||||
},
|
||||
{
|
||||
"label": "Returns",
|
||||
"href": "/help/returns"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"social": [
|
||||
{
|
||||
"label": "Instagram",
|
||||
"href": "#"
|
||||
},
|
||||
{
|
||||
"label": "Strava",
|
||||
"href": "#"
|
||||
}
|
||||
],
|
||||
"showNewsletter": "no",
|
||||
"newsletterHeading": "",
|
||||
"newsletterEndpoint": "",
|
||||
"copyright": "© 2026 Pulse. Built to be replaced when used up."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
6
app/search/page.tsx
Normal file
6
app/search/page.tsx
Normal file
@@ -0,0 +1,6 @@
|
||||
import PageRender from "@/components/page-render";
|
||||
import page from "./page.json";
|
||||
|
||||
export default function Page() {
|
||||
return <PageRender page={page} />;
|
||||
}
|
||||
Reference in New Issue
Block a user