Getting Started with Gatsby.js and BCMS
This guide will show you how to integrate BCMS with a Gatsby project.
Let’s dive in!
To quickly set up a simple Gatsby blog with BCMS, run the following command:
npx @thebcms/cli create gatsby starter simple-blog
Follow the prompts as they appear.
This command will:
Set up a new BCMS project
Add sample content
Scaffold a Gatsby project locally
Generate an .env file and update the code with the necessary BCMS settings
Afterward, just run:
npm install npm run develop
If you’d rather go through each step manually, here’s a detailed guide:
Open Your BCMS Project
Visit https://app.thebcms.com and make sure you have some entries in your BCMS project. This is essential for fetching and displaying data in Gatsby.js. For instance, create a template called Blog and add a media property like Cover Image.
Create a Blog Entry
Add a new blog entry titled My First Blog, include a cover image, and some content, such as lorem ipsum.
Create an API Key
Go to Administration > Settings > API Keys. Create a new API key, and keep this page open, as you'll need the API key information in the following steps. Ensure that the key has permission to access entries from the Blog template.
Create a Gatsby.js Project
Open your terminal and use the Gatsby.js CLI to create a new project:
gatsby new
Once the project is created, open it in your code editor.
Install BCMS Packages
Install the necessary BCMS-related packages by running the following command:
npm i --save @thebcms/cli @thebcms/types @thebcms/utils @thebcms/client @thebcms/components-react
Modify package.json
In your project, open package.json
and adjust the scripts section to look like this:
{ "scripts":{ "develop":"bcms --pull types --lng ts && gatsby develop", "start":"bcms --pull types --lng ts && gatsby develop", "build":"bcms --pull types --lng ts && gatsby build", "serve":"bcms --pull types --lng ts && gatsby serve", "clean":"gatsby clean", "typecheck":"tsc --noEmit" } }
The bcms --pull types --lng ts
command will start the BCMS CLI, pull types from BCMS, and store them in /bcms/types/
. These types work for both JavaScript and TypeScript.
Set Up the BCMS Configuration
In the root of your project, create a file named bcms.config.cjs
. Add the following configuration:
module.exports = { client: { orgId: "YOUR_PROJECT_ORG_ID", instanceId: "YOUR_PROJECT_INSTANCE_ID", apiKey: { id: "API_KEY_ID", secret: "API_KEY_SECRET", }, }, };
You can find the necessary information for this configuration on the API key page you created earlier.
Initialize BCMS Client
In the root directory, create a new file called bcms-client.ts
. Inside, initialize the BCMS client:
import { Client } from "@thebcms/client"; export const bcms = new Client("ORG_ID", "INSTANCE_ID", { id: "API_KEY_ID", secret: "API_KEY_SECRET", }, { injectSvg: true, }, );
Create Blog Page Templates
Create two page templates: one to list all blogs (./src/templates/blogs.tsx
) and another to display individual blog data (./src/templates/blog.tsx
).
Here’s the code for blog.tsx
:
import React from "react"; import { BlogEntryMetaItem } from "../../bcms/types/ts"; import { EntryContentParsedItem } from "@thebcms/client/types"; import { BCMSContentManager, BCMSImage } from "@thebcms/components-react"; import { bcms } from "../../bcms-client"; export interface BlogPageTemplateProps { blog: { meta: BlogEntryMetaItem; content: EntryContentParsedItem[]; }; } export const BlogPageTemplate: React.FC<{ pageContext: BlogPageTemplateProps; }> = ({ pageContext: { blog } }) => { return ( <div className="flex flex-col items-center"> <div className="relative w-full h-[450px]"> <BCMSImage media={blog.meta.cover_image} clientConfig={bcms.getConfig()} className="w-full h-full object-cover" /> <div className={`absolute top-0 left-0 w-full h-full bg-black bg-opacity-30 backdrop-blur-sm flex flex-col gap-2 items-center justify-center`} > <div className="text-3xl text-white font-bold">{blog.meta.title}</div> </div> </div> <div className="max-w-[640px] w-full mt-36"> <BCMSContentManager items={blog.content} /> </div> </div> ); }; export default BlogPageTemplate;
And here’s the code for blogs.tsx
:
import React from "react"; import { BCMSImage } from "@thebcms/components-react"; import { BCMSMedia } from "../../bcms/types/ts"; import { bcms } from "../../bcms-client"; import { Link } from "gatsby"; export interface BlogsPageTemplateProps { blogs: Array<{ title: string; image: BCMSMedia; slug: string }>; } export const BlogsPageTemplate: React.FC<{ pageContext: BlogsPageTemplateProps; }> = ({ pageContext: { blogs } }) => { return ( <div className="flex flex-col gap-4"> {blogs.map((blog, blogIdx) => { return ( <Link to={`/blog/${blog.slug}`} key={blogIdx} className="flex gap-2 items-center bg-gray-50" > <div className="w-20 h-20"> <BCMSImage className="w-full h-full object-cover" media={blog.image} clientConfig={bcms.getConfig()} options={{ sizes: [ { width: 80, height: 80 }, { width: 160, height: 160 }, ], }} /> </div> </Link> ); })} ; </div> ); }; export default BlogsPageTemplate;
Create Pages in gatsby-node.ts
In gatsby-node.ts
, create pages based on the templates you just made:
import { CreatePagesArgs } from "gatsby"; import { BlogEntry, BlogEntryMetaItem } from "./bcms/types/ts"; import path from "path"; import { bcms } from "./bcms-client"; import { BlogsPageTemplateProps } from "./src/templates/blogs"; import { BlogPageTemplateProps } from "./src/templates/blog"; import { EntryContentParsedItem } from "@thebcms/client/types"; export const createPages = async ({ actions: { createPage }, }: CreatePagesArgs) => { const blogs = (await bcms.entry.getAll("blog")) as BlogEntry[]; const blogsCtx: BlogsPageTemplateProps = { blogs: blogs.map((blog) => { const meta = blog.meta.en as BlogEntryMetaItem; return { title: meta.title, slug: meta.slug, image: meta.cover_image, }; }), }; createPage({ path: "/blog", component: path.resolve("./src/templates/blogs.tsx"), context: blogsCtx, }); for (const blog of blogs) { const meta = blog.meta.en as BlogEntryMetaItem; const blogCtx: BlogPageTemplateProps = { blog: { meta: meta, content: blog.content.en as EntryContentParsedItem[], }, }; createPage({ path: `/blog/${meta.slug}`, component: path.resolve("./src/templates/blog.tsx"), context: blogCtx, }); } };
That's it—happy coding!