Business logic coordination between routes and services.
Controllers are the business logic layer that:
Controllers do NOT:
All controller functions return:
{
success: boolean,
data: any | null,
error: string | null,
details?: string // Additional error context when available
}
When to use: Most API endpoints, business logic that can be tested independently
Characteristics:
Data Flow:
Route → Controller → Service(s) → External API
Route ← Controller ← Service(s) ← External API
Input Data:
id: string // Notion page UUID
Processing:
getPageById(id)
serviceOutput Data:
{
success: true,
data: {
id: string,
properties: {
// All properties except type: "button"
[key: string]: NotionPropertyValue
},
parent: NotionParent,
// ... other page fields
},
error: null
}
Input Data:
id: string // Notion page UUID
Processing:
getPageWithBlocks(id)
service (orchestrates page + blocks)Output Data:
{
success: true,
data: {
// Page properties (filtered)
id: string,
properties: { [key: string]: NotionPropertyValue },
// Block content (hierarchical)
blocks: NotionBlock[],
// ... other page fields
},
error: null
}
When to use: Authentication flows, webhooks, redirects, HTML responses
Characteristics:
Input Data:
// HTTP Request Body (JSON)
{
data?: { id: string },
id?: string,
page_id?: string
}
// HTTP Headers
{
host: string // Used to construct glimpse URL
}
Processing:
updatePageUrl(pageId, glimpseUrl)
serviceOutput Data:
// HTTP Response (JSON)
{
success: true,
message: "Page URL updated successfully",
pageId: string,
url: string, // The constructed glimpse URL
timestamp: string
}
Input Data:
// From Auth Middleware Context
userEmail: string
// From Environment Variables
GLANCE_DEMOS_DB_ID: string
Processing:
findUserByEmail(databaseId, email)
createUserRecord(databaseId, email)
Output Data:
/glimpse/thanks
User Record Data Structure:
// Expected in Notion database
{
Email: {
type: "email",
email: string
},
URL?: {
type: "url",
url: string
} | {
type: "rich_text",
rich_text: [{ plain_text: string }]
}
}
Input Data:
// From Auth Middleware Context
userEmail: string
Processing:
Output Data:
/
{
success: false,
error: "User-friendly error message",
details: "Technical error details from service",
data: null
}