Skip to content

Enhance related articles with smarter matching and UI improvements#56

Merged
hoangsonww merged 1 commit into
masterfrom
feat/enhance-user-experience
Mar 23, 2026
Merged

Enhance related articles with smarter matching and UI improvements#56
hoangsonww merged 1 commit into
masterfrom
feat/enhance-user-experience

Conversation

@hoangsonww
Copy link
Copy Markdown
Owner

This pull request introduces several UI/UX improvements and visual enhancements across the landing page, article pages, and related components. The main focus is on improving the appearance and interactivity of topic and tag displays, expanding the related articles section, and refining the color/icon logic for topics. Below are the most important changes:

Landing Page & Topic/Tag Display Enhancements:

  • Replaced static tag and topic grids with animated, horizontally scrolling marquees for both hero tags and topic chips on the landing page, using new CSS classes and keyframes for smooth, pausable scrolling. This results in a more dynamic and engaging visual presentation. [1] [2] [3] [4] [5] [6]
  • Added white-space: nowrap and flex-shrink: 0 to tag and chip styles to ensure proper marquee behavior and prevent wrapping. [1] [2]

Related Articles Section Improvements:

  • Refactored the RelatedPosts component to show articles in a paginated fashion, displaying four at a time with a "Show more related articles" button for incremental reveal, improving usability for articles with many related posts. Added a header with an icon and improved styling for consistency. [1] [2] [3]
  • Increased the number of related articles fetched for each article from 4 to 8 (with a fallback of 4), ensuring the new pagination has sufficient content. (app/articles/[slug]/page.tsxL72-R72)

Topic Color and Icon Logic:

  • Significantly expanded and reorganized the TOPIC_COLORS and TOPIC_ICONS mappings in InteractiveCard.tsx to cover more topics, ensure more distinctive and consistent colors, and better represent topic families (AI, Web, Backend, Security, etc.).
  • Introduced a pickAccentTopic function to choose a more specific accent topic (and thus color/icon) for articles with broad first topics, improving visual differentiation across cards. Updated color/icon picking logic to use this function. [1] [2] [3]

Other UI/Content Refinements:

  • Removed the fade-down animation on article pages for a simpler appearance. (app/articles/[slug]/article.cssL7-L20)
  • Updated the chat page hero section with a robot emoji and clarified the description of RAG and Pinecone.

Minor/Administrative:

  • Cleaned up the .claude/settings.local.json permissions to remove an unused grep command.

…ancements, and marquee topics

- Enhance related post algorithm: use topic, title, description, and content similarity, reading time, and recency for better relevance
- Expand related articles section to show more posts with "Show more" button and animated card reveal
- Add icon and subtitle to related articles header for improved UX
- Refine InteractiveCard accent color/icon logic for more specific topic highlighting
- Add animated marquee for hero and topic tags on landing page
- Update styles for hero/topic marquees and related articles section
- Remove fadeDown animation from article container
- Update sitemap and settings for local development
@hoangsonww hoangsonww self-assigned this Mar 23, 2026
@hoangsonww hoangsonww added bug Something isn't working duplicate This issue or pull request already exists enhancement New feature or request help wanted Extra attention is needed good first issue Good for newcomers labels Mar 23, 2026
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
dev-verse-swe-blog Ignored Ignored Mar 23, 2026 2:41am

@hoangsonww hoangsonww merged commit 42ad337 into master Mar 23, 2026
3 checks passed
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request delivers substantial improvements to the blog's user interface, content presentation, and underlying architecture. The primary goal was to create a more interactive and visually appealing experience for users, particularly on the landing page and article detail pages. Key changes include dynamic animated elements, a more intelligent related articles algorithm with pagination, and a refined system for assigning topic-specific colors and icons. Additionally, comprehensive architectural documentation has been added to provide clarity on the system's design and functionality.

