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: v12View latest version
Server-side rendered views and data endpoints for frontend consumption.
View routes handle:
- Authentication-protected data access
- JSON response formatting for authenticated users
- Business logic delegation to controllers
- Consistent error response formatting
Purpose: Get Notion page data for authenticated users (filtered for data consumption)
Authentication: Required (Google OAuth via LastLogin)
Input Data:
// URL Parameters
{
id: string // Notion page UUID
}
// Authentication Context (from middleware)
{
userEmail: string,
// Other auth context
}
Processing Flow:
- Authentication middleware validates user
- Extract page ID from URL parameter
- Call
getDemoProperties(id)
controller - Return filtered page data
Success Response (200):
{
id: string,
properties: {
// All properties except type: "button" (UI filtering)
[propertyName: string]: {
type: "title" | "rich_text" | "number" | "select" | "multi_select" | "date" | "checkbox" | "url" | "email" | "phone_number" | "formula" | "relation" | "rollup" | "created_time" | "created_by" | "last_edited_time" | "last_edited_by",
// Property-specific value structure based on type
id: string,
// Type-specific content
}
},
parent: {
type: "database_id" | "page_id",
database_id?: string,
page_id?: string
},
created_time: string,
last_edited_time: string,
created_by: {
object: "user",
id: string
},
last_edited_by: {
object: "user",
id: string
},
cover: {
type: "external" | "file",
external?: { url: string },
file?: { url: string, expiry_time: string }
} | null,
icon: {
type: "emoji" | "external" | "file",
emoji?: string,
external?: { url: string },
file?: { url: string, expiry_time: string }
} | null,
archived: boolean,
url: string
}
Error Responses:
// 401 - Unauthorized (from auth middleware)
{
error: "Authentication required"
}
// 400 - Invalid Request
{
error: "Page ID is required",
details?: string
}
// 500 - Server Error
{
error: "Failed to fetch page data",
details: "Notion API error message"
}
View routes apply business logic filtering:
- Purpose: Remove UI-specific properties that shouldn't be displayed in data views
- Implementation: Controller filters out all properties where
type === "button"
- Reason: Button properties are interactive elements in Notion, not data to be displayed
// Filtered OUT (not included in response)
{
"Action Button": {
"type": "button",
"button": {}
}
}
// Included in response
{
"Title": {
"type": "title",
"title": [
{
"type": "text",
"text": { "content": "Page Title" },
"plain_text": "Page Title"
}
]
},
"Status": {
"type": "select",
"select": {
"id": "abc123",
"name": "Active",
"color": "green"
}
},
"URL": {
"type": "url",
"url": "https://example.com"
}
}
- Request arrives at
/views/glimpse/:id
- Auth middleware validates Google OAuth token
- User context is added to request (email, etc.)
- Route handler extracts page ID and calls controller
- Controller applies business logic and filtering
- Response returns filtered page data
# Authenticated request (requires valid session) curl -H "Cookie: session=..." https://your-val.web.val.run/views/glimpse/abc123 # Response includes filtered properties { "id": "abc123", "properties": { "Title": { "type": "title", "title": [...] }, "Status": { "type": "select", "select": {...} } // Button properties excluded } }
Aspect | /views/glimpse/:id | /api/demo/:id/properties |
---|---|---|
Authentication | Required | Not required |
Data filtering | Button properties removed | Button properties removed |
Use case | Authenticated data access | Public demo access |
Response format | Same filtered structure | Same filtered structure |
Both endpoints use the same controller (getDemoProperties
) but have different authentication requirements.