A developer told me: 'I needed a webhook endpoint. I spent 45 minutes setting up a Vercel project, configuring the build, deploying. Then I found Val Town — I had a live endpoint in 30 seconds.'
What Val Town Offers for Free
Val Town free tier:
- Unlimited vals (serverless functions)
- HTTP endpoints — instant API endpoints
- Cron jobs — scheduled functions
- Email handling — receive and send emails
- Blob storage — persistent key-value store
- SQLite database — built-in SQL database
- npm packages — import any package
- Web-based editor with TypeScript support
Quick Start
// Create an HTTP endpoint (instant API)
// Just write this in Val Town's editor:
export default async function(req: Request): Promise<Response> {
const url = new URL(req.url);
const name = url.searchParams.get('name') || 'World';
return Response.json({
message: `Hello, ${name}!`,
timestamp: new Date().toISOString()
});
}
// Instantly available at: https://username-valname.web.val.run
Build an API in Minutes
import { blob } from 'https://esm.town/v/std/blob';
// Simple CRUD API with blob storage
export default async function(req: Request): Promise<Response> {
const url = new URL(req.url);
const path = url.pathname;
// GET /items — list all
if (req.method === 'GET' && path === '/items') {
const items = await blob.getJSON('items') || [];
return Response.json(items);
}
// POST /items — create
if (req.method === 'POST' && path === '/items') {
const body = await req.json();
const items = await blob.getJSON('items') || [];
const newItem = { id: Date.now(), ...body, createdAt: new Date().toISOString() };
items.push(newItem);
await blob.setJSON('items', items);
return Response.json(newItem, { status: 201 });
}
return new Response('Not Found', { status: 404 });
}
Cron Jobs
// Runs every hour — no infrastructure to manage
export default async function() {
const res = await fetch('https://api.example.com/health');
if (!res.ok) {
// Send alert via email
await email({ to: 'you@example.com', subject: 'API Down!', text: `Status: ${res.status}` });
}
console.log(`Health check: ${res.status} at ${new Date().toISOString()}`);
}
// Set schedule in Val Town: @cron('0 * * * *') — every hour
SQLite Database
import { sqlite } from 'https://esm.town/v/std/sqlite';
// Create table
await sqlite.execute(`
CREATE TABLE IF NOT EXISTS bookmarks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
url TEXT NOT NULL,
title TEXT,
tags TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`);
export default async function(req: Request): Promise<Response> {
if (req.method === 'POST') {
const { url, title, tags } = await req.json();
await sqlite.execute(
'INSERT INTO bookmarks (url, title, tags) VALUES (?, ?, ?)',
[url, title, tags?.join(',')]
);
return Response.json({ success: true });
}
const { rows } = await sqlite.execute(
'SELECT * FROM bookmarks ORDER BY created_at DESC LIMIT 50'
);
return Response.json(rows);
}
Email Handling
import { email } from 'https://esm.town/v/std/email';
// Send email
await email({
to: 'alice@example.com',
subject: 'Your weekly report',
html: '<h1>Weekly Stats</h1><p>Views: 1,234</p>'
});
// Receive email — any email sent to your@valtown.email triggers this val
export default async function(receivedEmail) {
console.log(`From: ${receivedEmail.from}`);
console.log(`Subject: ${receivedEmail.subject}`);
console.log(`Body: ${receivedEmail.text}`);
// Auto-reply, save to database, trigger webhook, etc.
}
REST API for Val Town Itself
# Run a val
curl 'https://api.val.town/v1/run/username.myVal' \
-H 'Authorization: Bearer YOUR_API_TOKEN' \
-d '{"args": [{"name": "Alice"}]}'
# List your vals
curl 'https://api.val.town/v1/me/vals' \
-H 'Authorization: Bearer YOUR_API_TOKEN'
# Create a new val
curl -X POST 'https://api.val.town/v1/vals' \
-H 'Authorization: Bearer YOUR_API_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"code": "export default function() { return 42; }", "name": "myNewVal"}'
Use Cases
- Webhook receivers — Stripe, GitHub, Slack webhooks
- API proxies — add auth, caching, or rate limiting to any API
- Cron jobs — scheduled scrapers, health checks, reports
- Quick APIs — bookmark savers, URL shorteners, form backends
- Email automation — auto-responders, email-to-database
Need to scrape data on autopilot? Check out my web scraping actors on Apify — no-code data collection.
Need custom serverless functions? Email me at spinov001@gmail.com.
Top comments (0)