Next.js - Read/Write Data to JSON Files as the Database

Tutorial built with Next.js 11.1.0

This is a quick post to show how to manage (read/write) data in a JSON flat file with Next.js, it's useful for building example apps or for when you need to get up and running quickly before setting up a full database such as MongoDB, MySQL, SQL Server etc.

The below code snippets are taken from a Next.js login tutorial I posted recently, for the full tutorial or to download and test the code locally see Next.js 11 - User Registration and Login Tutorial with Example App.

To keep the Next.js tutorial as simple as possible, instead of a database it stores user data in a JSON flat file located at /data/users.json, the data is accessed and managed via the users repo which supports all basic CRUD operations.


Users JSON Data File

Path: /data/users.json

A JSON file containing user data for the Next.js tutorial app, the data is accessed and managed via the users repo which supports all basic CRUD operations. The file contains an empty array ([]) by default which is first populated when a new user is registered.


Users Repo to Read/Write JSON File

Path: /helpers/users-repo.js

The users repo encapsulates all read/write access to the users JSON data file and exposes a standard set of CRUD methods for reading and managing the data. It's used on the server-side by the Next.js users API route handlers (e.g. the register route handler).

const fs = require('fs');

// users in JSON file for simplicity, store in a db for production applications
let users = require('data/users.json');

export const usersRepo = {
    getAll: () => users,
    getById: id => users.find(x => === id.toString()),
    find: x => users.find(x),
    delete: _delete

function create(user) {
    // generate new user id = users.length ? Math.max( => + 1 : 1;

    // set date created and updated
    user.dateCreated = new Date().toISOString();
    user.dateUpdated = new Date().toISOString();

    // add and save user

function update(id, params) {
    const user = users.find(x => === id.toString());

    // set date updated
    user.dateUpdated = new Date().toISOString();

    // update and save
    Object.assign(user, params);

// prefixed with underscore '_' because 'delete' is a reserved word in javascript
function _delete(id) {
    // filter out deleted user and save
    users = users.filter(x => !== id.toString());

// private helper functions

function saveData() {
    fs.writeFileSync('data/users.json', JSON.stringify(users, null, 4));

Register API Route Handler

Path: /pages/api/users/register.js

The register handler receives HTTP requests sent to the register route /api/users/register. It supports HTTP POST requests containing user details which are registered in the Next.js app by the register() function.

The register() function uses the usersRepo.find() method to validate that the username is unique, and the usersRepo.create() method to save the user details to the JSON data file. On successful registration a 200 OK response is returned with an empty JSON object.

The route handler supports HTTP POST requests by passing an object with a post() method to the apiHandler() wrapper function. For more info on the API handler wrapper function see the full tutorial linked at the top of the post.

const bcrypt = require('bcryptjs');

import { apiHandler, usersRepo } from 'helpers/api';

export default apiHandler({
    post: register

function register(req, res) {
    // split out password from user details 
    const { password, ...user } = req.body;

    // validate
    if (usersRepo.find(x => x.username === user.username))
        throw `User with the username "${user.username}" already exists`;

    // hash password
    user.hash = bcrypt.hashSync(password, 10);    

    return res.status(200).json({});


Subscribe or Follow Me For Updates

Subscribe to my YouTube channel or follow me on Twitter, Facebook or GitHub to be notified when I post new content.

Other than coding...

I'm currently attempting to travel around Australia by motorcycle with my wife Tina on a pair of Royal Enfield Himalayans. You can follow our adventures on YouTube, Instagram and Facebook.

Need Some NextJS Help?

Search fiverr to find help quickly from experienced NextJS developers.

Supported by