Integrate Visual Editing of Your Homepage
A direct option for giving non-developer teammates access to editing your homepage is to integrate landing pages and use the same code for your homepage. In this way, choosing / as a page's URL shows it on the homepage.
Alternatively, you can make a dedicated section model for your homepage. This is preferable if you make many variations of your homepage.
Model definition
A standard section model named homepage is all you need.
By default, you don't need any fields but may choose to add targeting to show different visitors different versions of your homepage.
Example code
// pages/collections/[collection].jsx
import { BuilderComponent, builder } from '@builder.io/react';
// Replace with your Public API Key.
builder.init(YOUR_API_KEY);
export async function getStaticProps({ params }) {
const homepage = await builder.get('homepage').toPromise();
return {
props: {
homepage: homepage || null,
},
};
}
export default function Page({ homepage }) {
return (
<>
{/* Put your header here. */}
<YourHeader />
<BuilderComponent model="homepage" content={homepage} />
{/* Put your footer here. */}
<YourFooter />
</>
);
}builder.get('your-model', {
query: {
'data.myCustomProperty.$eq': 'sale'
}
})import React from "react";
import { builder } from "@builder.io/sdk";
import Head from "next/head";
import { RenderBuilderContent } from "@/components/builder";
// Replace with your Public API Key
builder.init(YOUR_API_KEY);
interface PageProps {
params: {
page: string[];
};
}
export default async function Page(props: PageProps) {
const homepageContent = await builder
.get('homepage', {
prerender: false,
})
.toPromise();
return (
<>
<Head>
<title>{content?.data.title}</title>
</Head>
{/* Render the Builder page */}
<RenderBuilderContent
model="homepage"
content={homepageContent} />
</>
);
}
Notice that RenderBuilderContent is a component you'd make, for example:
"use client";
import { BuilderComponent, useIsPreviewing } from "@builder.io/react";
import DefaultErrorPage from "next/error";
interface BuilderPageProps {
content: any;
}
export function RenderBuilderContent({ content }: BuilderPageProps) {
const isPreviewing = useIsPreviewing();
if (content || isPreviewing) {
return <BuilderComponent content={content} model="homepage" />;
}
return null;
}builder.get('your-model', {
query: {
'data.myCustomProperty.$eq': 'sale'
}
})Install the SDK:
npm install @builder.io/reactNext, create a new React component that fetches the Builder.io content and renders it using the BuilderComponent.
Place this code in any file you want to represent the homepage of your React app. Typically, you might put this code in a file named HomePage.js or HomePage.jsx.
import React, { useEffect, useState } from "react";
import { BuilderComponent, builder } from "@builder.io/react";
// Replace with your Public API Key.
builder.init(YOUR_API_KEY);
export default function Page() {
const [homepage, setHomepage] = useState(null);
useEffect(() => {
builder
.get("homepage")
.toPromise()
.then((homepageData) => setHomepage(homepageData));
}, []);
return (
<>
{/* Put your header here. */}
<YourHeader />
{homepage && <BuilderComponent model="homepage" content={homepage} />}
{/* Put your footer here. */}
<YourFooter />
</>
);
}Make sure to replace YOUR_PUBLIC_API_KEY with your own Builder.io Public API key.
builder.get('your-model', {
query: {
'data.myCustomProperty.$eq': 'sale'
}
})Install the SDK:
npm install @builder.io/sdk-reactPlace the following code in a file inside the src directory with a filename that matches the route that you want to render the Builder content on.
For example, if you wanted to render Builder content on the /collections/:collection route, you would create a file at src/collections/[collection].tsx and place the code in that file.
// $.tsx
import {
fetchOneEntry,
isEditing,
isPreviewing,
Content,
getBuilderSearchParams
} from "@builder.io/sdk-react";
import type { LoaderFunction } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
export const loader: LoaderFunction = async ({ params, request }) => {
const url = new URL(request.url);
const apiKey = "YOUR_API_KEY"; // Replace with your actual API key
const content = await fetchOneEntry({
model: "announcement-bar",
apiKey: apiKey,
options: getBuilderSearchParams(new URL(request.url).searchParams),
userAttributes: {
urlPath: `/${params["*"]}`,
// add other targeting options
},
});
const isEditingOrPreviewing = isEditing() || isPreviewing();
if (!content && !isEditingOrPreviewing) {
// if section doesn't exist, return an empty object
return { content: null };
}
return { content };
};
// Define a page.
export default function Page() {
// Use the useLoaderData hook to get the announcement-bar data from `loader` above.
const { content } = useLoaderData<typeof loader>();
// Render the announcement-bar content from Builder.io
return (
<Content
model="homepage"
apiKey="YOUR_API_KEY"
content={content}
/>
);
}Make sure to replace YOUR_PUBLIC_API_KEY with your own Builder.io Public API key.
builder.get('your-model', {
query: {
'data.myCustomProperty.$eq': 'sale'
}
})This example uses SvelteKit.
Install the SDK:
npm install @builder.io/sdk-svelteDefine a load() function in Home.js. Home.js is where the Builder content is fetched and returned as props.
// src/routes/home.js
import { fetchOneEntry, getBuilderSearchParams } from '@builder.io/sdk-svelte';
// Add your public API key
const BUILDER_PUBLIC_API_KEY = YOUR_API_KEY;
export async function load() {
const homepage = await fetchOneEntry({
model: 'homepage',
apiKey: BUILDER_PUBLIC_API_KEY,
options: getBuilderSearchParams(event.url.searchParams)
});
return { homepage };
}In home.svelte, render the Builder content using the Content component.
<!-- src/routes/home.svelte -->
<script>
import { isPreviewing, Content } from "@builder.io/sdk-svelte";
const apiKey = //ADD YOUR PUBLIC API KEY
const model = "homepage"
export let data;
const canShowContent = data?.homepage || isPreviewing();
</script>
<main>
<div>Your Builder Homepage:</div>
{#if canShowContent}
<!-- Render builder content with all required props -->
<Content
model = {model}
content = {data?.homepage}
apiKey = {apiKey}
/>
{:else}
<p>Loading...</p>
{/if}
</main>Make sure to replace YOUR_PUBLIC_API_KEY with your own Builder.io Public API key.
builder.get('your-model', {
query: {
'data.myCustomProperty.$eq': 'sale'
}
})Install the SDK:
npm install @builder.io/sdk-vueFetch the content with the onMounted lifecycle hook and render it using the Content component from Builder.io's Vue SDK; for example:
// pages/your-page.vue
<template>
<div>
<div>Below is Builder Content:</div>
<div v-if="canShowContent">
<Content
model="homepage"
:content="content"
:api-key="apiKey"
/>
</div>
</div>
</template>
<script>
import { fetchOneEntry, Content, isPreviewing, getBuilderSearchParams } from '@builder.io/sdk-vue';
// define vue component
export default {
data: () => ({
// boolean to control showing content
canShowContent: false,
// content variable to store content from Builder
content: null,
// use your API key
apiKey: YOUR_PUBLIC_API_KEY,
}),
// mounted() lifecycle hook called after component is in the DOM
mounted() {
// get page model from space (specified by the Public API Key)
// and the URL
fetchOneEntry({
model: 'homepage',
apiKey: this.apiKey,
options: getBuilderSearchParams(new URL(location.href).searchParams),
userAttributes: {
urlPath: window.location.pathname,
},
}).then(res => {
// sets content to results of `fetchOneEntry()`
this.content = res;
// If there's content or if the page is being
// viewed in the Visual Editor,
// set canShowContent to true.
this.canShowContent = this.content || isPreviewing();
});
},
}
</script>Make sure to replace YOUR_API_KEY with your own Builder.io Public API key.
Install the SDK:
npm install @builder.io/sdk-vueNext, use asyncData() method to fetch the homepage content from Builder.io before initializing the component. This way, the fetched content will be available when the component is rendered.
The Content component then renders the Builder.io content for the homepage model when the homepage data is available.
// pages/your-page.vue
<template>
<div>
<!-- Put your header here. -->
<YourHeader />
<Content
:key="$route.path"
model="homepage"
@contentLoaded="contentLoaded"
@contentError="contentError"
:options="{
url: $route.path,
}"
/>
<!-- Put the rest of your page here. -->
<TheRestOfYourPage />
</div>
</template>
<script>
import Vue from 'vue';
import { Content } from '@builder.io/sdk-vue';
export default Vue.extend({
components: {
Content,
YourHeader,
TheRestOfYourPage,
},
})
</script>Add the following to nuxt.config.js:
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
module: ['@builder.io/sdk-vue/nuxt'],
});If you are using an SSR framework other than Nuxt, you must import the CSS by adding the following to your entry point, before rendering Builder content:
<script>
import '@builder.io/sdk-vue/css';
</script>Make sure to replace YOUR_API_KEY with your own Builder.io Public API key.
Install the SDK:
npm install @builder.io/sdk-qwikCreate a new Qwik component that fetches and renders the Builder.io content using the Builder.io SDK for Qwik:
// src/components/builder-page.tsx
import { component$ } from '@builder.io/qwik';
import { routeLoader$ } from '@builder.io/qwik/router';
import {
fetchOneEntry,
Content,
getBuilderSearchParams,
} from '@builder.io/sdk-qwik';
export const BUILDER_PUBLIC_API_KEY = 'YOUR_PUBLIC_API_KEY'; // <-- Add your Public API KEY here
export const BUILDER_MODEL = 'page';
// Use Qwik routeLoader$ to get your content from Builder.
// routeLoader$() takes an async function to fetch content
// from Builder with fetchOneEntry().
export const useBuilderContent = routeLoader$(async ({ url, error }) => {
const builderContent = await fetchOneEntry({
model: BUILDER_MODEL,
apiKey: BUILDER_PUBLIC_API_KEY,
options: getBuilderSearchParams(url.searchParams),
userAttributes: {
urlPath: url.pathname,
},
});
// If there's no content, throw a 404.
// You can use your own 404 component here
if (!builderContent) {
throw error(404, 'File Not Found');
}
// return content fetched from Builder
return builderContent;
});
export default component$(() => {
// call useBuilderContent() and set content equal to
// returned builderContent
const content = useBuilderContent();
// Content uses `content` to
// render the content of the given model, here a page,
// of your space (specified by the API Key)
return (
<Content
model={BUILDER_MODEL}
content={content.value}
apiKey={BUILDER_PUBLIC_API_KEY}
/>
);
});Make sure to replace YOUR_PUBLIC_API_KEY with your own Builder.io Public API key.
Import the BuilderPage component and use it in your main Qwik component; for example index.tsx:
// src/index.tsx
import { h } from '@builder.io/qwik';
import BuilderPage from './components/builder-page';
export default function App() {
return (
<>
{/* Put your header here. */}
<YourHeader />
<BuilderPage />
{/* Put your footer here. */}
<YourFooter />
</>
);
}// homepage.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { fetchOneEntry, type BuilderContent } from '@builder.io/sdk-angular';
import { Content } from '@builder.io/sdk-angular';
@Component({
selector: 'app-homepage',
standalone: true,
imports: [Content, CommonModule],
templateUrl: './homepage.component.html',
styleUrl: './homepage.component.css'
})
export class LandingPageComponent {
// Add your Public API Key, specify the page model, and initialize the content variable
apiKey = /* ADD YOUR PUBLIC API KEY HERE */;
model = 'homepage';
content: BuilderContent | null = null;
async ngOnInit() {
const urlPath = window.location.pathname || '';
// fetch the content for the current model based on the current URL
const content = await fetchOneEntry({
apiKey: this.apiKey,
model: this.model,
userAttributes: {
urlPath,
},
});
if (!content) {
return;
}
this.content = content;
}
}Fetch the data with a resolver:
// homepage.resolver.ts
import type { ActivatedRouteSnapshot, ResolveFn } from '@angular/router';
import { fetchOneEntry, getBuilderSearchParams } from '@builder.io/sdk-angular';
export const homepageResolver: ResolveFn<any> = (
route: ActivatedRouteSnapshot
) => {
const urlPath = `/${route.url.join('/')}`;
const searchParams = getBuilderSearchParams(route.queryParams);
return fetchOneEntry({
apiKey: /* PUT YOUR PUBLIC API KEY HERE */,
model: 'homepage',
userAttributes: {
urlPath,
},
options: searchParams,
});
};In homepage.component.ts, subscribe to the route's resolved data from the resolver, in order to render it in the template.
// src/app/homepage/homepage.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ActivatedRoute } from '@angular/router';
import { Content, type BuilderContent } from '@builder.io/sdk-angular';
@Component({
selector: 'app-homepage',
standalone: true,
templateUrl: './homepage.component.html',
})
export class CollectionHeroComponent {
apiKey = '/* PUT YOUR PUBLIC API KEY HERE */';
model = 'homepage';
content: BuilderContent | null = null;
constructor(private activatedRoute: ActivatedRoute) {}
ngOnInit() {
this.activatedRoute.data.subscribe((data: any) => {
this.content = data.content;
});
}
}Install the SDK:
npm install @builder.io/gatsby @builder.io/reactFetch the homepage content from Builder.io using Gatsby's createPages API in gatsby-node.js.
Then pass the fetched content as a prop to the HomePage component through the pageContext object. The BuilderComponent renders the Builder.io content for the homepage model.
First, create a new file src/templates/homepage.js with the following content:
// src/templates/homepage.js
import React from "react";
import { BuilderComponent } from "@builder.io/react";
const HomePage = ({ pageContext }) => {
const { homepage } = pageContext;
return (
<>
{/* Put your header here. */}
<YourHeader />
<BuilderComponent model="homepage" content={homepage} />
{/* Put the rest of your page here. */}
<TheRestOfYourPage />
</>
);
};
export default HomePage;Then, modify your gatsby-node.js file to fetch the homepage content from Builder.io and create a page using the homepage.js template:
// gatsby-node.js
const fetch = require("node-fetch");
const path = require("path");
exports.createPages = async ({ actions }) => {
const { createPage } = actions;
// Replace with your Public API Key.
const YOUR_API_KEY = "YOUR_PUBLIC_API_KEY";
// Fetch the homepage content from Builder.io.
const response = await fetch(
`https://cdn.builder.io/api/v2/content/homepage?apiKey=${YOUR_API_KEY}`
);
const homepage = await response.json();
// Create the page using the fetched content.
createPage({
path: "/", // Change this to the desired path.
component: path.resolve("src/templates/homepage.js"),
context: {
homepage,
},
});
};Make sure to replace YOUR_API_KEY with your own Builder.io Public API key.
builder.get('your-model', {
query: {
'data.myCustomProperty.$eq': 'sale'
}
})Import Builder and fetch the homepage, making sure to replace YOUR_PUBLIC_API_KEY with your Builder Public API Key.
// Import necessary libraries
import SwiftUI
import BuilderIO
struct ContentView: View {
@ObservedObject var content: BuilderContentWrapper = BuilderContentWrapper()
init() {
self.getContent()
}
// Define getContent as a method to fetch content from Builder.io
func getContent() {
Content.getContent(model: "homepage",
apiKey: YOUR_PUBLIC_API_KEY, // Replace with your Public API key
url: "", // No URL is needed for sections
locale: "",
preview: "") { content in
// The completion block to be executed once getContent is completed
// Ideally in the main thread because it likely updates UI components
DispatchQueue.main.async {
// Calls changeContent on self.content with the new content
self.content.changeContent(content)
}
}
}
var body: some View {
VStack {
if let contentValue = content.content {
// Use the content to render your section view
// TO DO: Replace with code to render your section
RenderContent(content: contentValue, apiKey: YOUR_PUBLIC_API_KEY)
} else {
// Display a loading message if the content is not yet available
Text("Loading...")
}
// Handle live previewing
if Content.isPreviewing() {
// Display a 'Reload' button during content previews for manual refresh
Button("Reload") {
self.getContent()
}
}
}
}
}
Install the SDK:
npm install @builder.io/angularCreate a new component; for example., homepage.component.ts:
// src/app/homepage/homepage.component.ts
import { Component, OnInit } from '@angular/core';
import { Builder, BuilderContent } from '@builder.io/angular';
// Replace with your Public API Key.
const YOUR_API_KEY = 'YOUR_PUBLIC_API_KEY';
@Component({
selector: 'app-homepage',
templateUrl: './homepage.component.html',
styleUrls: ['./homepage.component.css'],
})
export class HomepageComponent implements OnInit {
homepage: BuilderContent | null = null;
constructor(private builder: Builder) {
builder.setApiKey(YOUR_API_KEY);
}
ngOnInit(): void {
this.builder
.get('homepage')
.promise()
.then((homepageData) => {
this.homepage = homepageData;
});
}
}Paste the following in the corresponding template file, homepage.component.html:
<!-- src/app/homepage/homepage.component.html -->
<!-- Put your header here. -->
<app-your-header></app-your-header>
<builder-component *ngIf="homepage" [content]="homepage"></builder-component>
<!-- Put the rest of your page here. -->
<app-the-rest-of-your-page></app-the-rest-of-your-page>Import the BuilderModule in your app.module.ts:
// src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { YourHeaderComponent } from './your-header/your-header.component';
import { TheRestOfYourPageComponent } from './the-rest-of-your-page/the-rest-of-your-page.component';
import { BuilderModule } from '@builder.io/angular';
import { HomepageComponent } from './homepage/homepage.component';
@NgModule({
declarations: [
AppComponent,
YourHeaderComponent,
TheRestOfYourPageComponent,
HomepageComponent,
],
imports: [BrowserModule, AppRoutingModule, BuilderModule.forRoot()],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}Add the new component's route to your app-routing.module.ts:
// src/app/app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomepageComponent } from './homepage/homepage.component';
const routes: Routes = [
{
path: '', // Change this to the desired path.
component: HomepageComponent,
},
// ...other routes
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}