Get started with Gatsby

You must first create a project in Plasmic.

To view this quickstart with all the IDs and token placeholders replaced with real values, open your project in Plasmic Studio and press the “Code” button in the top toolbar.

Overview

This covers integrating Plasmic into your existing Gatsby codebase.

Want to quickly generate a new codebase with Plasmic already integrated? Use create-plasmic-app instead, or just press the Publish button in your project to push a new repo to GitHub!

Want to generate source code into your codebase (warning: advanced)? Learn about codegen.

Installation

Copy
npm install @plasmicapp/loader-gatsby
# or yarn add @plasmicapp/loader-gatsby

Initialization

Include the plugin @plasmicapp/loader-gatsby in gatsby-config.js.

Copy
module.exports = {
// ...
plugins: [
{
resolve: '@plasmicapp/loader-gatsby',
options: {
projects: [
{
id: 'PROJECTID', // ID of a project you are using
token: 'APITOKEN' // API token for that project
}
],
// Fetches the latest revisions, whether or not they were unpublished!
// Disable for production to ensure you render only published changes.
preview: true
}
}
]
};

To find your project’s ID and public API token: open the project in Plasmic Studio.

The project ID is in the URL, like: https://studio.plasmic.app/projects/PROJECTID.

The public API token can be found by clicking the Code toolbar button.

And define a plasmic-init.ts file—this is where code component registrations will go (later).

Copy
import { initPlasmicLoader } from '@plasmicapp/loader-gatsby';
export function initPlasmicLoaderWithRegistrations(plasmicOptions: any) {
const PLASMIC = initPlasmicLoader(plasmicOptions);
// Add all your code component registrations here.
return PLASMIC;
}

Auto load all Plasmic pages

To automatically render all Plasmic-defined pages at the routes specified in Plasmic, specify a Gatsby template page:

Copy
module.exports = {
// ...
plugins: [
{
resolve: '@plasmicapp/loader-gatsby',
options: {
// ...
},
options: {
projects: [
{
id: 'PROJECTID', // ID of a project you are using
token: 'APITOKEN' // API token for that project
}
],
// You may need to use require.resolve() for older versions of Gatsby.
defaultPlasmicPage: path.resolve('./src/templates/defaultPlasmicPage.tsx'),
// Optionally specify pages to ignore.
ignorePaths: ['/my-page']
}
}
]
};

And create the template, editing it with any wrappers you want:

Copy
import React from 'react';
import Helmet from 'react-helmet';
import { PlasmicComponent, PlasmicRootProvider, InitOptions, ComponentRenderData } from '@plasmicapp/loader-gatsby';
import { graphql, PageProps } from 'gatsby';
import { initPlasmicLoaderWithRegistrations } from '../plasmic-init';
export const query = graphql`
query ($path: String) {
plasmicComponents(componentNames: [$path])
plasmicOptions
}
`;
interface PlasmicGatsbyPageProps extends PageProps {
data: {
plasmicOptions: InitOptions;
plasmicComponents: ComponentRenderData;
};
}
const PlasmicGatsbyPage = ({ data, location }: PlasmicGatsbyPageProps) => {
const { plasmicComponents, plasmicOptions } = data;
const pageMeta = plasmicComponents.entryCompMetas[0];
const pageMetadata = pageMeta.pageMetadata;
return (
<PlasmicRootProvider
loader={initPlasmicLoaderWithRegistrations(plasmicOptions)}
prefetchedData={plasmicComponents}
pageRoute={pageMeta.path}
pageParams={pageMeta.params}
pageQuery={Object.fromEntries(new URLSearchParams(location.search))}
Head={Helmet}
>
<Helmet>
{pageMetadata?.title && <title>{pageMetadata.title}</title>}
{pageMetadata?.title && <meta property="og:title" content={pageMetadata.title} />}
{pageMetadata?.description && <meta property="og:description" content={pageMetadata.description} />}
{pageMetadata?.openGraphImageUrl && <meta property="og:image" content={pageMetadata.openGraphImageUrl} />}
</Helmet>
<PlasmicComponent component={pageMeta.displayName} />
</PlasmicRootProvider>
);
};
export default PlasmicGatsbyPage;

If your project has dynamic pages, you will need to manually add your dynamic routes to your gatsby-node.ts. Learn more about dynamic pages.

Render a single Plasmic page or component

Note: You can instead auto-load all Plasmic pages at the correct routes (recommended) rather than manually loading individual pages—see previous section.

We use Gatsby’s GraphQL layer to fetch the design statically.

For example, to render a page: add a file under src/pages/, named for your desired route, with the following code.

COMPONENT_OR_PAGEROUTE refers to the name of the page or component that you want to render, such as Winter22LandingPage. If it’s a page, you can also use the route you assigned the page in Plasmic, like /landing.

