Public
Like
glimpse2-runbook-view-glimpse-save-login-react
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Viewing readonly version of main branch: v6View latest version
HTTP route handlers organized by functionality.
Routes are the HTTP transport layer that:
- Handle HTTP request/response concerns only
- Extract and validate parameters from HTTP requests
- Call controllers with clean, typed parameters
- Transform controller responses into appropriate HTTP responses
- Handle HTTP status codes, headers, and content types
- Provide consistent error response formatting
Routes do NOT:
- Contain business logic (delegate to controllers)
- Make direct service calls (use controllers as intermediary)
- Handle environment variables or configuration
- Perform data transformation beyond HTTP concerns
HTTP Request → Route Handler → Controller → Service → External API
HTTP Response ← Route Handler ← Controller ← Service ← External API
Each route subdirectory should have a _[directory_name].routes.ts
file that mounts routes for that section.
routes/
├── api/
│ ├── _api.routes.ts # Mounts all API routes
│ └── README.md
├── tasks/
│ ├── _tasks.routes.ts # Mounts webhook routes
│ └── README.md
├── views/
│ ├── _views.routes.ts # Mounts HTML view routes
│ └── README.md
└── glimpse/
├── _glimpse.routes.ts # Mounts authentication routes
└── README.md
Characteristics:
- Extract parameters from URL/body
- Call controller functions with simple parameters
- Return JSON responses
- Handle HTTP status codes based on controller results
HTTP Request Data:
// URL Parameters
params: { id: string }
// Example: GET /api/demo/abc123/properties
Route Processing:
app.get("/demo/:id/properties", async (c) => {
// 1. Extract parameters from HTTP request
const id = c.req.param("id");
// 2. Call controller with clean parameters
const result = await getDemoProperties(id);
// 3. Transform controller response to HTTP response
if (!result.success) {
return c.json({
error: result.error,
details: result.details
}, result.error === "Page ID is required" ? 400 : 500);
}
// 4. Return successful data
return c.json(result.data);
});
HTTP Response Data:
// Success Response (200)
{
id: string,
properties: { [key: string]: NotionPropertyValue },
// ... filtered page data
}
// Error Response (400/500)
{
error: string,
details?: string
}
Characteristics:
- Parse JSON request bodies
- Pass Hono Context to controllers (for HTTP-specific needs)
- Return structured JSON responses
- Handle webhook-specific error scenarios
HTTP Request Data:
// Request Body (JSON)
{
data?: { id: string },
id?: string,
page_id?: string
}
// Request Headers
{
host: string,
"content-type": "application/json"
}
Route Processing:
app.post("/url", handleUrlWebhook);
// Controller handles full HTTP context due to webhook complexity
HTTP Response Data:
// Success Response (200)
{
success: true,
message: "Page URL updated successfully",
pageId: string,
url: string,
timestamp: string
}
// Error Response (400/500)
{
success: false,
error: string,
details?: string
}
Characteristics:
- Handle authentication middleware context
- Support both HTML and JSON responses
- Manage redirects and session state
- Provide user-friendly error pages
HTTP Request Data:
// From Authentication Middleware
context: {
userEmail: string
}
// Environment Configuration
{
GLANCE_DEMOS_DB_ID: string
}
Route Processing:
app.get("/login", glimpseLoginHandler);
// Controller handles full HTTP context for redirects and HTML responses
HTTP Response Data:
- Success:
302 Redirect
to user's personalized URL - New User:
302 Redirect
to/glimpse/thanks
- Error:
200 HTML
error page or500 JSON
error response
Characteristics:
- Simple status endpoints
- Minimal processing
- Consistent JSON responses
HTTP Request Data: None
Route Processing:
app.get("/health", async (c) => {
const healthStatus = await getHealthStatus();
return c.json(healthStatus);
});
HTTP Response Data:
{
status: "healthy" | "unhealthy",
timestamp: string,
// ... additional health metrics
}
// Validation Errors (400)
if (!result.success && result.error === "Page ID is required") {
return c.json({ error: result.error }, 400);
}
// Server Errors (500)
if (!result.success) {
return c.json({
error: result.error,
details: result.details
}, 500);
}
// Bad Request (400)
return c.json({
success: false,
error: "Page ID is required in webhook payload"
}, 400);
// Server Error (500)
return c.json({
success: false,
error: "Internal server error processing webhook",
details: error.message
}, 500);
- HTML Error Pages: For user-facing authentication errors
- JSON Error Responses: For technical/debugging errors
- Redirects: For successful authentication flows
Each route module exports a Hono app that gets mounted in the main application:
// _api.routes.ts
import { Hono } from "npm:hono@3.12.12";
import { getDemoProperties, getDemoFull } from "../../controllers/demo.controller.ts";
const app = new Hono();
app.get("/demo/:id/properties", async (c) => {
// Route implementation
});
export default app;
// main.tsx
import apiRoutes from "./backend/routes/api/_api.routes.ts";
import taskRoutes from "./backend/routes/tasks/_tasks.routes.ts";
app.route("/api", apiRoutes);
app.route("/tasks", taskRoutes);
- Use
c.req.param()
for URL parameters - Use
await c.req.json()
for request bodies - Validate required parameters before calling controllers
- Return raw data for successful API calls
- Include error context for debugging
- Use appropriate HTTP status codes
- Maintain consistent response structures
- Provide user-friendly error messages
- Include technical details for debugging
- Use appropriate HTTP status codes (400 for client errors, 500 for server errors)
- Log errors for monitoring and debugging