Build an API for your front end using Pages Functions
In this tutorial, you will build a full-stack Pages application. Your application will contain:
- A front end, built using Cloudflare Pages and the React framework.
- A JSON API, built with Pages Functions, that returns blog posts that can be retrieved and rendered in your front end.
If you prefer to work with a headless CMS rather than an API to render your blog content, refer to the headless CMS tutorial.
To begin, create a new Pages application using the React framework.
In your terminal, create a new React project called blog-frontend using the create-vite command. Go into the newly created blog-frontend directory and start a local development server:
npx create-vite -t react blog-frontendcd blog-frontendnpm installnpm run devTo set up your React project:
- Install the React Router ↗ in the root of your blog-frontenddirectory.
- Clear the contents of src/App.js. Copy and paste the following code to import the React Router intoApp.js, and set up a new router with two routes:
import { Routes, Route } from "react-router-dom";
import Posts from "./components/posts";import Post from "./components/post";
function App() {  return (    <Routes>      <Route path="/" element={<Posts />} />      <Route path="/posts/:id" element={<Post />} />    </Routes>  );}
export default App;- In the srcdirectory, create a new folder calledcomponents.
- In the componentsdirectory, create two files:posts.js, andpost.js. These files will load the blog posts from your API, and render them.
- Populate posts.jswith the following code:
import React, { useEffect, useState } from "react";import { Link } from "react-router-dom";
const Posts = () => {  const [posts, setPosts] = useState([]);
  useEffect(() => {    const getPosts = async () => {      const resp = await fetch("/api/posts");      const postsResp = await resp.json();      setPosts(postsResp);    };
    getPosts();  }, []);
  return (    <div>      <h1>Posts</h1>      {posts.map((post) => (        <div key={post.id}>          <h2>            <Link to={`/posts/${post.id}`}>{post.title}</Link>          </h2>        </div>      ))}    </div>  );};
export default Posts;- Populate post.jswith the following code:
import React, { useEffect, useState } from "react";import { Link, useParams } from "react-router-dom";
const Post = () => {  const [post, setPost] = useState({});  const { id } = useParams();
  useEffect(() => {    const getPost = async () => {      const resp = await fetch(`/api/post/${id}`);      const postResp = await resp.json();      setPost(postResp);    };
    getPost();  }, [id]);
  if (!Object.keys(post).length) return <div />;
  return (    <div>      <h1>{post.title}</h1>      <p>{post.text}</p>      <p>        <em>Published {new Date(post.published_at).toLocaleString()}</em>      </p>      <p>        <Link to="/">Go back</Link>      </p>    </div>  );};
export default Post;You will now create a Pages Functions that stores your blog content and retrieves it via a JSON API.
To create the Pages Function that will act as your JSON API:
- Create a functionsdirectory in yourblog-frontenddirectory.
- In functions, create a directory namedapi.
- In api, create aposts.jsfile in theapidirectory.
- Populate posts.jswith the following code:
import posts from "./post/data";
export function onRequestGet() {  return Response.json(posts);}This code gets blog data (from data.js, which you will make in step 8) and returns it as a JSON response from the path /api/posts.
- In the apidirectory, create a directory namedpost.
- In the postdirectory, create adata.jsfile.
- Populate data.jswith the following code. This is where your blog content, blog title, and other information about your blog lives.
const posts = [  {    id: 1,    title: "My first blog post",    text: "Hello world! This is my first blog post on my new Cloudflare Workers + Pages blog.",    published_at: new Date("2020-10-23"),  },  {    id: 2,    title: "Updating my blog",    text: "It's my second blog post! I'm still writing and publishing using Cloudflare Workers + Pages :)",    published_at: new Date("2020-10-26"),  },];
export default posts;- In the postdirectory, create an[[id]].jsfile.
- Populate [[id]].jswith the following code:
import posts from "./data";
export function onRequestGet(context) {  const id = context.params.id;
  if (!id) {    return new Response("Not found", { status: 404 });  }
  const post = posts.find((post) => post.id === Number(id));
  if (!post) {    return new Response("Not found", { status: 404 });  }
  return Response.json(post);}[[id]].js is a dynamic route which is used to accept a blog post id.
After you have configured your Pages application and Pages Function, deploy your project using the Wrangler or via the dashboard.
In your blog-frontend directory, run wrangler pages deploy to deploy your project to the Cloudflare dashboard.
wrangler pages deploy blog-frontendTo deploy via the Cloudflare dashboard, you will need to create a new Git repository for your Pages project and connect your Git repository to Cloudflare. This tutorial uses GitHub as its Git provider.
Create a new GitHub repository by visiting repo.new ↗. After creating a new repository, prepare and push your local application to GitHub by running the following commands in your terminal:
git initgit remote add origin https://github.com/<YOUR-GH-USERNAME>/<REPOSITORY-NAME>git add .git commit -m "Initial commit"git branch -M maingit push -u origin mainDeploy your application to Pages:
- Log in to the Cloudflare dashboard ↗ and select your account.
- In Account Home, select Workers & Pages > Create application > Pages > Connect to Git.
- Select the new GitHub repository that you created and, in the Set up builds and deployments section, provide the following information:
| Configuration option | Value | 
|---|---|
| Production branch | main | 
| Build command | npm run build | 
| Build directory | build | 
After configuring your site, begin your first deploy. You should see Cloudflare Pages installing blog-frontend, your project dependencies, and building your site.
By completing this tutorial, you have created a full-stack Pages application.
- Learn about Pages Functions routing
Was this helpful?
- Resources
- API
- New to Cloudflare?
- Products
- Sponsorships
- Open Source
- Support
- Help Center
- System Status
- Compliance
- GDPR
- Company
- cloudflare.com
- Our team
- Careers
- 2025 Cloudflare, Inc.
- Privacy Policy
- Terms of Use
- Report Security Issues
- Trademark