Overview
The Weaverse Hydrogen theme follows a modern Shopify Hydrogen structure, optimized for performance and developer experience. Let's explore the key components of your theme.
Core Structure
🌳 my-theme├── 📁 app/│ ├── 📁 components/ # Reusable UI components│ ├── 📁 graphql/ # GraphQL queries and fragments│ ├── 📁 hooks/ # Custom React hooks│ ├── 📁 routes/ # Application routes│ ├── 📁 sections/ # Theme sections│ ├── 📁 styles/ # Global styles and Tailwind│ ├── 📁 types/ # TypeScript definitions│ ├── 📁 utils/ # Helper functions│ ├── 📁 weaverse/ # Weaverse configuration│ ├── 📄 entry.client.tsx│ ├── 📄 entry.server.tsx│ └── 📄 root.tsx├── 📁 public/ # Static assets├── 📄 server.ts # Server configuration├── 📄 vite.config.ts # Build configuration├── 📄 tailwind.config.js # Tailwind settings└── 📄 .env # Environment variables
Key Directories
/app/components
Reusable UI components:
// Example: app/components/Button.tsxexport function Button({ children, className = '', ...props }) { return ( <button className={`px-4 py-2 bg-primary text-white ${className}`} {...props} > {children} </button> );}
/app/sections
Theme sections for Weaverse Studio:
// Example: app/sections/Hero.tsximport { forwardRef } from 'react';
export type HeroProps = { heading: string; description: string; className?: string;};
export let schema = { title: 'Hero', type: 'hero', inspector: [ { group: 'Content', inputs: [ { type: 'text', name: 'heading', label: 'Heading' }, { type: 'textarea', name: 'description', label: 'Description' } ] } ]};
export let Hero = forwardRef<HTMLElement, HeroProps>((props, ref) => { let { heading, description, className = '' } = props; return ( <section ref={ref} className={`py-12 px-4 max-w-7xl mx-auto ${className}`} > <div className="text-center"> <h1 className="text-4xl font-bold tracking-tight sm:text-6xl"> {heading} </h1> <p className="mt-6 text-lg leading-8 text-gray-600"> {description} </p> </div> </section> );});
Hero.displayName = 'Hero';
/app/weaverse
Core Weaverse configuration files:
components.ts
- Component registryschema.server.ts
- Theme schemacreate-weaverse.server.ts
- Client setup
Essential Files
server.ts
Server configuration and Weaverse client integration:
import { WeaverseClient } from '@weaverse/hydrogen';import { components } from '~/weaverse/components';import { themeSchema } from '~/weaverse/schema.server';
export async function createAppLoadContext(request, env, executionContext) { // Initialize Hydrogen context let hydrogenContext = createHydrogenContext({ env, request, cache, waitUntil, session, i18n: getLocaleFromRequest(request), cart: { queryFragment: CART_QUERY_FRAGMENT }, });
// Initialize Weaverse client return { ...hydrogenContext, weaverse: new WeaverseClient({ ...hydrogenContext, request, cache, themeSchema, components, }), };}
entry.server.tsx
Server-side rendering setup:
import { RemixServer } from "@remix-run/react";import { createContentSecurityPolicy } from "@shopify/hydrogen";import type { AppLoadContext, EntryContext } from "@shopify/remix-oxygen";import { isbot } from "isbot";import { renderToReadableStream } from "react-dom/server";import { getWeaverseCsp } from "~/weaverse/csp";
export default async function handleRequest( request: Request, responseStatusCode: number, responseHeaders: Headers, remixContext: EntryContext, context: AppLoadContext,) { const { nonce, header, NonceProvider } = createContentSecurityPolicy({ ...getWeaverseCsp(request, context), shop: { checkoutDomain: context.env?.PUBLIC_CHECKOUT_DOMAIN || context.env?.PUBLIC_STORE_DOMAIN, storeDomain: context.env?.PUBLIC_STORE_DOMAIN, }, });
const body = await renderToReadableStream( <NonceProvider> <RemixServer context={remixContext} url={request.url} nonce={nonce} /> </NonceProvider>, { nonce, signal: request.signal, onError(error) { console.error(error); responseStatusCode = 500; }, }, );
if (isbot(request.headers.get("user-agent"))) { await body.allReady; }
responseHeaders.set("Content-Type", "text/html"); responseHeaders.set("Content-Security-Policy-Report-Only", header);
return new Response(body, { headers: responseHeaders, status: responseStatusCode, });}
.env
Required environment variables:
# Core ConfigurationSESSION_SECRET="foobar"
# Shopify ConfigurationPUBLIC_STORE_DOMAIN=your-store.myshopify.comPUBLIC_STOREFRONT_API_TOKEN=your-tokenPUBLIC_CUSTOMER_ACCOUNT_API_CLIENT_ID=your-client-idSHOP_ID=your-shop-idPUBLIC_CHECKOUT_DOMAIN=your-checkout-domain
# Optional Shopify ConfigurationPUBLIC_STOREFRONT_ID=your-storefront-id# PRIVATE_STOREFRONT_API_TOKEN=your-private-token
# Weaverse ConfigurationWEAVERSE_PROJECT_ID=your-project-id# WEAVERSE_API_KEY=your-api-key
# Additional Services (Optional)# PUBLIC_GOOGLE_GTM_ID=your-gtm-id# JUDGEME_PRIVATE_API_TOKEN=your-judgeme-token# ALI_REVIEWS_API_KEY=your-ali-reviews-key
# Custom Metafields & MetaobjectsMETAOBJECT_COLORS_TYPE=shopify--color-patternCUSTOM_COLLECTION_BANNER_METAFIELD=custom.collection_banner
# Shopify Inbox (Optional)# PUBLIC_SHOPIFY_INBOX_SHOP_ID=your-inbox-shop-id
Development Commands
# Install dependenciesnpm install
# Start developmentnpm run dev
# Build for productionnpm run build
# Preview production buildnpm run preview
Next Steps
Need help? Join our Community Slack.