Click Below to Get the Code

Browse, clone, and build from real-world templates powered by Harper.
Tutorial
GitHub Logo

Getting Started with Harper’s Resource API

Learn how to build a full-stack Todo app using Harper’s Resource API, including schema-first data modeling, automatic REST API generation, custom backend logic, and seamless frontend integration for high-performance application development.
Tutorial

Getting Started with Harper’s Resource API

Austin Akers
Head of Developer Relations
at Harper
March 4, 2026
Austin Akers
Head of Developer Relations
at Harper
March 4, 2026
Austin Akers
Head of Developer Relations
at Harper
March 4, 2026
March 4, 2026
Learn how to build a full-stack Todo app using Harper’s Resource API, including schema-first data modeling, automatic REST API generation, custom backend logic, and seamless frontend integration for high-performance application development.
Austin Akers
Head of Developer Relations

Getting Started with Harper’s Resource API

Harper simplifies full-stack development by combining data modeling, API generation, and runtime execution into a single platform.

In this tutorial, we’ll build a simple Todo application while exploring how Harper’s Resource API allows you to model data and extend REST endpoints with custom logic.

By the end of this guide, you’ll understand how to:

  • Install and configure Harper locally
  • Run a Vite application inside Harper
  • Define a schema using a schema-first approach
  • Deploy a table
  • Extend that table using a custom Resource Class
  • Connect your frontend to Resource-backed REST endpoints

Overview

In this article, we will:

  1. Install and set up Harper locally
  2. Configure a Vite application to run inside Harper
  3. Define and deploy a GraphQL schema
  4. Create a custom Resource Class
  5. Connect our frontend to Harper’s REST endpoints
  6. Add backend validation logic

Install and Set Up Harper

Harper is installed via the harperdb CLI package.

Open your terminal and run:

npm install -g harperdb

Once installation completes, start Harper:

harper

The first time you run harper, you’ll be prompted to configure:

  • Destination – Where Harper will be installed on your machine
  • Username – Used to log into Harper Studio
  • Password – Used to log into Harper Studio
  • Configuration options

After completing setup, Harper will start locally.

Access Harper Studio

While Harper is running, navigate to:

http://localhost:9925/

Log in using the credentials you created during setup.

In Harper Studio, you’ll see:

  • Applications – Manage applications
  • Databases – Manage databases, tables, and records
  • APIs – View and test generated REST endpoints
  • Status – Monitor system metrics
  • Logs – View instance logs
  • Config – Manage roles and users

Application Setup

Before integrating Harper, clone the Todo example app:

git clone https://github.com/HarperFast/harper-todo-example

Then:

  1. Open the harper-todo-example/start/ folder in your editor
  2. Run:

npm install
npm run dev

  1. Navigate to:

http://localhost:5173/

The application runs — but:

  • It is not running inside Harper
  • It does not yet use Harper for CRUD operations

Let’s fix that.

Configuring the Application to Run Inside Harper

1. Install the Harper Vite Plugin

npm install -D @harperfast/vite-plugin

2. Update config.yaml

Add the plugin:

'@harperfast/vite-plugin':
 package: '@harperfast/vite-plugin'

3. Update package.json

Replace the dev script with:

"dev": "harper run ."

Restart the app:

npm run dev

Now navigate to:

http://localhost:9926/

Your application is now running inside Harper.

What Did We Just Do?

By running inside Harper, your application now benefits from:

  • Integrated database access
  • Automatic REST API generation
  • In-memory caching
  • Low-latency backend execution

Defining Our Table (Schema-First)

Harper uses a schema-first approach with GraphQL.

Open schema.graphql and add:

type TodoList @table {
 id: ID @primaryKey
 status: String @index
 description: String
}

This defines:

  • A table named TodoList
  • A primary key id
  • Indexed status
  • A description field

Deploy the Schema

Run:

harper deploy

In Harper Studio:

  • Navigate to Databases
  • Open the TodoList table

If no database exists, Harper automatically creates a default database named data.

