Understanding the Code Structure
server.js
āāā Configuration (lines 1-43)
ā āāā Imports (Hono, Val.town services)
ā āāā Environment variables
ā āāā Storage keys
ā
āāā Core Services (lines 45-162)
ā āāā readBlob() - Consistent blob reading
ā āāā auth object - All authentication logic
ā
āāā Templates & Helpers (lines 164-358)
ā āāā TEMPLATES - All HTML templates
ā āāā respond - Response helpers
ā āāā handleAsync - Error handling wrapper
ā
āāā Middleware (lines 459-486)
ā āāā requireAdmin - Protected route auth
ā
āāā Routes (lines 490-651)
āāā GET / - Main app
āāā Auth endpoints (/auth/*)
āāā POST /save/app - Save content
āāā GET /versions - History
āāā GET /reset-dangerous - Reset
Adding Your First Feature
Let's add a simple page counter:
1. Add Counter Display to Template
const DEFAULT_HTML = `<!DOCTYPE html>
<html>
<head>
<script src="https://hyperclay.com/js/hyperclay-starter-kit.js"></script>
</head>
<body>
<h1>My Notes</h1>
<div id="counter">Views: 0</div> <!-- Add this -->
<textarea persist edit-mode-input></textarea>
</body>
</html>`;
const counter = {
async increment() {
const key = `${APP_NAMESPACE}_counter`;
const current = await blob.getJSON(key) || { count: 0 };
current.count++;
await blob.setJSON(key, current);
return current.count;
},
async get() {
const key = `${APP_NAMESPACE}_counter`;
const data = await blob.getJSON(key) || { count: 0 };
return data.count;
}
};
app.get("/", async (c) => {
const html = await getCurrentHTML();
const count = await counter.increment();
const updatedHtml = html.replace(
'Views: 0',
`Views: ${count}`
);
return c.html(updatedHtml);
});
const DEFAULT_HTML = `
<!-- Your custom starting template -->
`;
app.get("/api/stats", requireAdmin, handleAsync(async (c) => {
const versions = await getVersionHistory();
return c.json({
versions: versions.length,
lastUpdated: new Date()
});
}));
const expiry = Date.now() + (30 * 60 * 1000);
app.post("/webhook", handleAsync(async (c) => {
const payload = await c.req.json();
const secret = c.req.header('X-Webhook-Secret');
if (secret !== Deno.env.get('WEBHOOK_SECRET')) {
return respond.unauthorized(c);
}
console.log('Webhook received:', payload);
return respond.success(c, 'Webhook processed');
}));
Component | Purpose | Line # |
---|
STORAGE_KEYS | All storage key patterns | 37-43 |
auth object | Authentication logic | 60-162 |
TEMPLATES | HTML templates | 165-286 |
respond | Response helpers | 289-331 |
handleAsync | Error handling | 334-358 |
requireAdmin | Auth middleware | 460-486 |
Routes | All endpoints | 490-651 |
Variable | Required | Description |
---|
ADMIN_EMAIL | ā
Yes | Your email for admin access |
APP_NAMESPACE | No | Storage namespace (default: "default") |
DEBUG | No | Enable debug logs ("true"/"false") |