Highlights

  • UI/UX Enhancements: Implemented animated, horizontally scrolling marquees for hero tags and topic chips on the landing page, providing a more dynamic and engaging visual experience. This includes new CSS for smooth, pausable scrolling and proper element behavior.
  • Related Articles Logic and Display: Refactored the 'RelatedPosts' component to display articles in a paginated fashion, showing four at a time with a 'Show more' button. The underlying logic for fetching related articles was enhanced with a multi-signal scoring algorithm, considering topic overlap, title/description/content similarity, reading time proximity, and recency, and the fetch limit was increased from 4 to 8.
  • Smarter Topic Color and Icon Assignment: Significantly expanded the mappings for TOPIC_COLORS and TOPIC_ICONS to cover a wider range of topics. A new pickAccentTopic function was introduced to intelligently select a more specific accent topic for articles, improving visual differentiation and consistency across interactive cards.
  • Documentation and Project Structure: Added a comprehensive ARCHITECTURE.md document detailing the system overview, content pipeline, rendering architecture, RAG chat system, authentication, data flow, API routes, build/deploy processes, and key invariants. The README.md was also extensively updated to reflect new features like the RAG chatbot, Mermaid diagram support, and article view counts, along with a refined project structure.
  • Minor UI and Content Refinements: Removed the fade-down animation on article pages for a cleaner appearance and updated the chat page hero section with a robot emoji and clarified the description of RAG and Pinecone.
  • Configuration Cleanup: Cleaned up the .claude/settings.local.json file by removing an unused grep command from allowed permissions.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces significant UI/UX improvements, including animated marquees for tags and topics, and a paginated "show more" feature for related articles. The logic for selecting related articles has been made much more sophisticated, and the topic color/icon system has been expanded for better visual differentiation. A comprehensive architecture document has also been added. My review identifies a critical issue with hardcoded localhost URLs in the generated sitemaps, which will break production SEO. I've also highlighted several high-risk items from the new architecture document, including insecure API endpoints, duplicated code, and a CI process that doesn't validate the production build. I've also suggested improvements for documentation clarity and automating a manual process.

Comment thread ARCHITECTURE.md

### Security Considerations