Adding a Record (Testing)

In Harper Studio:

  1. Click + Add New Record(s)
  2. Replace the object with:

{
 "status": "active",
 "description": "finish todo app"
}

  1. Click Save Changes

Your first record is now stored.

Understanding Auto-Generated REST Endpoints

When you define a table, Harper automatically generates REST endpoints for it.

You can view and test them in:

Harper Studio → APIs

These endpoints allow standard CRUD operations.

However, what if we want to:

  • Validate input
  • Modify data before saving
  • Add business logic

That’s where the Resource Class comes in.

What Is the Resource Class?

The Resource Class extends a table and allows you to:

  • Intercept REST operations
  • Modify or validate data
  • Add custom logic
  • Restrict scope to a specific table

Instead of using the base Resource class (which can access all tables), we extend a specific table for better scope control.

Creating Our First Resource Class

Open resources.js.

By default, it looks like:

import { tables } from 'harperdb';

export class MyCustomResource extends tables.TableName {
 static loadAsInstance = false;
}

Update for TodoList

First, reference the table:

import { tables } from 'harperdb';

const TodoListTable = tables.TodoList;

Now create the Resource:

export class TodoListResource extends TodoListTable {
 static loadAsInstance = false;
}

This automatically creates a REST endpoint at:

/TodoListResource/

Fetching Todos

Open src/main.ts and locate fetchTodos():

todos = await fetch(`/TodoListResource/`)
 .then(res => res.json());

This fetches all records from the TodoList table via our Resource endpoint.

Updating Todo Status

To update a record, we use a PUT request:

await fetch(`/TodoListResource/${id}`, {
 method: 'PUT',
 headers: {
   'Content-Type': 'application/json',
 },
 body: JSON.stringify({
   description: todos.find(todo => todo.id === id)?.description,
   status: todos.find(todo => todo.id === id)?.status === "active"
     ? "completed"
     : "active",
 }),
});

Updating Todo Description

await fetch(`/TodoListResource/${id}`, {
 method: 'PUT',
 headers: {
   'Content-Type': 'application/json',
 },
 body: JSON.stringify({
   description: newText,
   status: todos.find(todo => todo.id === id)?.status,
 }),
});

Adding Backend Validation with the Resource Class

Now let’s trim the description before saving it.

Update resources.js:

export class TodoListResource extends TodoListTable {
 static loadAsInstance = false;

 put(target, taskItemData) {
   return super.put(target, {
     id: taskItemData.id,
     description: taskItemData.description.trim(),
     status: taskItemData.status
   });
 }

 post(target, taskItemData) {
   return super.post(target, {
     description: taskItemData.description.trim(),
     status: taskItemData.status
   });
 }
}

Now:

  • Descriptions are trimmed automatically
  • Validation logic lives on the backend
  • Frontend remains clean

Adding a New Todo

await fetch(`/TodoListResource/`, {
 method: 'POST',
 headers: {
   'Content-Type': 'application/json',
 },
 body: JSON.stringify({
   description: todoText,
   status: "active",
 }),
});

We do not provide an id — Harper automatically generates one.

Deleting a Todo

await fetch(`/TodoListResource/${id}`, {
 method: 'DELETE',
});

Conclusion

In this tutorial, we built a full-stack Todo application using Harper’s Resource API.

We demonstrated how to:

  • Run a frontend application inside Harper
  • Define a schema using a schema-first approach
  • Automatically generate REST endpoints
  • Extend those endpoints using a custom Resource Class
  • Add backend validation logic
  • Perform full CRUD operations

Harper enables a streamlined development experience by combining:

  • Data modeling
  • API generation
  • Runtime execution
  • Backend extensibility

—all within a single platform.

To explore more, visit:

https://www.harper.fast/

Getting Started with Harper’s Resource API

Harper simplifies full-stack development by combining data modeling, API generation, and runtime execution into a single platform.

In this tutorial, we’ll build a simple Todo application while exploring how Harper’s Resource API allows you to model data and extend REST endpoints with custom logic.

