18}
19// Simple hook for mobile menu toggle
20function useMobileMenu() {
21 const [isOpen, setIsOpen] = useState(false);
22 const toggleMenu = () => setIsOpen(!isOpen);
26
27// Simple hook for tracking current hash for active nav styling
28function useCurrentHash() {
29 const [currentHash, setCurrentHash] = useState(() =>
30 window.location.hash.slice(1)
43}
44
45export function App({ initialData }: AppProps) {
46 // initialData
47 const { demoData, loading, error } = initialData;
1export async function startSession() {
2 GLANCE.Cobrowse.Visitor.startSession("GLANCE_KEYTYPE_RANDOM");
3}
4// If you forget to add functions called by events
5// to the global scope (e.g., `onclick="startSession();"`),
6// then those functions won't be in the global scope,
7// and the onclick will fail with Uncaught ReferenceError.
8window.startSession = startSession;
1export default function slugify(str: string) {
2 return str
3 .toString()
7});
8
9export async function getRelatedPagesFromDatabase(pageId: string) {
10 try {
11 const response = await notion.databases.query({
1export async function recordClick(action: string) {
2 // Create data to store
3 const clickData = {
86```typescript
87// Client-side event recording
88window.recordClick = function (action) {
89 fetch(`/api/setAction`, {
90 method: "POST",
116│ └── index.tsx # Frontend JavaScript entry point
117└── shared/ # Utilities used by both frontend and backend
118 └── utils/ # Shared helper functions
119```
120
129### Shared (`/shared`)
130
131Contains utilities and functions that work in both browser and server environments, ensuring code reusability across the application.
132
133## Framework and Technology Stack
189### Shared Utilities (`/shared`)
190
191Contains helper functions that work in both frontend and backend environments:
192
193```typescript
220
221```typescript
222export default async function (interval: Interval) {
223 const pages = await notion.databases.query({
224 database_id: Deno.env.get("GLANCE_DEMOS_DB_ID"),
280| Aspect | Controller | Utility |
281| ------------ | --------------------------------------------- | ------------------------------------------------- |
282| Purpose | Orchestrates business logic and workflows | Provides small, stateless helper functions |
283| Scope | High-level, involves services or side effects | Low-level, narrow focus (string, date operations) |
284| State | Works with application or user-specific data | Stateless - input in, output out |
6| Aspect | **Controller** | **Util** |
7| ----------------- | --------------------------------------------------- | --------------------------------------------------- |
8| **Purpose** | Orchestrates business logic and workflows | Provides small, stateless helper functions |
9| **Scope** | High-level, often involves services or side effects | Low-level, narrow in focus (e.g., string, date ops) |
10| **State** | Works with application or user-specific data | Stateless – input in, output out |
7### Task endpoints use /controllers to get and save data
8
9In order to keep the API easy to look and work with, the routes in /tasks handle routing but do not get data from or save data to Notion. The functions that connect to Notion live in the /controllers directory, and are _called_ from the endpoints in /tasks.
10
11### Naming convention for routes and controllers
25 Note that the export in the controller follows the same convention; it's also called `setDemoURL`.
26
271. Once the controller is imported, pass data to the exported function so that it can do its thing:
28
29 ```
31 ```
32
33 Note the function call is the exported function in the import object at the top of the route; i.e., `{ setDemoURL }`. The `setDemoURL.ts` controller exports it like this:
34
35 ```
36 // /controllers/setDemoURL.ts
37 export async function setDemoURL(data: any) {
38 try {
39 ...
1This directory has crons that extract data from Notion and save that data to blob storage in val.town. Blob storage functions like a cache.
2
3# demoCache.ts
1The files in this directory export functions that get data from and save data to Notion. Most of these functions are used by /tasks.
2
3Every controller in this directory includes the Notion client:
20| Aspect | **Controller** | **Util** |
21| ----------------- | --------------------------------------------------- | --------------------------------------------------- |
22| **Purpose** | Orchestrates business logic and workflows | Provides small, stateless helper functions |
23| **Scope** | High-level, often involves services or side effects | Low-level, narrow in focus (e.g., string, date ops) |
24| **State** | Works with application or user-specific data | Stateless – input in, output out |