|
1 | | -# Website2 |
| 1 | +# EJ Fox's Website |
2 | 2 |
|
3 | | -**Website2** is a custom markdown processing and publishing system built with Nuxt 3. It enables seamless integration of rich content, interactive Gists, scrollytelling, and optimized image handling, while also supporting powerful features like syntax highlighting, Mermaid diagrams, and advanced caching. |
4 | | - |
5 | | -Here’s a high-level, concise guide to the most important files and directories in the **Website2** project: |
6 | | - |
7 | | ---- |
8 | | - |
9 | | -## Project Structure Overview |
10 | | - |
11 | | -This guide will help you navigate the most essential parts of the **Website2** markdown processing and publishing system. Each key directory and file is briefly explained to give you an understanding of what it does and where to find critical functionality. |
12 | | - |
13 | | ---- |
14 | | - |
15 | | -### Root Directory |
16 | | - |
17 | | -- **`nuxt.config.ts`**: The configuration file for Nuxt 3, where global settings for the app are defined, including plugins, runtime configurations, and build options. |
18 | | - |
19 | | -- **`app.vue`**: The root component of the application, which serves as the wrapper for all other pages. If you need to apply a global layout or logic, this is where it goes. |
20 | | - |
21 | | -- **`package.json`**: The project manifest file. It lists dependencies, scripts, and metadata about the project. This is also where you define npm/yarn scripts for running and building the project. |
22 | | - |
23 | | -- **`helpers.js`**: A utility file that contains helper functions used across different parts of the application. This is a great place to look for shared logic. |
24 | | - |
25 | | ---- |
26 | | - |
27 | | -### Important Directories |
28 | | - |
29 | | -- **`pages/`**: This directory contains the main pages for the app, defining the routes. For example: |
30 | | - - **`index.vue`**: The homepage of the site. |
31 | | - - **`blog/`**: Contains individual blog pages and content for the blog section. |
32 | | - - **`projects.vue`**: A dedicated page for showcasing projects. |
33 | | - |
34 | | -- **`composables/`**: Holds reusable logic that can be shared across components. Key files include: |
35 | | - - **`useProcessedMarkdown.ts`**: The core composable responsible for fetching and processing markdown content. |
36 | | - - **`useScraps.ts`**: Handles logic related to scrap content (a unique content type in this system). |
37 | | - |
38 | | -- **`scripts/`**: Where custom Node.js scripts are stored. Examples: |
39 | | - - **`processMarkdown.mjs`**: The main script that processes markdown files and converts them into HTML for display on the site. |
40 | | - - **`generateShareImages.mjs`**: Generates shareable images for social media based on content. |
41 | | - |
42 | | -- **`server/api/`**: Contains API endpoints for interacting with the backend. For instance: |
43 | | - - **`manifest-lite.ts`**: Fetches the metadata for all blog posts. |
44 | | - - **`posts/`**: Handles requests for individual blog posts based on the slug. |
45 | | - - **`scraps.post.ts`**: Manages scrap content in the system. |
46 | | - |
47 | | -- **`content/`**: Houses the markdown content files for the blog, scrapbook, and other sections. This is the source for the markdown processing pipeline. |
48 | | - |
49 | | -- **`dist/`**: The output directory for the processed markdown files and other generated content. |
50 | | - |
51 | | - |
52 | | ---- |
| 3 | +A personal website and blog built with Nuxt 3, Vue 3, and D3.js. Content is managed through Obsidian and processed through a custom pipeline for seamless publishing. |
53 | 4 |
|
54 | 5 | ## Features |
55 | 6 |
|
56 | | -- **Markdown Processing**: Converts markdown files into HTML with automatic enhancements. |
57 | | -- **Gist Embedding**: Execute and display Gists (HTML, JS, CSS, JSON) within markdown. |
58 | | -- **VueUse & Pinia**: Vue.js utilities and state management. |
59 | | -- **Scrollytelling Integration**: Trigger animations and events based on user scroll. |
60 | | -- **OpenAI Plugin**: Integrated plugin for AI-powered features. |
61 | | -- **Cloudinary Image Optimization**: Responsive images served from Cloudinary. |
62 | | -- **Syntax Highlighting**: Uses Shiki for beautiful code block rendering. |
63 | | -- **Mermaid Diagrams**: Embed diagrams in markdown files. |
64 | | -- **Automatic TOC Generation**: Adds table of contents based on markdown headings. |
65 | | -- **Custom Link and Image Processing**: Handles internal links, external links, and image transformations. |
66 | | -- **Caching**: Uses NodeCache to optimize image dimensions and other recurring data. |
67 | | - |
| 7 | +- **Content Management**: Write in Obsidian with markdown, publish with git |
| 8 | +- **Modern Stack**: Built with Nuxt 3, Vue 3 Composition API, and D3.js |
| 9 | +- **Rich Content**: Support for code highlighting, Mermaid diagrams, and interactive elements |
| 10 | +- **Image Optimization**: Automatic Cloudinary integration for responsive images |
| 11 | +- **Smart Filtering**: Multi-layer content visibility protection |
| 12 | +- **Developer Experience**: Hot reload, TypeScript support, and detailed debugging |
68 | 13 |
|
69 | | -This will set up the project, including the repo and its dependencies for rapid prototyping. |
| 14 | +## Content Management |
70 | 15 |
|
71 | | ---- |
| 16 | +### Writing Content |
72 | 17 |
|
73 | | -## Dependencies |
| 18 | +Content is written in Markdown within Obsidian and organized into sections: |
| 19 | +- **Blog Posts**: Main articles and thoughts |
| 20 | +- **Week Notes**: Weekly updates in YYYY-WW format |
| 21 | +- **Projects**: Portfolio and project showcases |
| 22 | +- **Reading Notes**: Book summaries and reflections |
| 23 | +- **Robots**: AI and automation experiments |
| 24 | +- **Prompts**: Writing prompts and exercises |
74 | 25 |
|
75 | | -- **Nuxt 3** |
76 | | -- **Vue 3** |
77 | | -- **Node.js** |
78 | | -- **Cloudinary**: For image hosting and optimization. |
79 | | -- **Shiki**: For syntax highlighting. |
| 26 | +### Frontmatter Options |
80 | 27 |
|
| 28 | +Control post visibility and metadata with frontmatter: |
| 29 | +```yaml |
81 | 30 | --- |
82 | | - |
83 | | -## Development |
84 | | - |
85 | | -To set up the project for development, follow these steps: |
86 | | - |
87 | | -1. Install dependencies: |
88 | | - |
89 | | -```bash |
90 | | -yarn install |
91 | | -``` |
92 | | - |
93 | | -2. Start the development server: |
94 | | - |
95 | | -```bash |
96 | | -yarn dev |
97 | | -``` |
98 | | - |
99 | | -3. Open the project at `http://localhost:3000`. |
100 | | - |
| 31 | +title: Post Title |
| 32 | +date: 2024-01-01 |
| 33 | +hidden: true/false # Completely excludes content from processing |
| 34 | +share: true/false # Required for drafts/robots |
| 35 | +dek: Description # Required for week notes |
101 | 36 | --- |
102 | | - |
103 | | -## Production |
104 | | - |
105 | | -To build and preview the project in production mode: |
106 | | - |
107 | | -1. Build the project for production: |
108 | | - |
109 | | -```bash |
110 | | -yarn build |
111 | 37 | ``` |
112 | 38 |
|
113 | | -2. Preview the production build locally: |
| 39 | +## Content Processing Pipeline |
114 | 40 |
|
115 | | -```bash |
116 | | -yarn preview |
117 | | -``` |
| 41 | +### 1. Import Stage (import.mjs) |
118 | 42 |
|
119 | | ---- |
| 43 | +First line of defense - reads from Obsidian vault and performs initial filtering: |
| 44 | +- Immediately skips any content with hidden: true |
| 45 | +- Filters sensitive content (drafts, robots) based on share status |
| 46 | +- Auto-corrects week note dates from filenames |
| 47 | +- Generates metadata (word count, reading time) |
120 | 48 |
|
121 | | -## Deployment |
| 49 | +### 2. Processing Stage (processMarkdown.mjs) |
122 | 50 |
|
123 | | -Website2 can be deployed on Netlify or any other hosting provider that supports static site generation. |
| 51 | +Second line of defense - transforms content for web display: |
| 52 | +- Double-checks hidden status before processing |
| 53 | +- Converts markdown to HTML |
| 54 | +- Handles syntax highlighting |
| 55 | +- Processes Mermaid diagrams |
| 56 | +- Optimizes images via Cloudinary |
| 57 | +- Generates manifest-lite.json for quick access |
124 | 58 |
|
125 | | -To deploy to Netlify, use the following badge to monitor the deployment status: |
| 59 | +### 3. Runtime Stage (useProcessedMarkdown.ts) |
126 | 60 |
|
127 | | -[](https://app.netlify.com/sites/ejfox-nuxt-template/deploys) |
| 61 | +Final line of defense - handles dynamic content filtering: |
| 62 | +- Triple-checks hidden status before serving |
| 63 | +- Applies visibility rules |
| 64 | +- Sorts and groups content |
| 65 | +- Provides composables for content access |
| 66 | +- Manages special section requirements |
128 | 67 |
|
129 | | ---- |
130 | | - |
131 | | -## Embedding Executable Gists |
132 | | - |
133 | | -### Overview |
134 | | - |
135 | | -**Website2** allows you to embed executable Gists directly into markdown files. These Gists can contain a combination of HTML, JS, CSS, and other file types to create interactive visualizations or complex web components. |
136 | | - |
137 | | -### Basic Usage |
138 | | - |
139 | | -To embed a Gist, use the following syntax in your markdown: |
140 | | - |
141 | | -```markdown |
142 | | -[gist id="your-gist-id-here"] |
143 | | -``` |
144 | | - |
145 | | -This will fetch and render all relevant files from the Gist automatically. Supported file types include: |
146 | | -- `index.html`: The primary HTML file. |
147 | | -- `script.js`: JavaScript code for interactivity. |
148 | | -- `styles.css`: Optional styles for custom design. |
149 | | -- `data.json`: Any accompanying data for dynamic content. |
150 | | - |
151 | | -### Advanced Features |
152 | | - |
153 | | -- **Scrollytelling**: Integrate scrollytelling events by embedding Gists and defining scroll-triggered behaviors in your Gist's JS. |
154 | | -- **Custom Data Handling**: Pass custom JSON data from the Gist into your visualizations. |
155 | | - |
156 | | ---- |
157 | | - |
158 | | -## API Endpoints |
159 | | - |
160 | | -Website2 includes a few core API endpoints to interact with the content: |
161 | | - |
162 | | -1. **Fetch Single Post** |
163 | | - - **Endpoint**: `/api/posts/:slug` |
164 | | - - **Description**: Fetches the content and metadata for a single post. |
165 | | - - **Returns**: JSON object containing the post's HTML and metadata (title, date, tags). |
166 | | - |
167 | | -2. **Fetch All Posts** |
168 | | - - **Endpoint**: `/api/manifest-lite` |
169 | | - - **Description**: Retrieves a list of all posts with basic metadata. |
170 | | - - **Returns**: Array of post metadata (slug, title, date, etc.). |
171 | | - |
172 | | ---- |
173 | | - |
174 | | -## Composables |
175 | | - |
176 | | -The system provides several composables to fetch and process content: |
| 68 | +## Visibility Rules |
177 | 69 |
|
178 | | -1. **`getPostBySlug(slug)`** |
179 | | - - Fetches the content and metadata of a post by its slug. |
180 | | - - Example: |
181 | | - ```js |
182 | | - const post = await getPostBySlug('my-post-slug') |
183 | | - ``` |
| 70 | +### Regular Posts |
| 71 | +- Visible by default |
| 72 | +- Setting hidden: true prevents the post from being processed at all |
184 | 73 |
|
185 | | -2. **`getAllPosts()`** |
186 | | - - Retrieves all posts, filtered and sorted. |
187 | | - - Example: |
188 | | - ```js |
189 | | - const posts = await getAllPosts() |
190 | | - ``` |
| 74 | +### Drafts & Robots |
| 75 | +- Hidden by default |
| 76 | +- Require share: true to be processed |
| 77 | +- Setting hidden: true overrides share status |
191 | 78 |
|
192 | | -3. **`getPostsWithContent(limit, offset)`** |
193 | | - - Fetches a subset of posts with their full content. |
194 | | - - Example: |
195 | | - ```js |
196 | | - const posts = await getPostsWithContent(10, 0) |
197 | | - ``` |
| 79 | +### Week Notes |
| 80 | +- Visible by default if they have a description |
| 81 | +- Use YYYY-WW filename format |
| 82 | +- Setting hidden: true prevents processing |
198 | 83 |
|
199 | | -4. **`getNextPrevPosts(slug)`** |
200 | | - - Fetches the next and previous posts relative to the current one. |
201 | | - - Example: |
202 | | - ```js |
203 | | - const { next, prev } = await getNextPrevPosts('current-slug') |
204 | | - ``` |
205 | | - |
206 | | ---- |
207 | | - |
208 | | -## Markdown Processing |
209 | | - |
210 | | -**Website2** uses a highly customized markdown processing pipeline, featuring: |
211 | | - |
212 | | -- **Unified & Remark**: The core libraries used for parsing and transforming markdown into HTML. |
213 | | -- **Plugins**: Extends functionality with plugins such as: |
214 | | - - `remarkParse`: Parses the markdown. |
215 | | - - `remarkGfm`: Adds support for GitHub Flavored Markdown (tables, task lists). |
216 | | - - `remarkObsidian`: Enables Obsidian-style internal linking. |
217 | | - - `rehypeStringify`: Converts processed markdown into HTML. |
218 | | - - `rehypePrettyCode`: Syntax highlighting using Shiki. |
219 | | - |
220 | | -### Custom Features |
221 | | - |
222 | | -- **Cloudinary Image Optimization**: Dynamically transforms and optimizes images via Cloudinary, ensuring responsive design and fast load times. |
223 | | -- **Table of Contents (TOC)**: Automatically generates a table of contents from the headings in markdown files. |
224 | | -- **Custom Link & Image Processing**: Special handling for internal links, external links (with icons), and Cloudinary-optimized images. |
225 | | - |
226 | | ---- |
227 | | - |
228 | | -## Caching |
229 | | - |
230 | | -Website2 uses **NodeCache** to cache data such as image dimensions and other frequently accessed resources, reducing the need for redundant API calls and improving performance. |
231 | | - |
232 | | -- **TTL (Time-to-Live)**: Set to 1 day for most cached resources. |
233 | | -- **Auto-Save**: The cache is saved to disk on exit, ensuring persistence between sessions. |
234 | | - |
235 | | ---- |
236 | | - |
237 | | -## Output |
238 | | - |
239 | | -Processed markdown files, including their HTML and metadata, are saved in the `dist/processed` directory. Metadata includes: |
240 | | -- **Title** |
241 | | -- **Slug** |
242 | | -- **Date** |
243 | | -- **Modified Date** |
244 | | -- **Word Count** |
245 | | -- **Reading Time** |
246 | | -- **Image and Link Count** |
| 84 | +## Development |
247 | 85 |
|
248 | | -These files are available through the `/api` endpoints and used to power the website's content delivery. |
| 86 | +### Prerequisites |
| 87 | +- Node.js 18+ |
| 88 | +- Yarn |
| 89 | +- Obsidian vault with content |
249 | 90 |
|
250 | | ---- |
| 91 | +### Setup |
| 92 | +1. Clone the repository |
| 93 | +2. Install dependencies: `yarn install` |
| 94 | +3. Copy .env.example to .env and configure |
| 95 | +4. Run development server: `yarn dev` |
251 | 96 |
|
252 | | -## Advanced Features |
| 97 | +### Content Processing |
| 98 | +1. Write content in Obsidian |
| 99 | +2. Run `yarn process` to rebuild content |
| 100 | +3. Changes appear in development server |
253 | 101 |
|
254 | | -1. **Scrollytelling Integration**: Easily trigger animations or events when elements come into view, adding interactivity to your markdown content. |
255 | | - |
256 | | -2. **Custom Data Handling in Gists**: Pass JSON or other custom data directly from a Gist into your JavaScript for dynamic visualizations. |
257 | | -
|
258 | | ---- |
| 102 | +### Environment Variables |
| 103 | +- `CLOUDINARY_*`: Image optimization settings |
| 104 | +- `DEBUG_IMPORT`: Show import process details |
| 105 | +- `DEBUG_PROCESS`: Show markdown processing details |
| 106 | +- `DEBUG_POSTS`: Show post filtering details |
259 | 107 |
|
260 | | -## Development Notes |
| 108 | +## License |
261 | 109 |
|
262 | | -- The `processMarkdown.mjs` script is responsible for transforming markdown into HTML. It applies several transformations, including image optimization, code syntax highlighting, and GitHub Flavored Markdown support. |
263 | | -- Gist embedding is handled by the markdown processor, fetching all Gist files and rendering them interactively on the page. |
264 | | -- The system is highly customizable, with support for additional markdown plugins and transformations. |
| 110 | +MIT License - See LICENSE file for details |
0 commit comments