A Hono REST API in one Function, on your own database
A Hono REST API with six routes for customers and their orders, checked with zod. The data lives in your own Supabase tables, and the whole API deploys and rolls back as one unit.
You want a REST API, not one deploy per route
On many platforms each route is its own function, with its own version and its own rollback. Here one Function gets every path under its address. All six routes ship together, and the data they write stays in a database you own.
The whole template is public. Read it before you trust it.
Or scaffold it
$ npx wawesome init --template rest-api
$ npx wawesome deployWhat you get
A Function called customers that answers six routes:
GET / list the customers
POST / create one
GET /:id read one
PUT /:id replace one
DELETE /:id delete one
GET /:id/orders list one customer's orders
The routes are in src/index.ts, written with Hono. The
shape of a customer is the zod schema at the top of that
file:
const CustomerDraft = z.object({
name: z.string().trim().min(1).max(200),
email: z.email().max(320),
});
A body that doesn’t match it gets a 422 that names each wrong field. An id
that isn’t a customer gets a 404. The tests are in src/index.test.ts.
The data lives in two tables, customers and orders, in your own
Supabase project. schema.sql creates them, with one
customer and two orders to start with. src/supabase.ts talks to Supabase’s
REST API with plain fetch. If Supabase refuses a request, the answer is a
500 and the reason is in your logs.
Run it
npx wawesome init --template rest-api
It offers to log you in if you aren’t. Then it asks for a Function name,
customers by default, and an App slug. If you haven’t deployed yet, it offers
to change your workspace address, which locks at your first deploy. Then it
asks for two values:
SUPABASE_URL, your project’s URL, likehttps://abcd.supabase.co. It’s under Project Settings → Data API. We open that one host to your App’s outbound calls.SUPABASE_KEY, the secret key, which starts withsb_secret_. It’s under Project Settings → API Keys. We store it as a secret. The Function needs this key becauseschema.sqlturns on row-level security with no policy, and the publishable key can’t read or write anything. Set the publishable key by mistake and every route answers503, naming the key it needs.
If you don’t have a Supabase project yet, leave both blank. Every route then
answers 503 until you set them.
Then it deploys. Before you use the API, open your project’s SQL Editor, paste
in schema.sql and run it. If you left the values blank, set them now:
npx wawesome env set SUPABASE_URL https://<project-ref>.supabase.co
npx wawesome env set SUPABASE_KEY sb_secret_... --secret
Then try it, with the address init printed:
API=https://api.wawesome.io/x/<workspace>/rest-api/customers
curl "$API"
curl -X POST "$API" -H 'Content-Type: application/json' \
-d '{"name":"Nadia Petrova","email":"nadia@example.com"}'
What to change first
The zod schema in src/index.ts, so a customer has the fields you need. A new
field needs a column in schema.sql too. A new route is one more app.get(...)
or app.post(...) in the same file.
To use a database other than Supabase, change src/supabase.ts. A Function
can only reach it with an HTTPS request made with fetch, and its host is
refused until you open it. See Where your data goes and
Outbound calls.
What it doesn’t do
Every route is public, so anyone with the address can read and delete your customers. Add authentication before you put real data in. There’s no CORS, so a browser on another origin can’t call it until you set the headers. The list routes return every row, with no pagination.
- rest
- api
- hono
- zod
- crud
- database
- supabase
- typescript
Ready in about a minute
Sign in with GitHub, deploy, and get a public HTTPS endpoint.