The `/api/verify-email` and `/api/reset-password` routes use the `SUPABASE_SERVICE_ROLE_KEY` and enumerate all users (up to 1000). These routes have no authentication or rate limiting at the application level. Changes to these routes require careful consideration of abuse potential and the 1000-user ceiling.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The documentation points out a critical security vulnerability: the /api/verify-email and /api/reset-password routes use a service role key and have no authentication or rate limiting. This exposes the application to abuse, such as user enumeration attacks, and allows unauthorized password resets if an attacker can guess an email. These endpoints must be protected immediately with rate limiting (at the infrastructure or application level) and some form of authentication or token-based verification (e.g., sending a signed, single-use link to the user's email) before they can be safely used.

Comment thread public/sitemap-0.xml
Comment on lines +3 to +60
<url><loc>http://localhost:3000/auth/login</loc><lastmod>2026-03-23T02:14:37.054Z</lastmod><changefreq>daily</changefreq><priority>0.8</priority></url>
<url><loc>http://localhost:3000/auth/reset</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>daily</changefreq><priority>0.8</priority></url>
<url><loc>http://localhost:3000/auth/register</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>daily</changefreq><priority>0.8</priority></url>
<url><loc>http://localhost:3000</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>daily</changefreq><priority>0.8</priority></url>
<url><loc>http://localhost:3000/home</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>daily</changefreq><priority>0.8</priority></url>
<url><loc>http://localhost:3000/chat</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>daily</changefreq><priority>0.8</priority></url>
<url><loc>http://localhost:3000/articles/2FA-User-Authentication</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Agentic-AI</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/AI-Coding-Assistants</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Amazon-Web-Services</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Apache-Kafka-Microservices</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Auth0-Authentication</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/BERT-and-Sentiment-Analysis</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/CICD-Pipelines-DevOps</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Compound-Engineering</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Context-Engineering</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Database-Index-Design</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Database-Optimization</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Design-Patterns</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Docker-K8s</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Edge-Computing</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/End-to-End-Data-Pipeline</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Event-Driven-Architecture</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Explainable-AI</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Express.js-RESTful-APIs</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Frontend-Frameworks</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Go-and-Golang-Frameworks</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Graph-Neural-Networks</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/GraphQL</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/HTML6-New-Features</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Improve-Web-SEO</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/InfluxDB</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Kafka-vs-RabbitMQ</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/LLM-Observability</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Microfrontends</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Microservices</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/MongoDB</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Next.js</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/ONNX</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/React-Native-vs-Swift-vs-Kotlin</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Redis</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Reinforcement-Learning-For-Self-Driving</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Rust-Arctix-Web</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/SRE-Incident-Response</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/SSG-SSR-and-ISR</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/State-Management-Web-Apps</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Supabase</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Supervised-Learning</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/TailwindCSS</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Technical-Interviews</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Vision-Transformers</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Web-Development-Basics</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Web3-and-Blockchain</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/WebAssembly</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/WebSockets</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/articles/Zero-Trust-Security</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>weekly</changefreq><priority>0.7</priority></url>
<url><loc>http://localhost:3000/favorites</loc><lastmod>2026-03-23T02:14:37.055Z</lastmod><changefreq>daily</changefreq><priority>0.8</priority></url>
</urlset> No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The sitemap URLs have been changed to use http://localhost:3000. This will break the sitemap on the production deployment and severely impact SEO. The site URL should be dynamically sourced from an environment variable (e.g., SITE_URL, which is already used for sitemap generation in next-sitemap.config.js) to ensure it's correct for the environment it's deployed to. Hardcoding localhost is incorrect for production builds.

Comment thread public/sitemap.xml
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap><loc>https://devverse-swe.vercel.app/sitemap-0.xml</loc></sitemap>
</sitemapindex>
<sitemap><loc>http://localhost:3000/sitemap-0.xml</loc></sitemap>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The sitemap URL has been changed to use http://localhost:3000. This will break the sitemap on the production deployment and severely impact SEO. The site URL should be dynamically sourced from an environment variable (e.g., SITE_URL, which is already used for sitemap generation in next-sitemap.config.js) to ensure it's correct for the environment it's deployed to. Hardcoding localhost is incorrect for production builds.

Comment thread ARCHITECTURE.md

### Content Parsers

Three independent modules parse MDX content using the same regex-based extraction patterns. They do not share a single parser implementation, so changes to the metadata contract must be updated in all three locations simultaneously.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The documentation correctly identifies a significant maintainability risk: three independent modules parse MDX content using duplicated regex patterns. This is error-prone and violates the DRY (Don't Repeat Yourself) principle. Any change to the MDX metadata contract requires updating three separate places, which is likely to lead to bugs and inconsistencies over time. This should be refactored into a single, shared parsing utility that is consumed by lib/rss.ts, lib/rag-local.ts, and scripts/vectorize_articles.mjs.

Comment thread ARCHITECTURE.md

### Docker Configuration

The Dockerfile uses `node:18-bullseye-slim` as the base image, installs dependencies with `npm install`, copies the project, and starts the development server with `npm run dev`. Note that this runs the dev server, not a production build -- CI does not prove a production build is healthy through the Docker image.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The documentation notes that the Dockerfile runs the development server (npm run dev) instead of a production build. This means the CI pipeline is not verifying that a production build is healthy. The Dockerfile should be updated to perform a production build (npm run build) and start the production server (npm run start). This ensures that what is tested and what is deployed are consistent. A multi-stage Dockerfile would be ideal here to create a minimal production image.

Comment thread ARCHITECTURE.md
Comment on lines +232 to +238
**Stage 1:** An inline `<script>` in `layout.tsx` runs before hydration. It reads `localStorage.getItem('darkMode')` and falls back to `window.matchMedia('(prefers-color-scheme: dark)')`. If dark mode is detected, it immediately adds the `dark` class to `<html>`.

**Stage 2:** The `dark` class on `<html>` activates CSS selectors like `html.dark { background-color: #121212 }` directly in the `<style>` tag in `<head>`, preventing a white flash.

**Stage 3:** CSS variables defined in `globals.css` respond to `html.dark` and provide `--text-color`, `--background-color`, `--container-background`, etc.

**Stage 4:** `DarkModeProvider` uses `useLayoutEffect` to read localStorage, toggle the class, and expose `darkMode`/`setDarkMode` via context. It renders `null` (no children) until the initial value is resolved, preventing a hydration mismatch.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The explanation for the "Dark Mode Chain" diagram appears to have formatting issues. The text from "Stage 1" to "Stage 4" seems intended to be a list, but it's rendered as a single paragraph with bolded prefixes. This makes it difficult to read. Consider formatting this section as a numbered or bulleted list to improve clarity.

Suggested change
**Stage 1:** An inline `<script>` in `layout.tsx` runs before hydration. It reads `localStorage.getItem('darkMode')` and falls back to `window.matchMedia('(prefers-color-scheme: dark)')`. If dark mode is detected, it immediately adds the `dark` class to `<html>`.
**Stage 2:** The `dark` class on `<html>` activates CSS selectors like `html.dark { background-color: #121212 }` directly in the `<style>` tag in `<head>`, preventing a white flash.
**Stage 3:** CSS variables defined in `globals.css` respond to `html.dark` and provide `--text-color`, `--background-color`, `--container-background`, etc.
**Stage 4:** `DarkModeProvider` uses `useLayoutEffect` to read localStorage, toggle the class, and expose `darkMode`/`setDarkMode` via context. It renders `null` (no children) until the initial value is resolved, preventing a hydration mismatch.
1. **Stage 1:** An inline `<script>` in `layout.tsx` runs before hydration. It reads `localStorage.getItem('darkMode')` and falls back to `window.matchMedia('(prefers-color-scheme: dark)')`. If dark mode is detected, it immediately adds the `dark` class to `<html>`.
2. **Stage 2:** The `dark` class on `<html>` activates CSS selectors like `html.dark { background-color: #121212 }` directly in the `<style>` tag in `<head>`, preventing a white flash.
3. **Stage 3:** CSS variables defined in `globals.css` respond to `html.dark` and provide `--text-color`, `--background-color`, `--container-background`, etc.
4. **Stage 4:** `DarkModeProvider` uses `useLayoutEffect` to read localStorage, toggle the class, and expose `darkMode`/`setDarkMode` via context. It renders `null` (no children) until the initial value is resolved, preventing a hydration mismatch.

Comment thread ARCHITECTURE.md
Note over Meta,DOM: Portal injects content<br/>below the date blockquote<br/>without modifying MDX output
```

`ArticleMeta` uses React's `createPortal` to inject reading time and view count into the MDX-rendered article body. It locates the first `<blockquote>` inside `.mdx-container` (which holds the `> Date: YYYY-MM-DD` line) and inserts a portal div immediately after it. This allows server-rendered metadata to appear inline without altering the MDX compilation pipeline.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There appears to be a typo in this line. The backtick at the beginning of the line seems unintentional and breaks the sentence flow.

Suggested change
`ArticleMeta` uses React's `createPortal` to inject reading time and view count into the MDX-rendered article body. It locates the first `<blockquote>` inside `.mdx-container` (which holds the `> Date: YYYY-MM-DD` line) and inserts a portal div immediately after it. This allows server-rendered metadata to appear inline without altering the MDX compilation pipeline.
ArticleMeta` uses React's `createPortal` to inject reading time and view count into the MDX-rendered article body. It locates the first `<blockquote>` inside `.mdx-container` (which holds the `> Date: YYYY-MM-DD` line) and inserts a portal div immediately after it. This allows server-rendered metadata to appear inline without altering the MDX compilation pipeline.

Comment thread ARCHITECTURE.md

### Content Staleness

Content edits can make Pinecone vectors stale. After MDX or RAG chunking changes, the vectorization script (`npm run vectorize:articles`) should be re-run to keep the vector index in sync.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The documentation mentions that the vectorization script must be run manually after content edits to prevent stale search results. This manual step is a potential source of operational error. This process should be automated as part of the CI/CD pipeline. For example, a GitHub Action could be triggered on changes to the content/ directory to run the vectorize:articles script, ensuring the Pinecone index is always in sync with the latest content.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working duplicate This issue or pull request already exists enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed

Projects

Development

Successfully merging this pull request may close these issues.

1 participant