By the end of this guide, you’ll understand how to:

  • Install and configure Harper locally
  • Run a Vite application inside Harper
  • Define a schema using a schema-first approach
  • Deploy a table
  • Extend that table using a custom Resource Class
  • Connect your frontend to Resource-backed REST endpoints

Overview

In this article, we will:

  1. Install and set up Harper locally
  2. Configure a Vite application to run inside Harper
  3. Define and deploy a GraphQL schema
  4. Create a custom Resource Class
  5. Connect our frontend to Harper’s REST endpoints
  6. Add backend validation logic

Install and Set Up Harper

Harper is installed via the harperdb CLI package.

Open your terminal and run:

npm install -g harperdb

Once installation completes, start Harper:

harper

The first time you run harper, you’ll be prompted to configure:

  • Destination – Where Harper will be installed on your machine
  • Username – Used to log into Harper Studio
  • Password – Used to log into Harper Studio
  • Configuration options

After completing setup, Harper will start locally.

Access Harper Studio

While Harper is running, navigate to:

http://localhost:9925/

Log in using the credentials you created during setup.

In Harper Studio, you’ll see:

  • Applications – Manage applications
  • Databases – Manage databases, tables, and records
  • APIs – View and test generated REST endpoints
  • Status – Monitor system metrics
  • Logs – View instance logs
  • Config – Manage roles and users

Application Setup

Before integrating Harper, clone the Todo example app:

git clone https://github.com/HarperFast/harper-todo-example

Then:

  1. Open the harper-todo-example/start/ folder in your editor
  2. Run:

npm install
npm run dev

  1. Navigate to:

http://localhost:5173/

The application runs — but:

  • It is not running inside Harper
  • It does not yet use Harper for CRUD operations

Let’s fix that.

Configuring the Application to Run Inside Harper

1. Install the Harper Vite Plugin

npm install -D @harperfast/vite-plugin

2. Update config.yaml

Add the plugin:

'@harperfast/vite-plugin':
 package: '@harperfast/vite-plugin'

3. Update package.json

Replace the dev script with:

"dev": "harper run ."

Restart the app:

npm run dev

Now navigate to:

http://localhost:9926/

Your application is now running inside Harper.

What Did We Just Do?

By running inside Harper, your application now benefits from:

  • Integrated database access
  • Automatic REST API generation
  • In-memory caching
  • Low-latency backend execution

Defining Our Table (Schema-First)

Harper uses a schema-first approach with GraphQL.

Open schema.graphql and add:

type TodoList @table {
 id: ID @primaryKey
 status: String @index
 description: String
}

This defines:

  • A table named TodoList
  • A primary key id
  • Indexed status
  • A description field

Deploy the Schema

Run:

harper deploy

In Harper Studio:

  • Navigate to Databases
  • Open the TodoList table

If no database exists, Harper automatically creates a default database named data.

Adding a Record (Testing)

In Harper Studio:

  1. Click + Add New Record(s)
  2. Replace the object with:

{
 "status": "active",
 "description": "finish todo app"
}

  1. Click Save Changes

Your first record is now stored.

Understanding Auto-Generated REST Endpoints

When you define a table, Harper automatically generates REST endpoints for it.

You can view and test them in:

Harper Studio → APIs

These endpoints allow standard CRUD operations.

However, what if we want to:

  • Validate input
  • Modify data before saving
  • Add business logic

That’s where the Resource Class comes in.

What Is the Resource Class?

The Resource Class extends a table and allows you to:

  • Intercept REST operations
  • Modify or validate data
  • Add custom logic
  • Restrict scope to a specific table

Instead of using the base Resource class (which can access all tables), we extend a specific table for better scope control.

Creating Our First Resource Class

Open resources.js.

By default, it looks like:

import { tables } from 'harperdb';

export class MyCustomResource extends tables.TableName {
 static loadAsInstance = false;
}

Update for TodoList

First, reference the table:

