Cloudflare Docs
Visit Pages on GitHub
Set theme to dark (⇧+D)

Build an API for your front end using Pages Functions

​​ Introduction

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.

​​ Build your front end

To begin, create a new Pages application using the React framework.

​​ Create a new React project

In your terminal, create a new React project called blog-frontend using the create-react-app command. Go into the newly created blog-frontend directory and start a local development server:

Create a new React application
$ npx create-react-app blog-frontend
$ cd blog-frontend
$ npm start

​​ Set up your React project

To set up your React project:

  1. Install the React Router in the root of your blog-frontend directory.

With npm:

$ npm install [email protected]

With yarn:

$ yarn add [email protected]
  1. Clear the contents of src/App.js. Copy and paste the following code to import the React Router into App.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 (
<Route path="/" element={<Posts />} />
<Route path="/posts/:id" element={<Post />} />
export default App;
  1. In the src directory, create a new folder called components.
  2. In the components directory, create two files: posts.js, and post.js. These files will load the blog posts from your API, and render them.
  3. Populate posts.js with 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();
}, []);
return (
{ => (
<div key={}>
<Link to={`/posts/${}`}>{post.title}</Link>
export default Posts;
  1. Populate post.js with 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();
}, [id]);
if (!Object.keys(post).length) return <div />;
return (
<em>Published {new Date(post.published_at).toLocaleString()}</em>
<Link to="/">Go back</Link>
export default Post;

​​ Build your API

You will now create a Pages Functions that stores your blog content and retrieves it via a JSON API.

​​ Write your Pages Function

To create the Pages Function that will act as your JSON API:

  1. Create a functions directory in your blog-frontend directory.
  2. In functions, create a directory named api.
  3. In api, create a posts.js file in the api directory.
  4. Populate posts.js with 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.

  1. In the api directory, create a directory named post.
  2. In the post directory, create a data.js file.
  3. Populate data.js with 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
  1. In the post directory, create an [[id]].js file.
  2. Populate [[id]].js with the following code:
import posts from './data'
export function onRequestGet(context) {
const id =
if (!id) {
return new Response('Not found', { status: 404 })
const post = posts.find(post => === 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.

​​ Deploy

After you have configured your Pages application and Pages Function, deploy your project using the Wrangler or via the dashboard.

​​ Deploy with Wrangler

In your blog-frontend directory, run wrangler pages deploy to deploy your project to the Cloudflare dashboard.

$ wrangler pages deploy blog-frontend

​​ Deploy via the dashboard

To 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 repository

Create a new GitHub repository by visiting After creating a new repository, prepare and push your local application to GitHub by running the following commands in your terminal:

$ git init
$ git remote add origin<YOUR-GH-USERNAME>/<REPOSITORY-NAME>
$ git add .
$ git commit -m "Initial commit"
$ git branch -M main
$ git push -u origin main

​​ Deploy with Cloudflare Pages

Deploy your application to Pages:

  1. Log in to the Cloudflare dashboard and select your account.
  2. In Account Home, select Workers & Pages > Create application > Pages > Connect to Git.
  3. Select the new GitHub repository that you created and, in the Set up builds and deployments section, provide the following information:
Configuration optionValue
Production branchmain
Build commandnpm run build
Build directorybuild

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.