|
1 | 1 | # Frame |
2 | 2 |
|
3 | | -This is the outlining directory that makes the site work, the spine of the site. |
| 3 | +The frame subject provides the foundational infrastructure for the docs.github.com application. It serves as the "spine" of the site, handling core Express server setup, middleware orchestration, shared React components, and fundamental utilities that don't belong to a specific subject. |
| 4 | + |
| 5 | +## Purpose & Scope |
| 6 | + |
| 7 | +This subject is responsible for: |
| 8 | +* Server initialization and Express app creation |
| 9 | +* Middleware orchestration across all subjects |
| 10 | +* Context management (`req.context` object building) |
| 11 | +* Shared React components (layouts, navigation, error pages) |
| 12 | +* Fundamental utilities (path parsing, frontmatter validation, page data) |
| 13 | +* Next.js integration and page routing |
| 14 | + |
| 15 | +Philosophy: The preference is to move code into more specific subject folders when possible. Frame should contain only cross-cutting concerns that truly span multiple subjects or don't have a clear subject-specific home. |
| 16 | + |
| 17 | +## Architecture & Key Assets |
| 18 | + |
| 19 | +``` |
| 20 | +src/frame/ |
| 21 | +├── components/ # Shared React components (DefaultLayout, Link, article, page-header/footer) |
| 22 | +├── lib/ # Core utilities (app.ts, page.ts, frontmatter.ts, path-utils.ts) |
| 23 | +├── middleware/ # Express middleware pipeline and context builders |
| 24 | +├── pages/ # Next.js pages directory (legacy) |
| 25 | +├── stylesheets/ # Global CSS and SCSS |
| 26 | +├── server.ts # Server entry point |
| 27 | +└── start-server.ts # Server startup logic |
| 28 | +``` |
| 29 | + |
| 30 | +### Key files and functions |
| 31 | + |
| 32 | +- `lib/app.ts` - `createApp()`: Creates and configures the Express application with all middleware |
| 33 | +- `lib/warm-server.ts` - `warmServer()`: Pre-loads pages, redirects, and site tree on startup |
| 34 | +- `lib/page.ts` - `Page` class: Represents a content page with rendering and metadata methods |
| 35 | +- `lib/frontmatter.ts` - AJV schema: Validates frontmatter structure for all markdown files |
| 36 | +- `lib/path-utils.ts` - Path parsing functions: Extract version, product, language from URLs |
| 37 | +- `middleware/index.ts` - Orchestrates the full middleware pipeline across all subjects |
| 38 | +- `middleware/context/context.ts` - `contextualize()`: Initializes base `req.context` object |
| 39 | +- `middleware/find-page.ts` - Locates the matching page in the site tree |
| 40 | +- `middleware/render-page.ts` - Renders page content and sends response |
| 41 | +- `components/DefaultLayout.tsx` - Main layout wrapper for all pages |
| 42 | + |
| 43 | +## Setup & Usage |
| 44 | + |
| 45 | +### Running the server locally |
| 46 | + |
| 47 | +```bash |
| 48 | +npm run dev |
| 49 | +# Server starts at http://localhost:4000 |
| 50 | +``` |
| 51 | + |
| 52 | +### Running tests |
| 53 | + |
| 54 | +```bash |
| 55 | +npm run test -- src/frame/tests |
| 56 | +``` |
| 57 | + |
| 58 | +### Middleware pipeline order |
| 59 | + |
| 60 | +The middleware in `middleware/index.ts` executes in a specific order. Key stages: |
| 61 | +1. Connection management (timeout, abort handling) |
| 62 | +2. Security and headers (helmet, CORS) |
| 63 | +3. Language detection and context initialization |
| 64 | +4. URL normalization and redirects |
| 65 | +5. Page finding and subject-specific middleware |
| 66 | +6. Context enrichment (breadcrumbs, TOC, features) |
| 67 | +7. Page rendering |
| 68 | +8. Error handling |
| 69 | + |
| 70 | +### Adding new middleware |
| 71 | + |
| 72 | +When adding middleware, consider: |
| 73 | +- Does it belong in a specific subject? If so, add it there and import into `middleware/index.ts` |
| 74 | +- Where does it fit in the pipeline order? |
| 75 | +- Does it need to modify `req.context`? |
| 76 | +- Add to `middleware/index.ts` in the appropriate position |
| 77 | + |
| 78 | +## Data & External Dependencies |
| 79 | + |
| 80 | +### Data inputs |
| 81 | +- Content files (`content/` directory) parsed and loaded into pages |
| 82 | +- Data files (`data/` directory) loaded for variables, features, versions |
| 83 | +- Frontmatter schema defines required/optional fields for all pages |
| 84 | + |
| 85 | +### Dependencies |
| 86 | +- Express.js for HTTP server and middleware |
| 87 | +- Next.js for some routing and SSR (transitioning away from pages/ directory) |
| 88 | +- AJV for frontmatter validation |
| 89 | +- Various subject middleware (versions, languages, redirects, etc.) |
| 90 | + |
| 91 | +### Data outputs |
| 92 | +- `req.context` object: Populated and passed to all downstream middleware and components |
| 93 | +- Site tree: Navigation structure built from content files |
| 94 | +- Rendered HTML: Final page output sent to clients |
| 95 | + |
| 96 | +## Cross-links & Ownership |
| 97 | + |
| 98 | +### Related subjects |
| 99 | +Nearly every subject interacts with frame: |
| 100 | +- [`src/versions`](../versions/README.md) - Version detection and middleware |
| 101 | +- [`src/languages`](../languages/README.md) - Language detection and translation |
| 102 | +- [`src/redirects`](../redirects/README.md) - URL redirect handling |
| 103 | +- [`src/content-render`](../content-render/README.md) - Markdown rendering |
| 104 | +- [`src/landings`](../landings/README.md) - Landing page layouts |
| 105 | +- [`src/learning-track`](../learning-track/README.md) - Learning track navigation |
| 106 | + |
| 107 | +### Ownership |
| 108 | +- Team: Docs Engineering |
| 109 | + |
| 110 | +## Current State & Next Steps |
| 111 | + |
| 112 | +### Known limitations |
| 113 | +- Middleware pipeline complexity: Many middleware pieces interact, making debugging challenging |
| 114 | +- Context object size: `req.context` accumulates many properties across middleware |
| 115 | +- Mixed patterns: Some components are in `components/`, others in subject folders |
| 116 | +- Legacy pages directory: Transitioning from Next.js pages/ to app/ router |
| 117 | + |
| 118 | +### Migration in progress |
| 119 | +- Moving from Next.js pages router to app router |
| 120 | +- Refactoring subject-specific code out of frame when possible |
| 121 | +- Consolidating similar patterns across middleware |
| 122 | + |
| 123 | +### When to add code to frame |
| 124 | +Add code here only if: |
| 125 | +- It's truly cross-cutting (used by 3+ subjects) |
| 126 | +- It's fundamental infrastructure (server, middleware orchestration) |
| 127 | +- No specific subject is a clear fit |
| 128 | + |
| 129 | +Otherwise, prefer adding to a subject-specific directory. |
| 130 | + |
| 131 | +### Future improvements |
| 132 | +### Possible extractions |
| 133 | +- Extract subject-specific middleware to their own directories (e.g., move language detection middleware to `src/languages/middleware`) |
| 134 | +- Extract redirect logic to `src/redirects/middleware` |
| 135 | +- Extract version detection to `src/versions/middleware` |
| 136 | +- Extract search-specific middleware to `src/search/middleware` |
| 137 | +- Extract context object building to individual subjects |
4 | 138 |
|
5 | | -The preference would be to put these files into a more specific subject folder when possible. |
|
0 commit comments