I've built a full-stack starter project that combines React 19 with React Router 7 in framework mode and Strapi 5 headless CMS, and I'd love to share it with you.
We'll build a simple but powerful blog website with three main pages:
Dynamic Landing Page - We'll create a homepage that pulls content from our Strapi backend. The cool part? Content managers can rearrange sections without touching any code.
Articles Page - A clean page that displays all our blog posts in a grid layout, ready for future pagination features.
Article Detail Page - Individual pages for each blog post, complete with the author info, content, and proper SEO tags.
What makes this project special is how everything connects. Our React frontend talks to Strapi through a clean API, giving us server-side rendering for better SEO, full TypeScript support for fewer bugs, and a content management system that non-technical users can actually use.
Later in this tutorial, we'll build the project together step by step. But first, let's talk about the tech stack and why I chose these tools.
React 19 - Because it's awesome and brings the latest performance improvements and modern features. Learn more about React
React Router 7 Framework Mode - The evolution of Remix, now integrated into React Router. This provides server-side rendering, file-based routing, and excellent developer experience out of the box. React Router Documentation
Shadcn/ui & Tailwind CSS - A combination of accessible, customizable components built on Radix UI with Tailwind's utility-first styling approach. This provides a clean, modern design system that's both beautiful and functional. Shadcn/ui | Tailwind CSS
Strapi 5 - A powerful headless CMS that provides a flexible admin panel, TypeScript support, and excellent developer experience. Strapi Documentation
If you just want to get the project running quickly:
git clone https://github.com/PaulBratslavsky/strapi-react-router-7-starter.git
cd strapi-react-router-7-starter
yarn setup
yarn seed
yarn devThe frontend will be available at http://localhost:5173 and the Strapi admin at http://localhost:1337/admin.
Check out the video walkthrough that showcases the project features and setup process.
One of the coolest features is the dynamic content block system. Non-technical users can easily rearrange page sections through the Strapi admin panel, and the changes reflect immediately on the frontend. This is achieved through a flexible block renderer system that matches Strapi components to React components.
The project uses Strapi's SDK for clean, type-safe API calls. Instead of manually writing fetch requests, you get elegant functions like:
1// Clean, typed API calls
2const landingPageData = await sdk.find('landing-page');
3const articles = await sdk.find('articles');Each page uses React Router 7's meta function to dynamically set SEO tags based on content from Strapi, ensuring great search engine optimization.
Custom error boundaries provide graceful fallbacks and a clean 404 page experience when content isn't found.
The project is structured as a monorepo with two main directories:
client/ - React Router 7 frontend applicationserver/ - Strapi 5 backend CMS1client/app/
2├── components/
3│ ├── blocks/ # Dynamic content blocks
4│ ├── custom/ # Custom components
5│ └── ui/ # Base UI components
6├── lib/ # API client and utilities
7├── routes/ # File-based routing
8└── types/ # TypeScript definitionsI will walk you through step by step guid how I built this project but in the mean time you can explore it via the codebase above.
Paul