Astro Conference templates & code starters for BCMS

Sick of rebuilding your portfolio every time you want to add a project to your work experience?
Astro templates & code starters for BCMS give you a clean separation between code and content, so you can focus on building and let BCMS handle content updates.
Astro’s static-first architecture means your portfolio loads instantly, with zero JS by default and just enough interactivity where needed.
You gain full control over structure and layout using components, while BCMS provides structured models for everything, including projects, case studies, skills, blogs, and custom pages.
This template is ideal for devs who want their work to speak clearly, without performance issues, overengineered frameworks, or pushing commits every time something changes.
Content is structured, not scattered: Model your portfolio in BCMS with fields for tech stack, role, links, images, and tags/ Fetch it cleanly via Astro without copy-pasting JSON blobs.
Write blog posts without touching the repo: Publish updates, thoughts, or case studies inside BCMS. Skip the markdown files and builds.
Zero-JS until you need it: Astro compiles your site to static HTML, with islands for interactive bits (like a project filter or contact form) no SPA bloat.
Component-based layout you control: Use Astro’s file-based routing and component structure to quickly build and customize your layout.
Multi-language support: Translate pages and projects using BCMS localization features. No fragile plugins required.
Optimized media out of the box: Use Astro’s <Image> component with BCMS to lazy-load and resize your screenshots, logos, or cover images.
Clean SEO setup, no boilerplate: Seo friendly features out of the box: page titles, meta descriptions, Open Graph data, and schema from your BCMS entries.
Mobile-first, performance-focused UI: Your site is responsive and fast by default no extra effort needed to look good on a phone.
Tired of clunky site generators and outdated CMS platforms slowing you down? You’re not alone. Many developers spend way too much time fighting against bloated frameworks and rigid tools just to launch a simple blog or content site.
But what if you didn’t have to compromise? What if you could build blazing-fast websites with total creative control and a content workflow that actually makes sense?
Building an Astro Portfolio website with a headless CMS, like BCMS, can be a great example of what I am talking about.
Astro is a modern static site generator built for performance. It ships less JavaScript by default, so your site loads faster, ranks better, and keeps visitors engaged. Pair that with BCMS, a headless CMS that gives you full flexibility over your content without the WordPress headaches, and you’ve got a winning combo for blogs, marketing sites, and anything content-heavy.
Let’s dive into why Astro and BCMS are the perfect match for your next project.
A headless CMS like BCMS decouples content management from front-end presentation, offering:
Flexibility
Deliver content via APIs to any frontend framework (Astro, React, mobile apps, etc.).
Developers aren’t locked into a CMS-specific templating system, enabling custom designs.
Security
The CMS backend is isolated from public access, minimizing risks like DDoS attacks or SQL injections.
Content is served via secure APIs, reducing exposure to vulnerabilities.
Scalability
Easily integrate third-party tools (analytics, e-commerce) without CMS constraints.
Scale content delivery independently of the frontend using CDNs or caching strategies.
Content Agility
Non-technical teams update content in BCMS without disrupting the codebase.
Schedule posts, manage SEO metadata, and reuse content across platforms.
Astro is a modern SSG designed for speed and developer flexibility. Here’s why it shines:
Blazing-fast performance:
Zero JavaScript by default: Astro ships static HTML/CSS, eliminating unnecessary client-side JS.
Static Site Generation (SSG): Pre-render pages at build time using content from BCMS, ensuring instant page loads.
“Islands” of interactivity: Use JavaScript to hydrate only essential components (e.g., a search bar), keeping the rest static.
Partial hydration reduces bundle sizes, improving Lighthouse scores and SEO.
Framework agnostic:
Use React, Vue, Svelte, or plain HTML components in the same project.
Perfect for teams transitioning between frameworks or leveraging existing components.
SEO-centric:
Static pages are SEO-friendly by default, with fast load times and clean HTML.
Integrate tools like Markdown, MDX, or Open Graph tags seamlessly.
Simpler developer experience:
No complex server configuration is required: Astro builds static files that are ready for global CDN deployment.
Built-in image optimization, asset bundling, and scoped CSS.
Before diving into creating a personal site with Astro and BCMS, ensure you have the following:
A basic understanding of Astro.
Node.js and npm installed.
A BCMS Account (Free Tier or Trial).
Getting started with Astro and BCMS is simple. You can use the Astro project setup tool to quickly spin up a sample blog. To create a new project with BCMS and Astro, run the following command in your terminal:
npx @thebcms/cli create astro starter simple-blog
Running this command will initialize your project, generate a blog starter, and connect it to your BCMS instance.
Your default browser will open, prompting you to log into your BCMS account. If you don’t have one yet, you’ll be guided through the sign-up process.
Once logged in, you’ll be asked to name your project. After that, the setup will complete automatically, as shown in the image below:
Once it’s ready, simply run:
npm install && npm run dev
Let’s head over to the BCMS dashboard and make sure the correct project, the one I just created, is selected.
Next, I’ll remove the default templates and entries that come with the Astro blog starter so we can start fresh with our own content.
To do this, go to Templates in the sidebar, select any existing templates, and delete them.
Now, let’s start with content modeling. Create a new template. Click Create new template, give it a name, and then click the Create button to proceed.
The Resume template will include the following keys:
title - string
slug - String
email - String
phone - Number
city - String
Next, I’ll create another template called Skills:
Skills template properties:
title - String
slug - String
skills - String
title - String
Slug - String
duration - Date
description - String
After creating the Experience template, you can link it to this group. It should be an array, as it will store multiple work experiences.
I’ll now create an education template:
The education templates will include keys such as:
certification - String
institution - String
duration - String
location - String
After creating and publishing entries in BCMS, the next step involves integrating the BCMS APIs into the Astro.js application to programmatically fetch the content. This enables dynamic rendering of blog posts on the client side.
I’ll start with importing the required modules we need:
import Layout from "../layouts/layout.astro"; import { bcms } from "../bcms-client"; import type { HeaderEntry, HeaderEntryMetaItem, SkillsEntry, SkillsEntryMetaItem, ExperienceEntry, ExperienceEntryMetaItem, EducationEntry, EducationEntryMetaItem, } from "../../bcms/types/ts";
//header const headerEntry = (await bcms.entry.getAll("header")) as HeaderEntry[]; const header = headerEntry.map((e) => e.meta.en as HeaderEntryMetaItem); //skills const skillEntry = (await bcms.entry.getAll("skills")) as SkillsEntry[]; const skillArr = skillEntry.map((e) => e.meta.en as SkillsEntryMetaItem); const skills = skillArr.map((e) => e); //expirience const expirienceEntry = (await bcms.entry.getAll( "experience" )) as ExperienceEntry[]; const expirienceArr = expirienceEntry.map( (e) => e.meta.en as ExperienceEntryMetaItem ); const experiences = expirienceArr.map((e) => e); //EDUCATION const educationEntry = (await bcms.entry.getAll("education")) as EducationEntry[]; const educationArr = educationEntry.map((e) => e.meta.en as EducationEntryMetaItem); const bcmsConfig = bcms.getConfig(); const formattedString= header[0].slug .replace(/-/g, " ") .replace(/\b\w/g, (char) => char.toUpperCase()); const fomartDate = (timestamp:number)=> { const date = new Date(timestamp); const formatted = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}` return formatted; }
The code snippet fetches structured content from the BCMS for four entry types: header, skills, experience, and education. Each entry. The getAll()
call retrieves all records for a given content type and casts them to their respective TypeScript types, thereby enforcing schema integrity.
Next, I’ll build the layout component and render the structured resume data sourced from the BCMS entries. The content is wrapped in a flexbox container, centered on the page, with responsive padding and width constraints defined via Tailwind CSS classes.
<Layout> <div class="flex justify-center border w-screen"> <div class="flex w-[60%] justify-center flex-col border px-8"> <div class="my-8"> <h1 class="text-4xl font-bold text-center mt-8 mb-4"> {header[0].title} </h1> <p class="text-center mb-4 tracking-wider">{formattedString}</p> <div class="flex justify-center"> <p>{header[0].phone} </p> <p class="underline">{header[0].email} </p> <p>{header[0].city} </p> </div> </div> <div> <h2 class="font-bold">SKILLS</h2> <hr class="border-t-2 border-black mb-4" /> { skills[0].skills.map((item) => ( <div class="flex flex-wrap gap-2"> <li>{item}</li> </div> )) } </div> <div class="my-4 "> <h2 class="font-bold" >PROFESSIONAL EXPIRIENCE</h2> <hr class="border-t-2 border-black mb-4" /> <div class=""> { experiences.map((item) => ( <div class="mb-2 flex w-full justify-between items-center"> <h3 class="font-bold"> {item.title} <br />{" "} <span class="text-gray-500"> {item.slug} </span> </h3> <h3> {fomartDate(item.duration!.timestamp)} </h3> </div> <div class="mb-8"> {item.description?.map((exp) => ( <ul> <li class="list-disc"> {exp} </li> </ul> ))} </div> )) } </div> </div> <div> <div class="my-4 "> <h2 class="font-bold" >EDUCATION</h2> <hr class="border-t-2 border-black mb-4" /> <div class=""> { educationArr.map((item)=> <h4 class="font-bold text-sm">{item.certification}</h4> <h5 class="text-sm">{item.institution}</h5> <h5 class="text-sm">{item.duration}, {item.location}</h5> <div> </div>) } </div> </div> </div> </Layout>
Here is a preview of the application:
This article outlined a complete workflow for integrating BCMS with the Astro.js application, covering everything from initial project scaffolding to modeling structured content and consuming it via the BCMS API.
The implementation showcases how to architect a content-driven web application where content and presentation are cleanly decoupled, enabling dynamic rendering of blog entries directly from a headless CMS.
By leveraging BCMS’s API-first approach and Astro.js’s optimized rendering capabilities, the resulting system is not only highly extensible but also performance-focused and developer-friendly.
This architecture makes it straightforward to introduce new content types, apply granular styling enhancements, or implement advanced capabilities such as incremental static regeneration, localization, and content versioning.
To explore more about Astro.js and BCMS, check out the Astro.js Blog Starter Toolkit and take a look at or contribute to our open-source astro-resume project.
npx @thebcms/cli create astro starter personal
There are many example apps and starter projects to get you started.
Get all the latest BCMS updates, news and events.
By submitting this form you consent to us emailing you occasionally about our products and services. You can unsubscribe from emails at any time, and we will never pass your email to third parties.