Skip to main content

Overview

Codehooks: APIs and Automations made simpleโ€‹

Codehooks provides powerful tools for developers to build, connect, and process APIs with ease. Create projects using our intuitive command line interface or web-based admin UI.

A Codehooks.io project contains one or more isolated Spaces - Spaces are complete self-contained environments with their own database, settings, and code.

The codehooks-js library is the foundation for all Codehooks JavaScript development, offering a comprehensive set of 8 specialized APIs that accelerate development, streamline data integration, and simplify data processing. Explore each capability below to see how Codehooks can improve your development experience.

Start Building in Minutes

Get up to speed fast with these essential resources:

API development
REST, CRUD or custom APIs
NoSQL & Key-Value
Code triggered by CRON
Long running processes
Build Reliable Workflows
File System
Serve static files
Data Aggregation
Groups & sums
Let codehooks serve your frontend

If you're like most developers (i.e. smart and lazy ๐Ÿ˜‰), we've added a ChatGPT and LLM Prompt you can use to kickstart new projects. The prompt itself is worth looking at to get an overview of the features of the codehooks-js library. Our new MCP Server implementation has this prompt built-in.

Codehooks CLI tool

To deploy code (and much more), you use the Codehooks CLI tool:

npm install codehooks -g

Code editing and deployment can also be done from the web based UI.

API developmentโ€‹

Get a flying start with an automatic CRUD REST API

Consider a Codehooks project, for example myproject-fafb. Under the hood, Codehooks deploys an automatic REST API which is made up of the following really short - but complete application code:
import {app} from 'codehooks-js'
// Use Crudlify to create a REST API for any database collection
app.crudlify()
// bind to serverless runtime
export default app.init();
It's just 3 lines of code ๐Ÿ”ฅ, and it delivers a fully secure CRUD REST API with a NoSQL database for JSON queries and updates. Client apps can instantly connect to your data API, for example from a JavaScript app like the example code snippet shown below:
const URL = 'https://myproject-fafb.api.codehooks.io/dev/orders';
response = await fetch(URL+'?status=OPEN', /* options */)
const result = await response.json()

NoSQL and Key-Value Datastoresโ€‹

Easy database API inspired by MongoDB

Sometimes a standard CRUD REST API isn't enough. With custom JavaScript functions you can create logic that integrates directly to the NoSQL datastore. No need to think about drivers, versions, protocol or security, the database is just there, available as an intrinsic object in every serverless function.
import {app, datastore} from 'codehooks-js'
// REST API route
app.get('/sales', async (req, res) => {
const conn = await datastore.open();
const query = { status: "OPEN" };
const options = { sort: { date: 1 } }
conn.getMany('orders', query, options).json(res); // stream JSON to client
})
// bind to serverless runtime
export default app.init();

Speed up your application with a Key-Value cache

The Codehooks data engine includes a simple key-value datastore. A key-value datastore has many use-cases, and is ideal for caching due to the swift data access and simple, maintenance-friendly architecture. A simple example is shown below, where a string is stored for 60 seconds with the ttl option.
import {app, datastore} from 'codehooks-js'
// REST API route
app.post('/cacheit', async (req, res) => {
const conn = await datastore.open();
const opt = {ttl: 60*1000};
await conn.set('my_cache_key', '1 min value', opt);
res.send('Look dad, I have my own cache now!');
})
// bind to serverless runtime
export default app.init();

Background Jobsโ€‹

CRON expressions + your function keeps running

Use simple CRON expressions to automate and manage the execution of routine tasks. You can schedule a job to run at multiple, disparate times. For example, you can schedule a task to run at 2 AM on Sundays and 4 PM on Wednesdays with the same CRON job.

In the simple example below, the CRON expression */5 * * * * will trigger a JavaScript function each 5 minutes.

import app from 'codehooks-js'
// Trigger a function with a CRON expression
app.job('*/5 * * * *', (_, job) => {
console.log('Hello every 5 minutes')
// Do stuff ...
job.end()
});
export default app.init();

Queuesโ€‹

Scale workloads with queues and worker functions

Use persistent queues and "worker" functions to create robust, efficient, and highly responsive back-end systems. Queues scales processing across multiple nodes and will restore and continue working in case of errors and system failures.
Check out the example below, where a REST API request starts a complex task by adding it to the Queue for later processing.
import { app, Datastore } from 'codehooks-js'

// register a Queue task worker
app.worker('ticketToPDF', (req, res) => {
const { email, ticketid } = req.body.payload;
//TODO: implement code to fetch ticket data, produce PDF
// and send email with attachment using Mailgun, Sendgrid or Amazon SES
// ...and implement error handling
res.end(); // done processing queue item
})

// REST API
app.post('/createticket', async (req, res) => {
const { email, ticketid } = req.body;
const conn = await Datastore.open();
await conn.enqueue("ticketToPDF", { email, ticketid });
res.status(201).json({"message": `Check email ${email}`});
})

export default app.init();

Reliable Workflowsโ€‹

Build reliable stateful workflows

Create and deploy robust, scalable workflows using queued functions and state management. Build reliable backend systems with automatic retry, state persistence, and distributed processing.