import { tables } from 'harperdb';

const TodoListTable = tables.TodoList;

Now create the Resource:

export class TodoListResource extends TodoListTable {
 static loadAsInstance = false;
}

This automatically creates a REST endpoint at:

/TodoListResource/

Fetching Todos

Open src/main.ts and locate fetchTodos():

todos = await fetch(`/TodoListResource/`)
 .then(res => res.json());

This fetches all records from the TodoList table via our Resource endpoint.

Updating Todo Status

To update a record, we use a PUT request:

await fetch(`/TodoListResource/${id}`, {
 method: 'PUT',
 headers: {
   'Content-Type': 'application/json',
 },
 body: JSON.stringify({
   description: todos.find(todo => todo.id === id)?.description,
   status: todos.find(todo => todo.id === id)?.status === "active"
     ? "completed"
     : "active",
 }),
});

Updating Todo Description

await fetch(`/TodoListResource/${id}`, {
 method: 'PUT',
 headers: {
   'Content-Type': 'application/json',
 },
 body: JSON.stringify({
   description: newText,
   status: todos.find(todo => todo.id === id)?.status,
 }),
});

Adding Backend Validation with the Resource Class

Now let’s trim the description before saving it.

Update resources.js:

export class TodoListResource extends TodoListTable {
 static loadAsInstance = false;

 put(target, taskItemData) {
   return super.put(target, {
     id: taskItemData.id,
     description: taskItemData.description.trim(),
     status: taskItemData.status
   });
 }

 post(target, taskItemData) {
   return super.post(target, {
     description: taskItemData.description.trim(),
     status: taskItemData.status
   });
 }
}

Now:

  • Descriptions are trimmed automatically
  • Validation logic lives on the backend
  • Frontend remains clean

Adding a New Todo

await fetch(`/TodoListResource/`, {
 method: 'POST',
 headers: {
   'Content-Type': 'application/json',
 },
 body: JSON.stringify({
   description: todoText,
   status: "active",
 }),
});

We do not provide an id — Harper automatically generates one.

Deleting a Todo

await fetch(`/TodoListResource/${id}`, {
 method: 'DELETE',
});

Conclusion

In this tutorial, we built a full-stack Todo application using Harper’s Resource API.

We demonstrated how to:

  • Run a frontend application inside Harper
  • Define a schema using a schema-first approach
  • Automatically generate REST endpoints
  • Extend those endpoints using a custom Resource Class
  • Add backend validation logic
  • Perform full CRUD operations

Harper enables a streamlined development experience by combining:

  • Data modeling
  • API generation
  • Runtime execution
  • Backend extensibility

—all within a single platform.

To explore more, visit:

https://www.harper.fast/

Learn how to build a full-stack Todo app using Harper’s Resource API, including schema-first data modeling, automatic REST API generation, custom backend logic, and seamless frontend integration for high-performance application development.

Download

White arrow pointing right
Learn how to build a full-stack Todo app using Harper’s Resource API, including schema-first data modeling, automatic REST API generation, custom backend logic, and seamless frontend integration for high-performance application development.

Download

White arrow pointing right
Learn how to build a full-stack Todo app using Harper’s Resource API, including schema-first data modeling, automatic REST API generation, custom backend logic, and seamless frontend integration for high-performance application development.

Download

White arrow pointing right

Explore Recent Resources

Blog
GitHub Logo

The Nearstore Agent: a reference pattern for low-latency, geofenced, promotional decisions

Build a real-time, geofenced promo engine on Harper's agentic runtime. The Nearstore Agent collapses geofence lookup, customer data, campaigns, and AI decisions into a single process. Clone the reference repo and deploy in minutes.
Blog
Build a real-time, geofenced promo engine on Harper's agentic runtime. The Nearstore Agent collapses geofence lookup, customer data, campaigns, and AI decisions into a single process. Clone the reference repo and deploy in minutes.
Person with short dark hair and moustache, wearing a colorful plaid shirt, smiling outdoors in a forested mountain landscape.
Aleks Haugom
Senior Manager of GTM
Blog

