Skip to content

Every company has the same dirty secret: critical business processes run on spreadsheets, Slack messages, and manual copy-paste between systems. The admin dashboard that would take two months to build properly never gets built. The webhook processor that should exist gets replaced by someone checking email. The report that should be automated is generated by hand every Friday.

These tools do not get built because the overhead of building them is absurd. Spin up a server. Configure a database. Set up authentication. Write a deployment pipeline. Manage SSL certificates. All for an internal tool that three people use.

On Hoody, an internal tool is a file. You write a function, it becomes an HTTP endpoint. You query the database through HTTP. You share the URL with your team. Done. No infrastructure. No deployment. No maintenance. The file IS the tool.


Traditional Internal ToolHoody Internal Tool
Provision a serverAlready have one
Install a web frameworkWrite a function in a file
Set up a databasehoody-sqlite is already running
Configure authenticationProxy permissions
Write deployment scriptsFiles are live instantly
Manage SSL certificatesHandled by the proxy
Monitor uptimehoody-daemon auto-restarts
Schedule taskshoody-cron is already running

The distance between “I need this tool” and “this tool exists” collapses from weeks to minutes.


An admin dashboard that reads user data from SQLite and returns JSON. The frontend can be any HTML page, a React app, or even a curl command.

Terminal window
# Create the users table with sample data (-c targets the container; --db is required)
hoody db exec-transaction -c $CONTAINER_ID --db /hoody/databases/app.db \
--sql "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT NOT NULL, name TEXT NOT NULL, role TEXT DEFAULT 'user', status TEXT DEFAULT 'active', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, last_login DATETIME)"
# Insert sample data
hoody db exec-transaction -c $CONTAINER_ID --db /hoody/databases/app.db \
--sql "INSERT INTO users (email, name, role, status, last_login) VALUES ('alice@company.com', 'Alice Chen', 'admin', 'active', '2026-03-03'), ('bob@company.com', 'Bob Martinez', 'user', 'active', '2026-03-04'), ('carol@company.com', 'Carol Kim', 'user', 'suspended', '2026-02-15')"

Create a hoody-exec script that serves as the dashboard backend:

Terminal window
hoody exec write -c $CONTAINER_ID \
--path "admin/dashboard.ts" \
--content "// @mode serverless\n// @cors reflective\n// @timeout 5000\n\nconst SQLITE = \"https://PROJECT-CONTAINER-sqlite-1.SERVER.containers.hoody.com\";\n\nconst stats = await fetch(SQLITE + \"/api/v1/sqlite/db?db=/hoody/databases/app.db\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ transaction: [{ query: \"SELECT COUNT(*) as total_users FROM users\" }] })\n}).then(r => r.json());\n\nreturn { statistics: stats, generated_at: new Date().toISOString() };"

Your dashboard API is now live:

Terminal window
curl "https://PROJECT-CONTAINER-exec-1.SERVER.containers.hoody.com/admin/dashboard"

Response:

{
"statistics": {
"total_users": 3,
"active_users": 2,
"suspended_users": 1,
"admin_count": 1,
"active_this_week": 2
},
"recent_logins": [
{ "name": "Bob Martinez", "email": "bob@company.com", "role": "user", "status": "active", "last_login": "2026-03-04" },
{ "name": "Alice Chen", "email": "alice@company.com", "role": "admin", "status": "active", "last_login": "2026-03-03" }
],
"generated_at": "2026-03-04T12:00:00.000Z"
}

From nothing to a working admin dashboard API: one file, one URL, zero infrastructure.


Receive webhooks from external services, store them in SQLite, and send notifications.

Terminal window
hoody exec write -c $CONTAINER_ID \
--path "webhooks/stripe.ts" \
--content "// @mode serverless\n// @cors *\n// @timeout 10000\n\nconst SQLITE = \"https://PROJECT-CONTAINER-sqlite-1.SERVER.containers.hoody.com\";\nconst NOTIFY = \"https://PROJECT-CONTAINER-n-1.SERVER.containers.hoody.com\";\n\nawait fetch(SQLITE + \"/api/v1/sqlite/db?db=/hoody/databases/app.db\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n transaction: [{\n query: \"INSERT INTO webhook_events (source, event_type, payload, received_at) VALUES (?, ?, ?, ?)\",\n values: [\"stripe\", req.body.type, JSON.stringify(req.body), new Date().toISOString()]\n }]\n })\n});\n\nreturn { received: true, event: req.body.type };"

Point Stripe’s webhook URL at:

https://PROJECT-CONTAINER-exec-1.SERVER.containers.hoody.com/webhooks/stripe

