$npx -y skills add Weaverse/shopify-hydrogen-skills --skill weaverse-hydrogenBuild Shopify Hydrogen storefronts with Weaverse — components, schemas, loaders, theming, data fetching, React Router v7, deployment, and advanced features.
| 1 | # Weaverse Hydrogen — Agent Skill |
| 2 | |
| 3 | > Build Shopify Hydrogen storefronts with Weaverse visual page builder. |
| 4 | > Docs: https://docs.weaverse.io | GitHub: https://github.com/Weaverse |
| 5 | |
| 6 | ## Live Documentation |
| 7 | |
| 8 | For the most up-to-date Weaverse documentation, use these scripts: |
| 9 | |
| 10 | - `node scripts/search_weaverse_docs.mjs "<query>"` — search Weaverse docs |
| 11 | - `node scripts/get_weaverse_page.mjs "<page-path>"` — fetch a specific page (use paths from search results) |
| 12 | - Weaverse docs: https://docs.weaverse.io |
| 13 | |
| 14 | **Examples:** |
| 15 | ```bash |
| 16 | node scripts/search_weaverse_docs.mjs "component schema" |
| 17 | node scripts/search_weaverse_docs.mjs "data fetching" |
| 18 | node scripts/get_weaverse_page.mjs "development-guide/component-schema" |
| 19 | node scripts/get_weaverse_page.mjs "api-reference/weaverse-client" |
| 20 | ``` |
| 21 | |
| 22 | The reference files below provide offline context but may not reflect the latest changes. |
| 23 | |
| 24 | --- |
| 25 | |
| 26 | ## What is Weaverse? |
| 27 | |
| 28 | Weaverse is a visual page builder for Shopify Hydrogen. It lets merchants customize storefronts via a drag-and-drop Studio while developers build type-safe React components with schemas that define the editor UI. |
| 29 | |
| 30 | **Stack:** React 19 · React Router v7 · Shopify Hydrogen · TypeScript · Tailwind CSS · Vite |
| 31 | |
| 32 | --- |
| 33 | |
| 34 | ## 1. Project Structure |
| 35 | |
| 36 | ``` |
| 37 | app/ |
| 38 | ├── components/ # Reusable UI components |
| 39 | ├── graphql/ # GraphQL queries & fragments |
| 40 | ├── hooks/ # Custom React hooks |
| 41 | ├── routes/ # React Router v7 route files |
| 42 | ├── sections/ # Weaverse section components ← YOUR WORK GOES HERE |
| 43 | ├── styles/ # Global styles + Tailwind |
| 44 | ├── weaverse/ |
| 45 | │ ├── components.ts # Component registry |
| 46 | │ ├── schema.server.ts # Theme schema (global settings) |
| 47 | │ └── csp.ts # Content Security Policy for Weaverse |
| 48 | ├── entry.client.tsx |
| 49 | ├── entry.server.tsx |
| 50 | └── root.tsx # Wrapped with withWeaverse(App) |
| 51 | server.ts # WeaverseClient initialization |
| 52 | vite.config.ts |
| 53 | react-router.config.ts |
| 54 | tailwind.config.js |
| 55 | .env |
| 56 | ``` |
| 57 | |
| 58 | --- |
| 59 | |
| 60 | ## 2. Component Anatomy |
| 61 | |
| 62 | Every Weaverse component has up to 3 exports from a single file (or directory): |
| 63 | |
| 64 | ```tsx |
| 65 | // app/sections/my-section/index.tsx |
| 66 | |
| 67 | // 1. Default export — React component |
| 68 | function MySection(props: MySectionProps) { ... } |
| 69 | export default MySection; |
| 70 | |
| 71 | // 2. Schema export — editor configuration |
| 72 | export let schema = createSchema({ ... }); |
| 73 | |
| 74 | // 3. Loader export (optional) — server-side data fetching |
| 75 | export let loader = async (args: ComponentLoaderArgs<DataType>) => { ... }; |
| 76 | ``` |
| 77 | |
| 78 | ### Minimal Example |
| 79 | |
| 80 | ```tsx |
| 81 | import { createSchema } from '@weaverse/hydrogen'; |
| 82 | import type { HydrogenComponentProps } from '@weaverse/hydrogen'; |
| 83 | |
| 84 | interface BannerProps extends HydrogenComponentProps { |
| 85 | heading: string; |
| 86 | description: string; |
| 87 | } |
| 88 | |
| 89 | function Banner({ heading, description, children, ...rest }: BannerProps) { |
| 90 | return ( |
| 91 | <section {...rest} className="py-16 px-4 text-center"> |
| 92 | <h2 className="text-3xl font-bold">{heading}</h2> |
| 93 | <p className="mt-4 text-lg text-gray-600">{description}</p> |
| 94 | {children} |
| 95 | </section> |
| 96 | ); |
| 97 | } |
| 98 | |
| 99 | export default Banner; |
| 100 | |
| 101 | export let schema = createSchema({ |
| 102 | type: 'banner', |
| 103 | title: 'Banner', |
| 104 | settings: [ |
| 105 | { |
| 106 | group: 'Content', |
| 107 | inputs: [ |
| 108 | { type: 'text', name: 'heading', label: 'Heading', defaultValue: 'Hello World' }, |
| 109 | { type: 'textarea', name: 'description', label: 'Description', defaultValue: 'Welcome to our store.' }, |
| 110 | ], |
| 111 | }, |
| 112 | ], |
| 113 | presets: { |
| 114 | heading: 'Hello World', |
| 115 | description: 'Welcome to our store.', |
| 116 | }, |
| 117 | }); |
| 118 | ``` |
| 119 | |
| 120 | ### Key Rules |
| 121 | |
| 122 | - **Spread `{...rest}`** on the root element — required for Weaverse Studio interaction. |
| 123 | - **Render `{children}`** if the component accepts child components (`childTypes`). |
| 124 | - **`forwardRef` is optional** in React 19. If using React 18, wrap with `forwardRef` and attach `ref` to root element. |
| 125 | - **`type` must be unique** across all components, use kebab-case (e.g., `hero-banner`). |
| 126 | |
| 127 | --- |
| 128 | |
| 129 | ## 3. Component Registration |
| 130 | |
| 131 | Components must be registered in `app/weaverse/components.ts`: |
| 132 | |
| 133 | ```tsx |
| 134 | import type { HydrogenComponent } from '@weaverse/hydrogen'; |
| 135 | |
| 136 | // MUST use namespace imports (import * as X), NOT default imports |
| 137 | import * as HeroBanner from '~/sections/hero-banner'; |
| 138 | import * as FeaturedCollection from '~/sections/featured-collection'; |
| 139 | import * as ProductCard from '~/sections/product-card'; |
| 140 | |
| 141 | export let components: HydrogenComponent[] = [ |
| 142 | HeroBanner, |
| 143 | FeaturedCollection, |
| 144 | ProductCard, |
| 145 | ]; |
| 146 | ``` |
| 147 | |
| 148 | **Common mistake:** Using `import HeroBanner from ...` — this won't work. Always `import * as HeroBanner from ...`. |
| 149 | |
| 150 | --- |
| 151 | |
| 152 | ## 4. Schema with `createSchema()` |
| 153 | |
| 154 | ```tsx |
| 155 | import { createSchema } from '@weaverse/hydrogen'; |
| 156 | |
| 157 | export let schema = createSchema({ |
| 158 | type: 'my-component', // Unique kebab-case identifier |
| 159 | title: 'My Component', // Display name in Studio |
| 160 | limit: 1 |