The example below shows a simple workflow that processes customer onboarding with email validation.
import { app } from 'codehooks-js';
// define the workflow
const workflow = app.createWorkflow('customerOnboarding', 'Customer signup and email validation', {
START: async function (state, goto) {
state = { email: state.email, validated: false };
await sendWelcomeEmail(state.email);
goto('waitForValidation', state);
},
waitForValidation: async function (state, goto) {
if (state.validated) {
goto('complete', state);
} else {
wait({wait_message: 'Waiting for subflow to complete'});
}
},
complete: function (state, goto) {
state.status = 'completed';
goto(null, state); // workflow complete
}
});
// Start workflow from REST API
app.post('/start-onboarding', async (req, res) => {
const result = await workflow.start({ email: req.body.email });
res.send(result);
});

export default app.init();

Blob Storage APIโ€‹

Store and manage files programmatically

Codehooks provides a built-in blob storage system for uploading, storing, and serving files through your applications. Use the File API to handle file operations programmatically in your serverless functions. You can upload files to blob storage using the CLI command:
$ coho file-upload --projectname 'myproject-fafc' --space 'dev' --src '/somedir/' --target '/myblobs'
The example below shows how to handle file uploads, downloads, and management through the File API in your application code:
import {app} from 'codehooks-js'

// serve a direcory of Blob storage files
app.storage({route:"/documents", directory: "/myblobs"})

// CRUD REST API
app.crudlify()
// bind to serverless runtime
export default app.init();

Data Aggregationโ€‹

Easy to use data aggregation format

Transform your live data streams into insights with just a few lines of code. Codehooks has a simple but powerful JSON-based aggregation expression language to specify data transformations. Groups and sums can be nested to create both simple and advanced data outputs. The aggregation API can process input from any JSON data-stream, for example the query output from the NoSQL datastore. ๐Ÿ”ฅ
import { app, Datastore, aggregation } from 'codehooks-js'
... // collapsed code
const spec = {
$group: {
$field: "month",
$max: ["sales", "winback"],
$sum: "sales"
}
}
const db = await datastore.open();
const dbstream = db.getMany('salesData');
const result = await aggregation(dbstream, spec)
... // collapsed code
The example aggreagation transformation produces JSON output similar to the example below.
{
"oct": {
"sales": {
"max": 1477.39,
"sum": 1234.05
},
"winback": {
"max": 22.0
}
},
"nov": {
"sales": {
"max": 2357.00,
"sum": 5432.00
},
"winback": {
"max": 91.0
}
},
}

Frontend Hosting Setupโ€‹

Host your frontend applications alongside your API

There are several benefits to hosting the frontend along with the backend API:
  • No CORS issues - Frontend and API share the same domain
  • Simplified deployment - Single command deploys both frontend and backend
  • Cost effective - No need for separate hosting services
Codehooks can serve your frontend applications as static assets, making it easy to deploy full-stack SPA and PWA applications from a single codebase. All you need to do is to include the HTML and CSS files in the source code and then use the app.static file handler to serve them along with the backend code. This hosting option is perfect if you don't need the high scalability offered by CDN-hosted frontends.
Important: Codehooks only serves static assets, not server-side rendered content. For frameworks like Next.js, Nuxt and SvelteKit, you must configure them for static generation/export (SSG).
Simply copy your framework's build or dist folder into your Codehooks project source and configure the static handler to serve it. When you run codehooks deploy, both your API and your frontend will be deployed:
import {app} from 'codehooks-js'
// serve /dist for react frontend
app.static({
route: '/',
directory: '/dist',
default: 'index.html',
notFound: '/index.html'
}, cacheFunction)
// Optionally define cache function for static assets
function cacheFunction(req, res, next) {
const ONE_DAY = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
res.set('Cache-Control', `public, max-age=${ONE_DAY}, s-maxage=${ONE_DAY}`)
res.set('Expires', new Date(Date.now() + ONE_DAY).toUTCString())
res.removeHeader('Pragma');
next()
}
// CRUD REST API (if you need it)
app.crudlify({}, {prefix: '/api'})
// bind to serverless runtime
export default app.init();
Note: The default and notFound settings are crucial for client-side routing. They ensure that all routes (like /about or /users/123) serve the index.html file, allowing your frontend router to handle navigation instead of the server returning 404 errors.
This setup works seamlessly with popular frameworks configured for static builds:
  • Pure HTML/CSS: Just keep the source with backend code from the start (in the dist/ folder in this example)
  • React: Copy your build/ folder (after npm run build)
  • Vue: Copy your dist/ folder (after npm run build)
  • Next.js: Configure static export (next export), then copy your out/ folder
  • Nuxt: Configure static generation (nuxt generate), then copy your dist/ folder
  • Svelte: Copy your build/ folder (after npm run build)
  • SvelteKit: Configure static adapter, then copy your build/ folder
  • Angular: Copy your dist/ folder (after ng build)
  • Astro: Copy your dist/ folder (after npm run build)
  • Gatsby: Copy your public/ folder (after gatsby build)
We recommend automating this step by setting your frontend framework's output directory to point directly to your backend source folder. This eliminates the manual copy step in your deployment workflow.
Example with Vite (in vite.config.js):
export default {
build: {
outDir: '../backend-src/dist', // Points to your codehooks source folder
},
};
Authentication
The example shown here is without any authentication. For most useful applications you would need to set up your frontend to use an authentication framework (Clerk, Auth0, Stack-Auth, codehooks-auth).

Next Stepsโ€‹

Read this far? Great ๐Ÿ™Œ

It's time to get your feet wet ๐Ÿ’ฆ. Why don't you start thinking about how codehooks' toolbox can help you build your solution. You can get started with the quickstart for developers or just sign up and create your project and space using the web UI. You can easily upload some CSV data and immediately test your new API.

The documentation or tutorials are great places to start. If you need more help, feel free to contact us on the chat.