Copy
// This page will show up at the route /my-page
import * as React from 'react';
import { PlasmicComponent, PlasmicRootProvider } from '@plasmicapp/loader-gatsby';
import { graphql } from 'gatsby';
// You can use any library you want for <head/> injection
import { Helmet } from 'react-helmet';
import { initPlasmicLoaderWithRegistrations } from '../plasmic-init';
// Statically fetch the data needed to render Plasmic pages or components.
// You can pass in multiple page paths or component names.
export const query = graphql`
query {
plasmicComponents(componentNames: ["COMPONENTNAME"])
plasmicOptions
}
`;
interface PlasmicGatsbyPageProps extends PageProps {
data: {
plasmicOptions: InitOptions;
plasmicComponents: ComponentRenderData;
};
}
// Render the page or component from Plasmic.
const MyPage = ({ data, location, path, params }: PlasmicGatsbyPageProps) => {
const { plasmicComponents, plasmicOptions } = data;
return (
<PlasmicRootProvider
loader={initPlasmicLoaderWithRegistrations(plasmicOptions)}
prefetchedData={plasmicComponents}
pageRoute={path}
pageParams={params}
pageQuery={Object.fromEntries(new URLSearchParams(location.search))}
Head={Helmet}
>
<PlasmicComponent component="COMPONENT_OR_PAGEROUTE" />
</PlasmicRootProvider>
);
};
export default MyPage;

Adding custom code components

Let your Plasmic Studio users drag/drop and visually manipulate your own custom React components! Learn more.

Step 1

Create a simple example React component:

src/components/HelloWorld.tsx
Copy
import * as React from 'react';
export interface HelloWorldProps {
children?: React.ReactNode;
className?: string;
verbose?: boolean;
}
export function HelloWorld({ children, className, verbose }: HelloWorldProps) {
return (
<div className={className} style={{ padding: '20px' }}>
<p>Hello there! {verbose && 'Really nice to meet you!'}</p>
<div>{children}</div>
</div>
);
}

Step 2

Update module src/plasmic-init.ts to register your code components.

Copy
import { initPlasmicLoader } from '@plasmicapp/loader-gatsby';
import { HelloWorld } from './components/HelloWorld';
export function initPlasmicLoaderWithRegistrations(plasmicOptions: any) {
const PLASMIC = initPlasmicLoader(plasmicOptions);
// Add all your code component registrations here.
PLASMIC.registerComponent(HelloWorld, {
name: 'HelloWorld',
props: {
verbose: 'boolean',
children: 'slot'
}
});
return PLASMIC;
}

Step 3

Create a host page at route /plasmic-host:

Copy
import * as React from 'react';
import { PlasmicCanvasHost } from '@plasmicapp/loader-gatsby';
import { initPlasmicLoaderWithRegistrations } from '../plasmic-init';
import { graphql } from 'gatsby';
export const pageQuery = graphql`
query {
plasmicOptions
}
`;
export default function Host({ data }) {
const { plasmicOptions } = data;
initPlasmicLoaderWithRegistrations(plasmicOptions);
return <PlasmicCanvasHost />;
}

We also need to update gatsby-ssr.js to remove HMR for the /plasmic-host route:

Copy
const React = require('react');
const HeadComponents = [
<script
key="plasmic-hmr"
type="text/javascript"
dangerouslySetInnerHTML={{
__html: `
if (typeof window !== "undefined" && /\\/plasmic-host\\/?$/.test(window.location.pathname)) {
const RealEventSource = window.EventSource;
window.EventSource = function(url, config) {
if (/[^a-zA-Z]hmr($|[^a-zA-Z])/.test(url)) {
console.warn("Plasmic: disabled EventSource request for", url);
return {
onerror() {}, onmessage() {}, onopen() {}, close() {}
};
} else {
return new RealEventSource(url, config);
}
}
}
`
}}
/>
];
const isProduction = process.env.NODE_ENV === 'production';
exports.onRenderBody = ({ pathname, setHeadComponents }) => {
/**
* We add the preamble tag script to all pages during development mode
* because during development all pages are dynamically rendered based
* on `/` route, during production we add it only in `/plasmic-host/`
*/
if (!isProduction || pathname === '/plasmic-host/') {
setHeadComponents(HeadComponents);
}
};

Step 4

Start your app:

npm run start

And check that you see a confirmation message at http://localhost:{props.port}/plasmic-host.

Step 5

Open https://studio.plasmic.app, click the menu for the current project, select “Configure project,” and set it to http://localhost:{props.port}/plasmic-host.

configure project menu

Step 6

Re-open this project (or reload this tab) to see your component listed in the insert menu!

insert code component

Later, after you deploy the route to production, update the project to use your production host URL instead, such as https://my-app.com/plasmic-host. This way, other members of your team (who can’t access your localhost dev server) will be able to open and edit the project in Plasmic. (Again, the /plasmic-host route itself is a special hidden route not meant for humans to visit; it is only for Plasmic Studio to hook into.)

Learn more about code components.

There’s much more to explore!

For example:

Continue learning in the full docs.

Was this page helpful?

Have feedback on this page? Let us know on our forum.