### Environment Configuration for Builder.io and Ecommerce in Bash Source: https://context7.com/builderio/unified-demo/llms.txt This script sets up environment variables for Vercel deployment, Builder.io API integration, and ecommerce platforms like Shopify, Swell, Commercetools, and Emporix. It requires replacing placeholder values with actual credentials. Inputs are custom keys and tokens; outputs are configured .env file for use in Next.js applications. Limitations include manual replacement of sensitive data and no validation in the example file. ```Bash # .env.example VERCEL="1" VERCEL_ENV="development" VERCEL_URL="http://localhost:3000" # Builder.io API Key NEXT_PUBLIC_BUILDER_API_KEY=your_builder_api_key # Shopify Configuration NEXT_PUBLIC_SHOPIFY_DOMAIN=your-store.myshopify.com NEXT_PUBLIC_SHOPIFY_STOREFRONT_TOKEN=your_storefront_access_token # Swell Configuration NEXT_PUBLIC_SWELL_STORE_ID=your_swell_store_id NEXT_PUBLIC_SWELL_PUBLIC_KEY=your_swell_public_key # Commercetools Configuration NEXT_PUBLIC_COMMERCETOOLS_PROJECT_KEY=your_project_key NEXT_PUBLIC_COMMERCETOOLS_CLIENT_ID=your_client_id NEXT_PUBLIC_COMMERCETOOLS_CLIENT_SECRET=your_client_secret # Emporix Configuration NEXT_PUBLIC_EMPORIX_TENANT=your_tenant NEXT_PUBLIC_EMPORIX_CLIENT_ID=your_client_id NEXT_PUBLIC_EMPORIX_API_URL=https://api.emporix.io ``` -------------------------------- ### Fetch Swell products with swell-js (TypeScript) Source: https://context7.com/builderio/unified-demo/llms.txt Demonstrates Swell.js integration with functions to list products, get products by ID/slug, and generate static paths. Requires swell-js package and environment variables for store configuration. Includes type-safe Product interface. ```typescript import swell from "swell-js"; swell.init( process.env.NEXT_PUBLIC_SWELL_STORE_ID as string, process.env.NEXT_PUBLIC_SWELL_PUBLIC_KEY as string ); interface Product { id?: string; name?: string; slug?: string; price?: number; images?: any[]; } // Get all products with optional limit export async function getAllProducts(limit?: number): Promise { const response = await swell.products.list({ limit }); return response.results.filter((product: Product) => product.id); } // Get all product slugs for static path generation export async function getAllProductPaths(limit?: number): Promise { const response = await swell.products.list({ limit }); return response.results .map((product) => product.slug) .filter((slug): slug is string => slug !== undefined); } // Get product by ID or slug export async function getProduct(options: { id?: string; handle?: string; }): Promise { const product = options.handle ? await swell.products.get(options.handle) : options.id ? await swell.products.get(options.id) : null; if (!product) throw new Error("A product ID or handle is required"); return product; } // Usage example const products = await getAllProducts(50); const product = await getProduct({ handle: 'vintage-sneakers' }); const paths = await getAllProductPaths(); ``` -------------------------------- ### Fetch Shopify products with Shopify Buy SDK (TypeScript) Source: https://context7.com/builderio/unified-demo/llms.txt Provides functions to fetch Shopify products by ID/handle, search products, get collections, and generate static paths. Requires shopify-buy package. Handles both ID and handle-based lookups with error checking. ```typescript import { buildClient } from 'shopify-buy'; const fastClone = (obj: any) => JSON.parse(JSON.stringify(obj)); // Get all products with optional limit export function getAllProducts(config: ShopifyBuy.Config, limit?: number) { const client = buildClient(config); return client.product.fetchAll(limit); } // Get product by handle or ID export async function getProduct( config: ShopifyBuy.Config, options: { id?: string; handle?: string } ) { const client = buildClient(config); if (options.handle) { return fastClone(await client.product.fetchByHandle(options.handle)); } if (!options.id) { throw new Error('A product ID or handle is required'); } return fastClone(await client.product.fetch(options.id)); } // Search products export async function searchProducts( config: ShopifyBuy.Config, searchString: string ) { const client = buildClient(config); return client.product.fetchQuery({ query: searchString ? `title:*${searchString}*` : '', }); } // Get collection by handle or ID export async function getCollection( config: ShopifyBuy.Config, options: { id?: string; handle?: string } ) { const client = buildClient(config); if (options.handle) { return fastClone(await client.collection.fetchByHandle(options.handle)); } if (!options.id) { throw new Error('A collection ID or handle is required'); } return fastClone(await client.collection.fetch(options.id)); } // Get all product handles for static path generation export async function getAllProductPaths( config: ShopifyBuy.Config, limit?: number ): Promise { const client = buildClient(config); const products: any[] = await client.product.fetchAll(limit); return products.map((val) => val.handle); } // Usage example const shopifyConfig = { domain: 'your-store.myshopify.com', storefrontAccessToken: 'your-token-here' }; const products = await getAllProducts(shopifyConfig, 20); const product = await getProduct(shopifyConfig, { handle: 'blue-jeans' }); const searchResults = await searchProducts(shopifyConfig, 'denim'); ``` -------------------------------- ### Initialize Builder.io SDK and render content in Next.js Source: https://context7.com/builderio/unified-demo/llms.txt Initializes the Builder.io SDK with an API key and renders content using the BuilderComponent. Includes handling for dynamic page titles, descriptions, and fallback error pages. Uses Next.js Pages Router for static site generation. ```typescript import React from 'react'; import { builder, BuilderComponent, Builder } from '@builder.io/react'; import Head from 'next/head'; import { GetStaticPaths, GetStaticProps } from 'next'; import Error from './_error'; builder.init('YJIGb4i01jvw0SRdL5Bt'); function LandingPage({ builderPage }: any) { const title = `${ (builderPage && (builderPage.data.pageTitle || builderPage.data.title)) || 'Default Title' } | Builder.io`; return (
{!builderPage && } {title} {builderPage || Builder.isEditing || Builder.isPreviewing ? ( ) : ( )}
); } export const getStaticPaths: GetStaticPaths = async () => { const pages = await builder.getAll('content-page', { fields: 'data.url', options: { noTargeting: true }, }); return { paths: pages.map((page) => `${page.data?.url}`), fallback: 'blocking', }; }; export const getStaticProps: GetStaticProps = async (context) => { const page = await builder .get('content-page', { userAttributes: { urlPath: '/' + ((context.params?.page as string[])?.join('/') || ''), }, }) .toPromise(); return { props: { builderPage: page || null, }, revalidate: 60, }; }; export default LandingPage; ``` -------------------------------- ### Dynamic Product Page with Next.js App Router and Builder.io in TypeScript Source: https://context7.com/builderio/unified-demo/llms.txt This server action component fetches product data and details from Builder.io models using Next.js App Router, then renders them with custom components. It depends on '@builder.io/sdk' and environment variables for API keys. Inputs include URL params for product handle; outputs are rendered JSX with product details and Builder content. Limitations include reliance on static params generation for SSG and potential errors if Builder.io queries fail. ```TypeScript "use server" import ProductDetails from "@/src/components/PDP/ProductDetails"; import { builder } from "@builder.io/sdk"; import { RenderBuilderContent } from "@/src/components/builder"; builder.init(process.env.NEXT_PUBLIC_BUILDER_API_KEY!); interface ProductPageProps { params: { handle: string; }; } export default async function ProductPage(props: ProductPageProps) { const builderProductDataModel = "product-data"; const builderProductDetailsModel = "product-details-bottom"; // Fetch product data from Builder.io const productData = await builder .get(builderProductDataModel, { query: { data: { handle: props?.params?.handle } } }) .toPromise(); // Fetch additional product details content const productDetailsContent = await builder .get(builderProductDetailsModel, { userAttributes: { product: props?.params?.handle, category: productData?.data?.category, options: { enrich: true } }, }) .toPromise(); return ( <> {productDetailsContent ? : null} ); } // Generate static params for all products export async function generateStaticParams() { const products = await builder.getAll("product-data", { fields: "data.handle", options: { noTargeting: true }, }); return products.map((product) => ({ handle: product.data?.handle, })); } ``` -------------------------------- ### Initialize Builder.io SDK with API Key and Design Tokens in TypeScript Source: https://context7.com/builderio/unified-demo/llms.txt This code initializes the Builder.io React SDK with an API key for content fetching and registers editor settings including custom design tokens for colors, spacing, and font sizes. It depends on the @builder.io/react package and requires a valid NEXT_PUBLIC_BUILDER_API_KEY environment variable. The purpose is to configure the SDK for use in a Next.js application, enabling visual editing without strict mode enforcement. Limitations include reliance on CSS variables for token values and potential need for additional token updates. ```typescript import { builder, Builder } from "@builder.io/react"; // Initialize with API key builder.init(process.env.NEXT_PUBLIC_BUILDER_API_KEY!); // Configure editor settings with design tokens Builder.register("editor.settings", { styleStrictMode: false, allowOverridingTokens: true, designTokens: { colors: [ { name: "Primary", value: "var(--color-primary, #000000)" }, { name: "Secondary", value: "var(--color-secondary, #ffffff)" }, { name: "Accent", value: "var(--color-accent, #F35959)" } ], spacing: [ { name: "Large", value: "var(--space-large, 20px)" }, { name: "Small", value: "var(--space-small, 10px)" } ], fontSize: [ { name: "Small", value: "var(--font-size-small, 12px)" }, { name: "Medium", value: "var(--font-size-medium, 24px)" }, { name: "Large", value: "var(--font-size-large, 36px)" } ] } }); ``` -------------------------------- ### Utility Functions for Styling and Configuration in TypeScript Source: https://context7.com/builderio/unified-demo/llms.txt These functions provide utilities for merging Tailwind CSS classes with conflict resolution, converting RGBA strings to hex format, capitalizing words, and selecting Builder.io API keys based on hostname. They depend on 'clsx' and 'tailwind-merge' libraries for class handling. Inputs include class values, RGBA strings, words, and host objects; outputs are merged classes, hex colors, capitalized strings, and API keys. Limitations include regex-based parsing for colors which may not handle all edge cases. ```TypeScript import { type ClassValue, clsx } from "clsx"; import { twMerge } from "tailwind-merge"; // Merge Tailwind classes with conflict resolution export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } // Convert RGBA color string to hex format export function rgbaToHex(rgbaString: string) { const rgbaRegex = /^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*([01]?\.?\d*)\s*)?\)$/; const match = rgbaString.match(rgbaRegex); if (match) { const r = parseInt(match[1], 10); const g = parseInt(match[2], 10); const b = parseInt(match[3], 10); const a = match[4] !== undefined ? parseFloat(match[4]) : 1; const rHex = r.toString(16).padStart(2, '0'); const gHex = g.toString(16).padStart(2, '0'); const bHex = b.toString(16).padStart(2, '0'); const aHex = Math.round(a * 255).toString(16).padStart(2, '0'); const hex = `#${rHex}${gHex}${bHex}${aHex !== 'ff' ? aHex : ''}`; return hex; } throw new Error("Invalid RGBA string"); } // Capitalize first letter of string export function capitalizeWord(word: string) { return word.charAt(0).toUpperCase() + word.slice(1); } // Get Builder.io API key based on hostname export function getBuilderApiKey(hostlist: any) { const host = typeof hostlist === "string" ? 'localhost' : hostlist.get('host'); const hostPrefix = host.split(/[-:]/)[0]; switch (hostPrefix) { case 'tim': return '50b344f9116e4820a020e382058146e0'; case 'localhost': return 'a87584e551b6472fa0f0a2eb10f2c0ff'; default: return 'a87584e551b6472fa0f0a2eb10f2c0ff'; } } // Usage examples const classes = cn("px-4 py-2", "bg-blue-500", "hover:bg-blue-600"); const hexColor = rgbaToHex("rgba(255, 99, 71, 0.8)"); // #ff63478c const title = capitalizeWord("product"); // "Product" const apiKey = getBuilderApiKey({ get: (key: string) => 'localhost:3000' }); ``` -------------------------------- ### Register Product Card with Multi-Platform Support Source: https://context7.com/builderio/unified-demo/llms.txt Demonstrates building a unified product card component that supports multiple ecommerce platforms (Shopify, Commercetools, Builder, Swell, Emporix) with dynamic input fields and conditional visibility based on selected data source. ```typescript import { Builder } from "@builder.io/react"; import ProductCard from "./components/Card/ProductCard"; Builder.registerComponent(ProductCard, { name: "ProductCard", image: "https://cdn.builder.io/api/v1/image/assets%2F.../product-card.png", inputs: [ { name: "dataSource", type: "text", enum: ["Shopify", "Commercetools", "Builder", "Swell", "Emporix"], defaultValue: "Builder", }, { name: "product", type: "reference", model: "product-data", required: true, showIf: function (options: any) { return options.get("dataSource") === "Builder"; }, }, { name: "shopifyProductHandle", friendlyName: "Shopify Product", type: "ShopifyProductHandle", required: true, showIf: function (options: any) { return options.get("dataSource") === "Shopify"; }, }, { name: "swellProductHandle", friendlyName: "Swell Product", type: "SwellProductHandle", required: true, showIf: function (options: any) { return options.get("dataSource") === "Swell"; }, }, { name: "commercetoolsProduct", friendlyName: "Commercetools Product", type: "CommercetoolsProduct", required: true, showIf: function (options: any) { return options.get("dataSource") === "Commercetools"; }, }, ], }); ``` -------------------------------- ### Fetch Content from Builder.io Models Using TypeScript Source: https://context7.com/builderio/unified-demo/llms.txt This snippet provides functions to retrieve content from Builder.io models, supporting user attributes for targeting and query parameters for specific data like product handles. It relies on the @builder.io/sdk package and initialization with an API key. Inputs include model names, user attributes (e.g., loggedIn, product), and queries; outputs are promise-resolved content objects. Limitations: Asynchronous nature requires await handling, and targeting depends on correctly set user attributes. ```typescript import { builder } from "@builder.io/sdk"; builder.init(process.env.NEXT_PUBLIC_BUILDER_API_KEY!); // Fetch homepage content async function getHomepageContent() { const content = await builder .get("homepage", { userAttributes: { loggedIn: true, }, }) .toPromise(); return content; } // Fetch product-specific content with query async function getProductData(handle: string) { const productData = await builder .get("product-data", { query: { data: { handle: handle } } }) .toPromise(); return productData; } // Fetch targeted content with user attributes async function getProductDetailsContent(handle: string, category: string) { const content = await builder .get("product-details-bottom", { userAttributes: { product: handle, category: category, options: { enrich: true } }, }) .toPromise(); return content; } ``` -------------------------------- ### Create Custom Insert Menus in Builder.io Editor Source: https://context7.com/builderio/unified-demo/llms.txt Shows how to organize registered components into custom categories within Builder.io's visual editor insert menu. Includes conditional menu registration based on the current editing model, enabling different component sets for different page types. ```typescript import { Builder } from "@builder.io/react"; // Register hero components menu Builder.register("insertMenu", { name: "Heros", items: [ { name: "TextHero" }, { name: "ImageHero" }, { name: "SplitHero" }, { name: "HeroWithChildren" }, ], }); // Register card components menu Builder.register("insertMenu", { name: "Cards", items: [ { name: "IconCard" }, { name: "ProductCard" } ], }); // Conditionally register menus based on model being edited if (Builder.isBrowser) { if (builder.editingModel === "homepage") { Builder.register("insertMenu", { name: "Layout", items: [ { name: "Columns" }, { name: "Builder:Carousel" }, { name: "Collection" }, { name: "Accordion" } ], }); } } ``` -------------------------------- ### Register Custom React Components with Builder.io Source: https://context7.com/builderio/unified-demo/llms.txt Demonstrates how to register React components with Builder.io's visual editor, including configurable inputs with types, default values, validation rules, and conditional display logic. Supports complex component registration patterns like children support and component overriding. ```typescript import { Builder, withChildren } from "@builder.io/react"; import SplitHero from "./components/Hero/SplitHero"; import Counter from "./components/Counter/Counter"; import { Button } from "./components/ui/button"; // Register component with inputs Builder.registerComponent(SplitHero, { name: "SplitHero", image: "https://cdn.builder.io/api/v1/image/assets%2F.../hero-preview.png", inputs: [ { name: "imageAlignment", type: "string", defaultValue: "right", enum: ["left", "right"], required: true, }, { name: "textAlignment", type: "string", defaultValue: "left", enum: ["left", "center", "right"], required: true, }, { name: "title", type: "longText", defaultValue: "OUR COMMITMENT TO SUSTAINABILITY", required: true, }, { name: "subTitle", type: "richText", defaultValue: "

Create impactful, bold silhouettes

", }, { name: "hasCTA", type: "boolean", defaultValue: false, }, { name: "buttonLink", type: "url", showIf: (options) => options.get("hasCTA") == true, defaultValue: "/", } ], }); // Register component with number input Builder.registerComponent(Counter, { name: "Counter", image: "https://cdn.builder.io/api/v1/image/assets%2F.../counter.png", inputs: [ { name: "initialCount", type: "number", }, ], }); // Register component with children support Builder.registerComponent(withChildren(Button), { name: "Core:Button", override: true, canHaveChildren: true, defaultChildren: [ { "@type": "@builder.io/sdk:Element", component: { name: "Text", options: { text: "

Click Me

" } }, }, ], childRequirements: { message: "You can only put Text or Image Icons inside a Button", query: { "component.name": { $in: ["Text"] }, }, }, inputs: [ { name: "variant", type: "string", defaultValue: "default", enum: ["default", "secondary", "tertiary", "outline", "link"], }, ], }); ``` -------------------------------- ### Search Products in Emporix API in TypeScript Source: https://context7.com/builderio/unified-demo/llms.txt Function to search for products using a query string via the Emporix API with authentication. Inputs include a config object with tenant, clientId, apiUrl, and an optional searchQuery. Outputs product search results or throws an error; handles 401 by clearing cache; no specific limitations beyond API constraints. ```typescript export async function searchProducts( config: { tenant: string; clientId: string; apiUrl: string }, searchQuery?: string ) { const tokenHelper = new AnonymousTokenHelper(config.tenant, config.clientId); try { const token = await tokenHelper.getAnonymousToken(); let url = `${config.apiUrl}/product/${config.tenant}/products`; if (searchQuery) { url += `?q=name:~${encodeURIComponent(searchQuery)}`; } const response = await fetch(url, { headers: { 'Authorization': `Bearer ${token}`, 'X-Version': 'v2', 'Content-Type': 'application/json', }, }); if (!response.ok) { if (response.status === 401) { tokenHelper.clearCache(); } throw new Error(`Failed to search Emporix products: ${response.statusText}`); } return response.json(); } catch (error) { console.error('Error searching Emporix products:', error); throw error; } } ``` -------------------------------- ### Render Builder.io Content in Next.js Pages with TypeScript Source: https://context7.com/builderio/unified-demo/llms.txt This code defines a RenderBuilderContent component for displaying Builder.io content in Next.js using the App Router, with preview mode support and fallback to a 404 error page if no content is available. It depends on @builder.io/react and Next.js error components. Inputs are content props, model name, and options like enrich; outputs rendered React components or error page. Limitations: Client-side only for the component, requires server-side content fetching in pages, and preview relies on useIsPreviewing hook. ```typescript "use client" import { ComponentProps } from "react"; import { BuilderComponent, useIsPreviewing } from "@builder.io/react"; import DefaultErrorPage from "next/error"; type BuilderPageProps = ComponentProps; export function RenderBuilderContent(props: BuilderPageProps) { const isPreviewing = useIsPreviewing(); if (props.content || isPreviewing) { return ( <> ); } return ; } // Usage in a Next.js App Router page import { builder } from "@builder.io/sdk"; import { RenderBuilderContent } from "@/src/components/builder"; builder.init(process.env.NEXT_PUBLIC_BUILDER_API_KEY!); export default async function Homepage() { const content = await builder .get("homepage", { userAttributes: { loggedIn: true }, }) .toPromise(); return ( ); } ``` -------------------------------- ### Fetch Product by ID from Emporix API in TypeScript Source: https://context7.com/builderio/unified-demo/llms.txt Function to retrieve a product by its ID using authenticated requests to the Emporix API. It takes a config object with tenant, clientId, and apiUrl, and the productId as input. On success, it returns product data; on 401 errors, it clears the token cache; limitations include fallback error response if fetch fails. ```typescript export async function getProduct( config: { tenant: string; clientId: string; apiUrl: string }, productId: string ) { const tokenHelper = new AnonymousTokenHelper(config.tenant, config.clientId); try { const token = await tokenHelper.getAnonymousToken(); const response = await fetch( `${config.apiUrl}/product/${config.tenant}/products/${productId}`, { headers: { 'Authorization': `Bearer ${token}`, 'X-Version': 'v2', 'Content-Type': 'application/json', }, } ); if (!response.ok) { if (response.status === 401) { tokenHelper.clearCache(); } throw new Error(`Failed to fetch Emporix product: ${response.statusText}`); } return response.json(); } catch (error) { console.error('[Emporix API] Error fetching product:', error); return { id: productId, code: productId, name: `Product ${productId}`, error: true, media: [], mixins: {} }; } } ``` -------------------------------- ### Implement Anonymous Token Helper in TypeScript Source: https://context7.com/builderio/unified-demo/llms.txt A class that manages OAuth token caching for anonymous authentication with the Emporix API. It stores tokens in memory to reduce API calls and automatically refreshes them upon expiration. This helper depends on the fetch API for making HTTP requests and requires tenant and clientId configuration. ```typescript class AnonymousTokenHelper { private tenant: string; private clientId: string; private cache: any; constructor(tenant: string, clientId: string) { this.tenant = tenant; this.clientId = clientId; this.cache = {}; } async getAnonymousToken() { if (!this.cache['access_token']) { await this.authenticate(); } if (this.cache['expires_at'] < Date.now()) { await this.authenticate(); } return this.cache['access_token']; } clearCache() { this.cache = {}; } async authenticate() { const response = await fetch( `https://api.emporix.io/customerlogin/auth/anonymous/login?client_id=${this.clientId}&tenant=${this.tenant}` ); const data = await response.json(); data['expires_at'] = Date.now() + 1000 * data['expires_in']; this.cache = data; } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.