Getting Started with Astro and BCMS
This guide will take you through integrating BCMS with an Astro project using native Astro integration. Let's get started!
To set up a simple Astro blog with BCMS quickly, use the following command:
npx @thebcms/cli create astro starter simple-blog
Follow the on-screen prompts.
This command will:
Initialize a new BCMS project
Add sample content for you
Scaffold an Astro project locally
Set up environment files and configure the project with BCMS settings
Create both private and public BCMS clients
Once it’s ready, simply run:
npm install npm run dev
For a detailed, step-by-step setup, read on below:
Open your BCMS project
Go to https://app.thebcms.com. Make sure you have some entries in your BCMS project to fetch and display in Astro. For example, create a template called Blog and add a media property called Cover Image.

Create a Blog Entry
Create a new blog entry with the title My First Blog, add a cover image, and write some content (e.g., lorem ipsum).

Create an API Key
Navigate to Administration > Settings > API Keys. Create a new API key, and leave the page open for the next steps. Ensure the key has permission to access entries from the Blog template.

Create an Astro Project
Open your terminal and create a new Astro project using the following command:
npm create astro@latest
Install BCMS Packages
Run the following command to install BCMS-related packages:
npm i --save @thebcms/cli @thebcms/client @thebcms/components-astro @thebcms/types @thebcms/utils
Update package.json
Modify the scripts section in package.json as follows:
"scripts": { "dev": "bcms pull types lng ts && astro dev", "start": "bcms pull types lng ts && astro dev", "build": "bcms pull types lng ts && astro check && astro build", "preview": "bcms pull types lng ts && astro preview", "astro": "astro" },
The bcms pull types lng ts
command starts the BCMS CLI and pulls types from BCMS, saving them in /bcms/types/
. These types work for both JavaScript and TypeScript.
Create bcms.config.cjs
In the root of your project, create a file called bcms.config.cjs
and add the following configuration:
/** * @type {import('@thebcms/cli/config').BCMSConfig} */ module.exports = { client: { orgId: process.env.BCMS_ORG_ID, instanceId: process.env.BCMS_INSTANCE_ID, apiKey: { id: process.env.BCMS_API_KEY_ID, secret: process.env.BCMS_API_KEY_SECRET, }, }, };
This configuration uses environment variables for security. All the information for this configuration can be found on the API key page you created earlier.
Create .env
Place your API key and project information in .env
file:
BCMS_ORG_ID= BCMS_INSTANCE_ID= BCMS_API_KEY_ID= BCMS_API_KEY_SECRET= # Information about this API Key will be public PUBLIC_BCMS_ORG_ID= PUBLIC_BCMS_INSTANCE_ID= PUBLIC_BCMS_API_KEY_ID= PUBLIC_BCMS_API_KEY_SECRET=
Initialize BCMS Clients
In the /src directory, create two client files for different use cases:
src/bcms-private.ts (Server-side operations)
import { Client } from '@thebcms/client'; export const bcmsPrivate = new Client( import.meta.env.BCMS_ORG_ID || '', import.meta.env.BCMS_INSTANCE_ID || '', { id: import.meta.env.BCMS_API_KEY_ID || '', secret: import.meta.env.BCMS_API_KEY_SECRET || '', }, { injectSvg: true, }, );
src/bcms-public.ts (Client-side operations)
import { Client } from '@thebcms/client'; export const bcmsPublic = new Client( import.meta.env.PUBLIC_BCMS_ORG_ID || '', import.meta.env.PUBLIC_BCMS_INSTANCE_ID || '', { id: import.meta.env.PUBLIC_BCMS_API_KEY_ID || '', secret: import.meta.env.PUBLIC_BCMS_API_KEY_SECRET || '', }, { injectSvg: true, }, );
Fetch and Display Data
In /src/pages/index.astro
, fetch data from the BCMS project and display it on the page:
--- import Layout from '../layouts/layout.astro'; import Tag from '../components/tag.astro'; import BlogCard from '../components/blog-card.astro'; import { bcmsPrivate } from '../bcms-private'; import type { BlogEntry, BlogEntryMetaItem } from '@bcms-types'; const blogs = (await bcmsPrivate.entry.getAll('blog')) as BlogEntry[]; const items = blogs.map((e) => e.meta.en as BlogEntryMetaItem); --- <Layout> <div class="py-24 md:py-32"> <div class="container"> <div class="flex flex-col gap-6 items-center text-center mb-20 md:mb-[120px]"> <Tag size="lg">Hi, I'm Mark 👋</Tag> <h1 class="text-4xl font-bold leading-none md:text-5xl"> This is my blog </h1> </div> <div> <div class="grid grid-cols-1 gap-12 max-w-[1040px] mx-auto"> { items.map((item) => { return <BlogCard blog={item} />; }) } </div> </div> </div> </div> </Layout>
That's it - happy coding!