π Read the docs | π£ Join our community on Slack | π Report a bug
Maison is an innovative Shopify theme, powered by Hydrogen, React Router 7, and Weaverse, designed to create lightning-fast storefronts with exceptional performance. This theme combines a collection of powerful tools and features to streamline your Shopify development experience.
These Shopify (Plus) brands built on top of Weaverse/Maison:
- Entropy Home - curated home goods brand operated by Entropy Bright LLC.
- Karma and Luck - modern lifestyle brand rooted in timeless traditions and spiritual intention.
- Baltzar - curated selection of menswear brands from world renowned specialists such as Frank Clegg, Albert Thurston and Astorflex.
- iROCKER - provide life on the water to all, with gear that goes the extra mile.
- Roland (Brazil) - electronic musical instruments, drums, digital pianos, synthesizers, and dance/DJ gears.
- Timothy - British brand of premium travel goods and accessories.
- And many more...
- Live store: https://maison.weaverse.dev
- Customizing Maison on Weaverse Studio: https://studio.weaverse.io/demo?theme=maison
- Shopify Hydrogen / Oxygen / CLI
- Shopify Basic/Plus features support:
- New Shopify Customer Account API (OAuth-based)
- Combined Listings
- Product bundles
- React Router 7 for routing/SSR/data loading
- Biome code linter/formatter
- TypeScript with strict configuration
- GraphQL code generator
- Styled with TailwindCSS (v4)
- Radix-UI for accessible/reusable UI components
- class-variance-authority (cva) for component variants
- Swiper for carousels/sliders
- Framer Motion for animations
- Judge.me reviews integration
- Klaviyo integration for email marketing
- Full-featured setup of components and routes
- Fully customizable inside Weaverse Studio
Requirements:
- Node.js version 20.0.0 or higher
npmorpnpmpackage manager
Follow these steps to get started with Maison and begin crafting your Hydrogen-driven storefront:
- Install Weaverse Hydrogen Customizer from Shopify App Store.
- Create new Hydrogen storefront inside Weaverse.
- Initialize the project and start a local dev server with
@weaverse/clitool as instructed in the Weaverse Studio. - Open Weaverse Studio to start customizing and tailoring your storefront according to your preferences.
# Install dependencies
npm install
# Start development server on port 3456
npm run dev
# Run code quality checks before committing
npm run biome:fix
npm run typecheck
# Build for production
npm run build
# Run E2E tests
npm run e2eMaison uses parallel data loading for optimal performance. Every route loads Weaverse data alongside GraphQL queries using Promise.all():
import { data } from '@shopify/remix-oxygen';
import { type LoaderFunctionArgs } from '@shopify/remix-oxygen';
export async function loader({ context }: LoaderFunctionArgs) {
const { storefront, weaverse } = context;
// Parallel data loading for best performance
const [collections, weaverseData] = await Promise.all([
storefront.query(COLLECTIONS_QUERY),
weaverse.loadPage({ type: 'INDEX' }),
]);
return data({
collections,
weaverseData,
});
}weaverse is an WeaverseClient instance that has been injected into the app context by Weaverse. It provides a set of methods to interact with the Weaverse API.
// app/lib/context.ts
const hydrogenContext = createHydrogenContext({
env,
request,
cache,
waitUntil,
session,
i18n: getLocaleFromRequest(request),
cart: {
queryFragment: CART_QUERY_FRAGMENT,
},
});
return {
...hydrogenContext,
// declare additional Remix loader context
weaverse: new WeaverseClient({
...hydrogenContext,
request,
cache,
themeSchema,
components,
}),
};Weaverse pages is rendered using <WeaverseContent /> component.
import { WeaverseHydrogenRoot } from '@weaverse/hydrogen';
import { GenericError } from '~/components/generic-error';
import { components } from './components';
export function WeaverseContent() {
return (
<WeaverseHydrogenRoot
components={components}
errorComponent={GenericError}
/>
);
}And in your route:
export default function Homepage() {
return <WeaverseContent />;
}Dead simple, right?
Weaverse global theme settings is loaded in the root's loader with context.weaverse.loadThemeSettings function.
export async function loader({request, context}: RouteLoaderArgs) {
return defer({
// App data...
weaverseTheme: await context.weaverse.loadThemeSettings(),
});
}And then you can use it in your components with useThemeSettings hook.
import { useThemeSettings } from '@weaverse/hydrogen';
function Logo() {
let {logo} = useThemeSettings();
return (
<div className="flex items-center">
<img src={logo} alt="Logo" />
</div>
);
}The App component is wrapped with withWeaverse HoC in order to SSR the theme settings.
import { withWeaverse } from '@weaverse/hydrogen';
function App() {
return (
<html lang={locale.language}>
// App markup
</html>
);
}
export default withWeaverse(App);To create a section, you need to create a new file in app/sections directory and register it in app/weaverse/components.ts file.
Important: All Weaverse sections must include ref as a prop (or use forwardRef with React prior to v19) and extend HydrogenComponentProps.
import type { HydrogenComponentProps } from '@weaverse/hydrogen';
interface VideoProps extends HydrogenComponentProps {
ref: React.Ref<HTMLElement>
heading: string;
description: string;
videoUrl: string;
}
export default function Video(props: VideoProps) {
const { ref, heading, description, videoUrl, ...rest } = props;
return (
<section ref={ref} {...rest}>
<div className="mx-auto max-w-7xl px-4 py-8 lg:px-12 lg:py-16 sm:text-center">
<h2 className="mb-4 text-4xl font-extrabold tracking-tight text-gray-900">
{heading}
</h2>
<p className="font-light text-gray-500 sm:text-lg md:px-20 lg:px-38 xl:px-48">
{description}
</p>
<iframe
className="mx-auto mt-8 h-64 w-full max-w-2xl rounded-lg lg:mt-12 sm:h-96"
src={videoUrl}
title="YouTube video player"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
/>
</div>
</section>
);
});Export a schema object from the file to define the component's schema with default data and settings to be used in the Weaverse Studio.
export const schema = createSchema({
type: 'video',
title: 'Video',
settings: [
{
group: 'Video',
inputs: [
{
type: 'text',
name: 'heading',
label: 'Heading',
defaultValue: 'Learn More About Our Products',
placeholder: 'Learn More About Our Products',
},
{
type: 'textarea',
name: 'description',
label: 'Description',
defaultValue: `Watch these short videos to see our products in action. Learn how to use them and what makes them special. See demos of our products being used in real-life situations. The videos provide extra details and showcase the full capabilities of what we offer. If you're interested in learning more before you buy, be sure to check out these informative product videos.`,
placeholder: 'Video description',
},
{
type: 'text',
name: 'videoUrl',
label: 'Video URL',
defaultValue: 'https://www.youtube.com/embed/-akQyQN8rYM',
placeholder: 'https://www.youtube.com/embed/-akQyQN8rYM',
},
],
},
],
});What if your component needs to fetch data from Shopify API or any third-party API?
Weaverse provide a powerful loader function to fetch data from any API, and it's run on the server-side π€―π.
Just export a loader function from your component:
import type { ComponentLoaderArgs } from '@weaverse/hydrogen';
export const loader = async ({ weaverse, data }: ComponentLoaderArgs) => {
const result = await weaverse.storefront.query<SeoCollectionContentQuery>(
HOMEPAGE_SEO_QUERY,
{
variables: { handle: data.collection.handle || 'frontpage' },
},
);
return result.data;
};And then you can use the data in your component with Component.props.loaderData π€
Don't forget to register your new section in app/weaverse/components.ts:
import * as Video from "~/sections/video";
export const components: HydrogenComponent[] = [
// ... existing components
Video,
];Weaverse provides a convenient way to customize your theme inside the Weaverse Studio. You can add new sections, customize existing ones, and change the theme settings.
app/
βββ components/ # Reusable UI components
βββ sections/ # Weaverse sections/components
βββ routes/ # React Router routes (with locale prefix)
βββ graphql/ # GraphQL queries and fragments
βββ utils/ # Helper functions
βββ weaverse/ # Weaverse configuration
Key configuration files:
- biome.json # Code formatting and linting
- codegen.ts # GraphQL code generation
- react-router.config.ts # React Router configuration
- vite.config.ts # Vite bundler configuration
- Development server: http://localhost:3456
- GraphiQL API browser: http://localhost:3456/graphiql
- Network inspector: http://localhost:3456/debug-network
- Weaverse Studio: Access through your Shopify admin
This project is provided under the MIT License.
Let Weaverse & Maison empower your Shopify store with top-notch performance and unmatched customization possibilities! π