---
description: This tutorial builds a full-stack Pages application using the React framework.
title: Build an API for your front end using Pages Functions
image: https://developers.cloudflare.com/og-docs.png
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/pages/llms.txt  
> Use this file to discover all available pages before exploring further.

# Build an API for your front end using Pages Functions

Last updated Aug 24, 2026|Copy as Markdown|[View as Markdown](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/pages/tutorials/build-an-api-with-pages-functions/index.md)|[Agent setup](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/agent-setup/)

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](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/pages/framework-guides/deploy-a-react-site/).
* A JSON API, built with [Pages Functions](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/pages/functions/get-started/), 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](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/pages/tutorials/build-a-blog-using-nuxt-and-sanity/).

## Video Tutorial

## 1\. 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-vite` command. Go into the newly created `blog-frontend` directory and start a local development server:

```sh
npx create-vite -t react blog-frontend
cd blog-frontend
npm install
npm run dev
```

### Set up your React project

To set up your React project:

1. Install the [React Router ↗](https://reactrouter.com/en/main/start/tutorial) in the root of your `blog-frontend` directory.

npmyarnpnpmbun

```
npm i react-router-dom@6
```

```
yarn add react-router-dom@6
```

```
pnpm add react-router-dom@6
```

```
bun add react-router-dom@6
```

s 
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:

```js
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;
```

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:

```js
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;
```

1. Populate `post.js` with the following code:

```js
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;
```

## 2\. 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:

```js
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.

```js
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:

```js
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](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/pages/functions/routing#dynamic-routes) which is used to accept a blog post `id`.

## 3\. 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](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/workers/wrangler/commands/general/#deploy) to deploy your project to the Cloudflare dashboard.

```sh
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 [repo.new ↗](https://repo.new). After creating a new repository, prepare and push your local application to GitHub by running the following commands in your terminal:

```sh
git init
git remote add origin https://github.com/<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. In the Cloudflare dashboard, go to the **Workers & Pages** page.  
[Go to **Workers & Pages** ↗](https://dash.cloudflare.com/?to=/:account/workers-and-pages)
2. Select **Create application** \> **Pages** \> **Import an existing Git repository**.
3. 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.

## Related resources

* Learn about [Pages Functions routing](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/pages/functions/routing)

Was this helpful?

YesNo

## On this page

[![](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/pages/tutorials/build-an-api-with-pages-functions/#page","headline":"Build an API for your front end using Pages Functions · Cloudflare Pages docs","description":"This tutorial builds a full-stack Pages application using the React framework.","url":"https://developers.cloudflare.com/pages/tutorials/build-an-api-with-pages-functions/","inLanguage":"en","image":"https://developers.cloudflare.com/og-docs.png","dateModified":"2026-08-24","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["JavaScript"]}
```