Every webhook is stored in SQLite. Payment successes and failures trigger push notifications to your phone. Because each request is an isolated execution that writes straight to SQLite, the database transaction is the source of truth — no shared in-memory state to corrupt.


Generate CSV reports from database queries and serve them via hoody-files.

Terminal window
SQLITE="https://$PROJECT_ID-$CONTAINER_ID-sqlite-1.$SERVER.containers.hoody.com"
FILES="https://$PROJECT_ID-$CONTAINER_ID-files-1.$SERVER.containers.hoody.com"
hoody exec write -c $CONTAINER_ID \
--path "reports/weekly-users.ts" \
--content "// @mode serverless\n// @cors reflective\n// @timeout 30000\n\nconst SQLITE = \"$SQLITE\";\nconst FILES = \"$FILES\";\n\nconst result = await fetch(SQLITE + \"/api/v1/sqlite/db?db=/hoody/databases/app.db\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ transaction: [{ query: \"SELECT name, email, role, status FROM users\" }] })\n}).then(r => r.json());\n\nconst rows = result.data || result;\nconst csv = \"Name,Email,Role,Status\\n\" + rows.map(r => [r.name, r.email, r.role, r.status].join(\",\")).join(\"\\n\");\n\nres.setHeader(\"Content-Type\", \"text/csv\");\nreturn csv;"

Hit the URL and download the report:

Terminal window
curl -o report.csv "https://PROJECT-CONTAINER-exec-1.SERVER.containers.hoody.com/reports/weekly-users"

The report is also saved to the filesystem via hoody-files, creating an archive of historical reports.

Run the report automatically every Friday:

Terminal window
hoody cron create root \
-c $CONTAINER_ID \
--schedule "0 9 * * 5" \
--command "curl -s https://PROJECT-CONTAINER-exec-1.SERVER.containers.hoody.com/reports/weekly-users > /dev/null" \
--comment "Weekly user report generation"

Every Friday at 9 AM, the report generates and saves to the filesystem. No crontab editing. No server maintenance. An HTTP call configured the schedule.


Internal tools should not be public. Lock them down:

Terminal window
# Read the current file_version first — the ETag (file:v<N>) is in the response
hoody containers get -c $CONTAINER_ID -o json
# Password protect the container (pass the current file_version via --if-match)
hoody containers replace -c $CONTAINER_ID \
--if-match file:v<N> \
--groups team='{"type": "password", "username": "team", "password": "internal-tools-2026", "salt": "unique-salt"}' \
--permissions team='{"terminal": true, "files": true, "ui": true, "exec": true, "http": true}' \
--default deny
# Or restrict to office IP
hoody containers replace -c $CONTAINER_ID \
--if-match file:v<N> \
--groups office='{"type": "ip", "range": "203.0.113.0/24"}' \
--permissions office='{"terminal": true, "files": true, "ui": true, "exec": true, "http": true}' \
--default deny

Now all services — exec endpoints, SQLite UI, terminal access — require the password. One setting protects everything.


Share the URL. That is the entire distribution process.

Admin Dashboard: https://PROJECT-CONTAINER-exec-1.SERVER.containers.hoody.com/admin/dashboard
Webhook Processor: https://PROJECT-CONTAINER-exec-1.SERVER.containers.hoody.com/webhooks/stripe
Weekly Report: https://PROJECT-CONTAINER-exec-1.SERVER.containers.hoody.com/reports/weekly-users
SQLite Web UI: https://PROJECT-CONTAINER-sqlite-1.SERVER.containers.hoody.com
File Browser: https://PROJECT-CONTAINER-files-1.SERVER.containers.hoody.com

Or create clean aliases:

Terminal window
hoody proxy aliases create --container $CONTAINER_ID --alias "admin" --program exec
# Now accessible at: https://admin.SERVER.containers.hoody.com/admin/dashboard

Your team opens the URL. The tool is there. No deployment, no installation, no training on how to access it. If they can open a browser, they can use the tool.


Every internal tool on Hoody follows the same pattern:

  1. Write a hoody-exec script — The logic lives in a file that becomes a URL
  2. Use hoody-sqlite for data — Queries and storage through HTTP
  3. Use hoody-notifications for alerts — Push notifications when events occur
  4. Use hoody-files for output — Reports, exports, archives
  5. Use hoody-cron for scheduling — Automated execution on a schedule
  6. Use proxy permissions for access — Password or IP restriction
  7. Share the URL — Distribution complete

No servers to manage. No frameworks to learn. No deployment pipelines to configure. No SSL certificates to renew. No Docker images to build. No Kubernetes manifests to write.

Just functions that become URLs, talking to databases that are URLs, saving files that are URLs, on a schedule that is configured via URL.