1## /api
2
3This directory holds the endpoints that serve JSON for the /demo, and a few other endpoints that handle POSTS and GETs from the /frontend.
5## Conventions
6
7As with other directories in `/routes`, the convention in this directory is that the file in the directory that has same name as the directory handles routing in this directory; i.e., `/api/api.ts` handles routing that directs a request from `/api/cobrowse` to the file that does the work: `/api/cobrowse.ts`.
8
9(If you're wondering why the file that handles routing in this directory isn't an `index.ts` file... Glad you asked! The reason is that when you have a bunch of files open in your IDE called `index.ts`, it's impossible to know without clicking in to each file which one is which. Similar issue with debugging server logs.)
8// Initialize Notion client
9const notion = new Client({
10 auth: Deno.env.get("NOTION_API_KEY"),
11});
12```
13
14Keeping controllers in this directory and importing them into our routes keeps our API endpoints thin and easier to work with. (See the /tasks directory as an example.)
15
16## Re: /controllers and /utils
7 const pinger = setInterval(async () => {
8 // check the boolean to see if a Glancer has enabled the link to start a cobrowsing session
9 const resp = await fetch("/api/cobrowse/" + window.__DEMO_ID__, {
10 method: "GET",
11 headers: {
37- Hono /backend/routes, including
38 - index.ts and what it does, and the routing strategy it establishes, including
39 - /api routes for serving JSON and other content to views
40 - /view routes for serving the demo at /demo/:id/
41 - /task routes for handling Notion webhooks
13}
14
15interface ApiErrorResponse {
16 message: string;
17 status: string | number;
18}
19
20export type DemoData = NotionPage | ApiErrorResponse;
21
22// Type guards
23export function isApiError(data: DemoData): data is ApiErrorResponse {
24 return 'message' in data && 'status' in data;
25}
60 }
61
62 // If no initial data, fetch it from the API
63 const demoId = window.__DEMO_ID__ || getDemoIdFromPath();
64 if (demoId && demoId !== 'demo') {
65 try {
66 const response = await fetch(`/api/demo/${demoId}`);
67 const data = await response.json();
68 return {
7
8// Import route modules
9import api from "./routes/api/api.ts";
10import auth from "./routes/auth.ts";
11import root from "./routes/root.ts";
34
35// Mount route modules
36app.route("/api", api);
37app.route("/tasks", tasks);
38app.route("/demo", demo);
9 <script src="https://cdn.tailwindcss.com"></script>
10 <link
11 href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap"
12 rel="stylesheet"
13 />
19 src="https://glance--90537b2ecab54268bf831875fe1d0158.web.val.run"
20 // src="https://lightweight--ef4179e03fc011f0bc0c76b3cceeab13.web.val.run"
21 // src="/api/iframe"
22 // src={`/api/${content}`}
23 // src={`/api/${content}?user=${userId}`}
24 // src={contentURL}
25 title={`Glance content: ${content}`}
5// Initialize Notion client
6const notion = new Client({
7 auth: Deno.env.get("NOTION_API_KEY"),
8});
9
11 return {
12 status: "connected",
13 message: "Successfully connected to Notion API",
14 databases: response.results.map((db) => ({
15 title: db.title?.[0]?.plain_text || "Untitled",
27 }}
28 >
29 <h3 className="font-bold capitalize">
30 {item?.properties?.Name?.title?.[0]?.plain_text}
31 </h3>