The Nearstore Agent: a reference pattern for low-latency, geofenced, promotional decisions

Build a real-time, geofenced promo engine on Harper's agentic runtime. The Nearstore Agent collapses geofence lookup, customer data, campaigns, and AI decisions into a single process. Clone the reference repo and deploy in minutes.
Aleks Haugom
Apr 2026
Blog

The Nearstore Agent: a reference pattern for low-latency, geofenced, promotional decisions

Build a real-time, geofenced promo engine on Harper's agentic runtime. The Nearstore Agent collapses geofence lookup, customer data, campaigns, and AI decisions into a single process. Clone the reference repo and deploy in minutes.
Aleks Haugom
Blog

The Nearstore Agent: a reference pattern for low-latency, geofenced, promotional decisions

Build a real-time, geofenced promo engine on Harper's agentic runtime. The Nearstore Agent collapses geofence lookup, customer data, campaigns, and AI decisions into a single process. Clone the reference repo and deploy in minutes.
Aleks Haugom
Blog
GitHub Logo

How a Shopify Custom Tie Shop Exposes a Common Flaw in Agent Architecture

Explore how a Shopify-based custom tie shop reveals a critical flaw in one LLM agent design strategy, and why context-first architectures with unified runtimes deliver faster, more accurate, and scalable customer support automation.
Blog
Explore how a Shopify-based custom tie shop reveals a critical flaw in one LLM agent design strategy, and why context-first architectures with unified runtimes deliver faster, more accurate, and scalable customer support automation.
Person with short dark hair and moustache, wearing a colorful plaid shirt, smiling outdoors in a forested mountain landscape.
Aleks Haugom
Senior Manager of GTM
Blog

How a Shopify Custom Tie Shop Exposes a Common Flaw in Agent Architecture

Explore how a Shopify-based custom tie shop reveals a critical flaw in one LLM agent design strategy, and why context-first architectures with unified runtimes deliver faster, more accurate, and scalable customer support automation.
Aleks Haugom
Apr 2026
Blog

How a Shopify Custom Tie Shop Exposes a Common Flaw in Agent Architecture

Explore how a Shopify-based custom tie shop reveals a critical flaw in one LLM agent design strategy, and why context-first architectures with unified runtimes deliver faster, more accurate, and scalable customer support automation.
Aleks Haugom
Blog

How a Shopify Custom Tie Shop Exposes a Common Flaw in Agent Architecture

Explore how a Shopify-based custom tie shop reveals a critical flaw in one LLM agent design strategy, and why context-first architectures with unified runtimes deliver faster, more accurate, and scalable customer support automation.
Aleks Haugom
Blog
GitHub Logo

