Instructions for Adding /views/glimpse/:id Endpoint
Here are the step-by-step instructions that would lead directly to the correct, clean implementation:
1. Analyze the Requirements
Endpoint: GET /views/glimpse/:id
Authentication: Required (existing Google OAuth)
Input: Notion page ID (not database ID)
Output: JSON response with full service response (minus UI elements)
Data source: Notion page properties
2. Examine Current Architecture
Check existing services to understand data access patterns
cat /backend/services/notion.service.ts
Check existing routes structure
cat /backend/routes/views/\_views.routes.ts
Understand authentication flow
cat /main.tsx # Look for auth middleware setup
3. Identify Missing Service Method
Current service has getDatabaseById() for database metadata
Need getPageById() for individual page data
Service should return full Notion response for flexibility
4. Add Service Method First
// Add to /backend/services/notion.service.ts
export async function getPageById(pageId: string) {
try {
const response = await notion.pages.retrieve({
page_id: pageId,
});
return {
success: true,
data: response,
timestamp: new Date().toISOString(),
};
} catch (error) {
return {
success: false,
error: error.message,
timestamp: new Date().toISOString(),
};
}
}
5. Create Controller with Minimal Processing
// Create /backend/controllers/glimpse.controller.ts
import { Context } from "npm:hono@3.12.12";
import { getPageById } from "../services/notion.service.ts";
export async function glimpseHandler(c: Context) {
const id = c.req.param("id");
if (!id) {
return c.json({ error: "Demo ID is required" }, 400);
}
const result = await getPageById(id);
if (!result.success) {
return c.json({ error: "Failed to fetch demo data", details: result.error }, 500);
}
// Filter out button properties from the response
if (result.data?.properties) {
const filteredProperties = Object.fromEntries(
Object.entries(result.data.properties).filter(([key, value]) => value?.type !== "button")
);
result.data.properties = filteredProperties;
}
return c.json(result);
}
// Update /backend/routes/views/\_views.routes.ts
import { Hono } from "npm:hono@3.12.12";
import { glimpseHandler } from "../../controllers/glimpse.controller.ts";
const app = new Hono();
app.get("/glimpse/:id", glimpseHandler);
export default app;
Add to /backend/routes/views/README.md
Purpose : Returns Notion page data as JSON (filtered for data consumption)
Authentication : Required (Google OAuth)
Parameters : id - Notion page ID
Response : Service response object with Notion page data (button properties removed)
Filtering : Removes UI-specific properties (type: "button") for cleaner data consumption
✅ Controller Best Practices:
Single Responsibility: Controller handles HTTP concerns + minimal data cleanup
Thin Layer: Minimal processing, focused on improving data consumption
Useful Filtering: Remove UI elements that don't belong in data APIs
Consistent Error Handling: Standard error response format
✅ Service Layer:
Data Access: Handle all Notion API interactions
Consistent Response Format: Always return {success, data/error, timestamp}
Raw Data: Return unfiltered data from external APIs
✅ Separation of Concerns:
Controller: HTTP validation, routing, error responses, basic data cleanup
Service: External API calls, data retrieval
Client: Complex data processing, extraction, formatting
{
"success": true,
"data": {
"object": "page",
"id": "notion-page-id",
"properties": {
"Name": {
"type": "title",
"title": [{"plain_text": "Demo Name"}]
},
"Status": {
"type": "select",
"select": {"name": "Active"}
}
// Button properties filtered out
}
},
"timestamp": "2025-07-15T17:25:00.000Z"
}
✅ Correct Approach:
Data Source: Use notion.pages.retrieve() for page data
Controller Logic: Keep minimal but include useful data cleanup
Property Filtering: Remove UI-specific elements (buttons) that don't belong in data APIs
Error Handling: Consistent service response pattern
✅ Appropriate Controller Processing:
UI Element Removal: Filter out button properties (not data)
Security Cleanup: Remove potentially sensitive UI configurations
Performance: Reduce payload size by removing unnecessary properties
❌ Avoid These Mistakes:
Over-processing: Don't extract/transform business data in controller
Tight Coupling: Don't assume specific property names or structures
Inconsistent Responses: Don't create custom response formats
Mixed Responsibilities: Don't mix HTTP handling with complex business logic
Test authentication (should show login page)
curl /views/glimpse/test-id
Test with valid Notion page ID (after auth)
curl -H "Cookie: auth-cookie" /views/glimpse/actual-notion-page-id
Verify button properties are filtered out
Response should not contain any properties with "type": "button"
12. Benefits of This Approach
Clean Data: Removes UI clutter from data API responses
Maintainable: Clear separation between layers with focused responsibilities
Flexible: Client can still extract any business data from Notion response
Consistent: Follows existing service response patterns
Secure: Prevents exposure of UI configurations
Performance: Smaller payloads without unnecessary UI properties
Future-proof: Easy to extend filtering logic for other UI property types
13. When to Add Controller Processing
✅ Good reasons to process in controller:
Remove UI-specific elements (buttons, formulas for display)
Filter sensitive configuration data
Remove properties that are never useful for data consumption
Basic security/privacy filtering
❌ Avoid processing in controller:
Complex business logic transformations
Data extraction that depends on specific use cases
Heavy computational processing
Application-specific data formatting
This approach creates a clean, maintainable endpoint that provides useful data filtering while maintaining architectural best practices and keeping the controller focused on its core responsibilities.