Next.js application code
Create the add product page (Frontend)
Create a new front-end page to add data to your database. Create a new file pages/add-products.js
in your project and add the following code to it.
import { useState } from 'react';
export default function AddProducts() {
const [state, setState] = useState({
title: '',
price: '',
description: '',
});
const handleChange = (e) => {
const { name, value } = e.target;
setState({ ...state, [name]: value });
};
const submitForm = async (e) => {
e.preventDefault();
// Make a API call to create a product
await fetch('/api/products', {
method: 'POST',
body: JSON.stringify(state),
});
setState({
title: '',
price: '',
description: '',
});
}
return (
<div className="container">
<h1>Add Products</h1>
<form onSubmit={submitForm}>
<label htmlFor="title">Title</label>
<input type="text" name="title" value={state.title} onChange={handleChange}/>
<br />
<label htmlFor="price">Price</label>
<input type="number" name="price" value={state.price} onChange={handleChange}/>
<br />
<label htmlFor="description" >Description</label>
<textarea name="description" value={state.description} onChange={handleChange}/>
<br />
<button type="submit">Add Product</button>
</form>
</div>
);
}
In the previous code block you have a simple form component to add products. On form submit it calls the /api/products
api routes.
Run the application locally with the following command.
$ npm run dev
Visit http://localhost:3000/add-products
and try to create a new product.
Notice, when you submit the form it gives you a 404 not found error. This is because the api route for api/products
doesn’t exist yet. Let’s go ahead and create the API route next.
Create the api route to add product (Backend)
Create a new file pages/api/products.js
and add the following code to the file.
// pages/api/products.js
export const config = {
runtime: 'experimental-edge',
}
export default async function (req) {
if(req.method === 'POST') {
const { title, price, description } = req.body;
// Save the product to the database
// TODO: Add Database Code here
return new Response(
JSON.stringify({ message: 'Product created successfully' }),
{
status: 200,
headers: {
'Content-Type': 'application/json'
}
}
)
}
}
Try creating a new product from the add-products
page again. Open the network tab in your browser and notice that on form submit you will not get a 404 error anymore.
Reading data from request body in Edge Runtime
The Next.js Edge Runtime is based on standard Web APIs. This is slightly different than the default Node.js-powered API route. The request body for Edge Runtime gives you a ReadableStream. You have to decode this to read the request body.
Make the following changes to your pages/api/products.js
file to read the request body data.
export const config = {
runtime: 'experimental-edge',
}
export default async function (req) {
if(req.method === 'POST') {
const body = await readRequestBodyStream(req.body);
const { title, price, description } = JSON.parse(body);
// TODO: Save the product to the database
return new Response(
JSON.stringify({
message: 'Product created successfully'
}),
{
status: 200,
headers: {
'Content-Type': 'application/json'
}
}
)
}
}
async function readRequestBodyStream(body) {
const reader = body.getReader();
let result = new Uint8Array(0);
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
const newResult = new Uint8Array(result.length + value.length);
newResult.set(result);
newResult.set(value, result.length);
result = newResult;
}
return new TextDecoder().decode(result);
}
However, this is not saving the data in our database yet. Next, let’s add the code for database operation.
Adding database operations
install the fauna package in your project by running the following command.
$ npm i faunadb --save
Next, create a new file called db.js
and add the following code.
// db.js
import fauna from 'faunadb';
const q = fauna.query;
const client = new fauna.Client({ secret: process.env.FAUNA_SECRET });
export const createProduct = async (title, price, description) => {
const product = {
data: {
title,
price,
description,
},
};
return client.query(q.Create(q.Collection('Products'), product));
};
You can import the createProduct
function into your Edge runtime and execute it to create a new database record.
// partials of pages/api/products.js
import { createProduct } from '../../db'
// ...
export default async function (req) {
if(req.method === 'POST') {
const body = await readRequestBodyStream(req.body);
const { title, price, description } = JSON.parse(body);
// Save the product to the database
const product = await createProduct(title, price, description);
return new Response(
JSON.stringify({
message: 'Product created successfully',
product: {
id: product.ref.id,
title,
price,
description,
},
}),
{
status: 200,
headers: {
'Content-Type': 'application/json'
}
}
)
}
}
// ... Rest of the file
Retrieve Products API
Next, go ahead and create new database function to retrieve all the products. Add the following function to your db.js
file.
// db.js
// ... Rest of file
export const getProducts = async () => {
const response = await client.query(
q.Map(
q.Paginate(q.Documents(q.Collection('Products'))),
q.Lambda(x => q.Get(x))
)
);
const products = response.data.map((product) => ({ ...product.data, _id: product.ref.id }));
return products;
}
Make the following changes in your pages/index.js
to retrieve all the products.
import styles from '../styles/Home.module.css'
import { getProducts } from '../db';
export const config = {
runtime: 'experimental-edge',
}
export async function getServerSideProps() {
const fauna_secret = process.env.FAUNA_SECRET;
const products = await getProducts();
return {
props: {
products,
fauna_secret
},
}
}
export default function Home({ products, fauna_secret }) {
return (
<div className={styles.container}>
<h1>Products</h1>
<ul>
{
products.map((product) => (
<li key={product._id}>
<h2>{product.title}</h2>
<p>{product.description}</p>
<p>{product.price}</p>
</li>
))
}
</ul>
</div>
)
}
Global Application Benchmark
Go to https://www.webpagetest.org/ and paste in your website url to check the performance of your global application. You can pick up various global location and network speed.
For this simple application, the page resolves in less 15ms on average from different servers across the globe.
The compute and database operations are almost the same across the globe. The powerful combination of Cloudflare CDN, workers and Fauna database allow your code and data to run closer to your end user reducing application latency globally.