Nobody Wants to Pick a Data Center (And They Shouldn't Have To)

Harper Fabric simplifies cloud deployment by eliminating the need to choose data centers, automating infrastructure, scaling, and global distribution. Built for Harper’s unified runtime, it enables developers to deploy high-performance, distributed applications quickly without managing complex cloud configurations or infrastructure overhead.
Blog
Harper Fabric simplifies cloud deployment by eliminating the need to choose data centers, automating infrastructure, scaling, and global distribution. Built for Harper’s unified runtime, it enables developers to deploy high-performance, distributed applications quickly without managing complex cloud configurations or infrastructure overhead.
Headshot of a smiling woman with shoulder-length dark hair wearing a black sweater with white stripes and a gold pendant necklace, standing outdoors with blurred trees and mountains in the background.
Bari Jay
Senior Director of Product Management
Blog

Nobody Wants to Pick a Data Center (And They Shouldn't Have To)

Harper Fabric simplifies cloud deployment by eliminating the need to choose data centers, automating infrastructure, scaling, and global distribution. Built for Harper’s unified runtime, it enables developers to deploy high-performance, distributed applications quickly without managing complex cloud configurations or infrastructure overhead.
Bari Jay
Apr 2026
Blog

Nobody Wants to Pick a Data Center (And They Shouldn't Have To)

Harper Fabric simplifies cloud deployment by eliminating the need to choose data centers, automating infrastructure, scaling, and global distribution. Built for Harper’s unified runtime, it enables developers to deploy high-performance, distributed applications quickly without managing complex cloud configurations or infrastructure overhead.
Bari Jay
Blog

Nobody Wants to Pick a Data Center (And They Shouldn't Have To)

Harper Fabric simplifies cloud deployment by eliminating the need to choose data centers, automating infrastructure, scaling, and global distribution. Built for Harper’s unified runtime, it enables developers to deploy high-performance, distributed applications quickly without managing complex cloud configurations or infrastructure overhead.
Bari Jay
Blog
GitHub Logo

New RocksDB Binding for Node.js

rocksdb-js is a modern Node.js binding for RocksDB, offering full transaction support, lazy range queries, and a TypeScript API. Built for performance and scalability, it enables reliable write-heavy workloads, real-time replication, and high-concurrency applications in Harper 5.0 and beyond.
Blog
rocksdb-js is a modern Node.js binding for RocksDB, offering full transaction support, lazy range queries, and a TypeScript API. Built for performance and scalability, it enables reliable write-heavy workloads, real-time replication, and high-concurrency applications in Harper 5.0 and beyond.
Person with short hair and rectangular glasses wearing a plaid shirt over a dark T‑shirt, smiling broadly with a blurred outdoor background of trees and hills.
Chris Barber
Staff Software Engineer
Blog

New RocksDB Binding for Node.js

rocksdb-js is a modern Node.js binding for RocksDB, offering full transaction support, lazy range queries, and a TypeScript API. Built for performance and scalability, it enables reliable write-heavy workloads, real-time replication, and high-concurrency applications in Harper 5.0 and beyond.
Chris Barber
Apr 2026
Blog

New RocksDB Binding for Node.js

rocksdb-js is a modern Node.js binding for RocksDB, offering full transaction support, lazy range queries, and a TypeScript API. Built for performance and scalability, it enables reliable write-heavy workloads, real-time replication, and high-concurrency applications in Harper 5.0 and beyond.
Chris Barber
Blog

New RocksDB Binding for Node.js

rocksdb-js is a modern Node.js binding for RocksDB, offering full transaction support, lazy range queries, and a TypeScript API. Built for performance and scalability, it enables reliable write-heavy workloads, real-time replication, and high-concurrency applications in Harper 5.0 and beyond.
Chris Barber
Blog
GitHub Logo

Open Sourcing Harper

Harper is now open source, with its core platform released under Apache 2.0 and enterprise features source-available. This shift builds trust, enables community contributions, and positions Harper as a unified, transparent platform for developers and AI-driven applications.
Blog
Harper is now open source, with its core platform released under Apache 2.0 and enterprise features source-available. This shift builds trust, enables community contributions, and positions Harper as a unified, transparent platform for developers and AI-driven applications.
Person with shoulder‑length curly brown hair and light beard wearing a gray long‑sleeve shirt, smiling outdoors with trees and greenery in the background.
Ethan Arrowood
Senior Software Engineer
Blog

Open Sourcing Harper

Harper is now open source, with its core platform released under Apache 2.0 and enterprise features source-available. This shift builds trust, enables community contributions, and positions Harper as a unified, transparent platform for developers and AI-driven applications.
Ethan Arrowood
Apr 2026
Blog

Open Sourcing Harper

Harper is now open source, with its core platform released under Apache 2.0 and enterprise features source-available. This shift builds trust, enables community contributions, and positions Harper as a unified, transparent platform for developers and AI-driven applications.
Ethan Arrowood
Blog

Open Sourcing Harper

Harper is now open source, with its core platform released under Apache 2.0 and enterprise features source-available. This shift builds trust, enables community contributions, and positions Harper as a unified, transparent platform for developers and AI-driven applications.
Ethan Arrowood