# elizabthpazp/blog architecture

> Architecture diagram of the GitHub repository elizabthpazp/blog, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-22). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/elizabthpazp/blog
- Repository: https://github.com/elizabthpazp/blog

## Overview

1. **What this repository is**
   - A multilingual personal blog built with **Next.js App Router**, **React**, **TypeScript**, and **Tailwind CSS**.
   - The content is primarily **Markdown-based articles** organized by slug and language, with deployment/runtime oriented toward **Vercel**.
   - The blog also includes engagement features like **likes** and **newsletter subscription**.

2. **Primary application boundary: the Next.js app**
   - The main UI lives under `app/`.
   - The route structure is language-aware: `app/[lang]/...` handles localized pages, and `app/[lang]/[slug]/page.tsx` renders individual posts.
   - `app/[lang]/layout.tsx` and `app/[lang]/providers.tsx` define the shared shell and client-side providers for localized pages.

3. **Content model: Markdown posts on disk**
   - Blog articles are stored in the `posts/` directory, grouped by slug and then by language (`en`, `es`).
   - This means the site is not CMS-driven at runtime; it reads content from the repository itself.
   - `getPostMetadata.ts`, `PostMetadata.ts`, and likely related helpers extract frontmatter/metadata and build the post index used by listing pages and post pages.

4. **Internationalization and routing**
   - Localization is a first-class boundary: `dictionaries/en.json` and `dictionaries/es.json` provide translated UI copy.
   - `get-dictionary.ts` and `i18n-config.ts` centralize dictionary lookup and supported locales.
   - `middleware.ts` likely enforces locale routing or redirects users into the correct `[lang]` segment.
   - Public locale-specific assets also exist under `public/en` and `public/es`, including `robots.txt` and `sitemap.xml`.

5. **Page composition**
   - `app/[lang]/page.tsx` is the localized home/index page, likely showing post previews and site-level content.
   - `components/PostPreview.tsx` is the main content-card boundary for listing posts.
   - `app/[lang]/[slug]/page.tsx` is the article detail page, pulling markdown content, metadata, and post-specific features together.

6. **Interactive client-side features**
   - Several components are explicitly interaction-heavy: `Search.tsx`, `LocaleSwitcher.tsx`, `ThemeSwitcher.tsx`, `Toggle.tsx`, `DropDown.tsx`, and `CopyCode.tsx`.
   - `CodeHighlight.tsx`, `CompareSlider.tsx`, `ResizablePanel.tsx`, and `LoadingDots.tsx` support richer article presentation and UX.
   - `app/hooks/useSubscribe.ts` and `app/hooks/index.ts` package reusable client behavior, probably around newsletter subscription state or form submission.

7. **Engagement and external integrations**
   - Newsletter flow is present through `components/EmailSubs.tsx`, `components/EmailPlantilla.tsx`, and `app/api/convertkit/route.ts`.
   - The ConvertKit API route suggests the newsletter is backed by an external email marketing service rather than an in-repo mailing system.
   - The subscription hook likely posts through this route, keeping the API boundary separate from the UI.

8. **Likes and post statistics subsystem**
   - `app/api/get/route.ts`, `app/api/post/route.ts`, `get-likes.ts`, `get-likes-post.ts`, and the `LikeCount.tsx` / `LikesList.tsx` components form a dedicated engagement subsystem.
   - The presence of `utils/redis.ts` and the README’s PostgreSQL mention suggests likes are persisted outside the React layer, using server-side storage or caching.
   - This subsystem is isolated behind API routes so the frontend can fetch and update like counts without direct database access.

9. **Search and navigation**
   - `components/Search.tsx` provides site search, likely indexing article metadata/content client-side or via local data fetched from the app.
   - `components/Header.tsx`, `components/Footer.tsx`, and `components/RouteActualLink.tsx` define the global navigation boundary.
   - `links-web.ts` appears to be a centralized link/config file for site navigation or external destinations.

10. **SEO, indexing, and public assets**
   - `public/sitemap.xml` plus locale-specific `robots.txt` and `sitemap.xml` files show SEO is treated as a first-class deliverable.
   - `getPostMetadata.ts` and article metadata utilities likely feed canonical URLs, titles, and descriptions.
   - The structure suggests statically generated or server-rendered pages with SEO-friendly output, which fits a blog optimized for discovery.

11. **Styling and presentation system**
   - Global styles live in `styles/globals.css`, with feature-specific styles like `styles/newsletter.css`, `styles/search.css`, and `styles/loading-dots.module.css`.
   - `tailwind.config.js` and `postcss.config.js` define the utility-first styling pipeline.
   - The UI mixes Tailwind-driven layout with a few dedicated CSS modules for more specialized interactions.

12. **Utility and infrastructure layer**
   - `utils/` contains shared low-level helpers such as date formatting, Redis access, image downloading, and string/file-name manipulation.
   - `revalidate-cache.ts` indicates the site uses cache invalidation or ISR-style regeneration for content updates.
   - `next.config.js`, `tsconfig.json`, and the package lock files define the build/runtime envelope around the app.

13. **End-to-end data flow**
   - Content flow: Markdown in `posts/` → metadata extraction → localized page rendering under `app/[lang]` → article display components.
   - Interaction flow: user actions in client components → Next.js API routes → persistence layer/external service → updated UI state.
   - Localization flow: locale detected/routed via middleware → dictionary loaded → localized layout/page/components rendered.

14. **Architectural summary**
   - This is a **content-first, multilingual blog** with a clear split between:
     - static/repository content,
     - localized presentation,
     - server-side API endpoints for engagement,
     - and small integrations with external services like ConvertKit and likely Redis/PostgreSQL-backed storage.
   - For an architecture diagram, the key boxes are: **Next.js app shell**, **Markdown content store**, **i18n dictionaries**, **API routes**, **persistence/cache layer**, and **external newsletter/hosting services**.

Main entry points: [`app/[lang]/layout.tsx`](https://github.com/elizabthpazp/blog/blob/main/app/[lang]/layout.tsx) (Localized shell), [`getPostMetadata.ts`](https://github.com/elizabthpazp/blog/blob/main/getPostMetadata.ts) (Post index), [`app/[lang]/page.tsx`](https://github.com/elizabthpazp/blog/blob/main/app/[lang]/page.tsx) (Home page), [`app/[lang]/[slug]/page.tsx`](https://github.com/elizabthpazp/blog/blob/main/app/[lang]/[slug]/page.tsx) (Article page)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_grp_app["Next.js app"]
  node_app_lang_layout["Localized shell<br/>Next layout<br/>[layout.tsx]"]
  node_app_lang_page["Home page<br/>Next page<br/>[page.tsx]"]
  node_app_lang_slug_page["Article page<br/>Next page<br/>[page.tsx]"]
  node_app_lang_providers["Providers<br/>[providers.tsx]"]
end

subgraph group_grp_content["Content"]
  node_posts_store["Markdown posts<br/>Content store"]
  node_post_metadata["Metadata model<br/>Post metadata<br/>[PostMetadata.ts]"]
  node_get_post_metadata["Post index<br/>Content indexer<br/>[getPostMetadata.ts]"]
end

subgraph group_grp_ui["UI"]
  node_post_preview["Post preview<br/>Card component<br/>[PostPreview.tsx]"]
  node_search["Search<br/>Client component<br/>[Search.tsx]"]
  node_header_footer["Shell chrome<br/>Navigation components<br/>[Header.tsx]"]
  node_locale_theme["Locale/theme UI<br/>Client controls<br/>[LocaleSwitcher.tsx]"]
  node_article_widgets["Article widgets<br/>Presentation widgets<br/>[CodeHighlight.tsx]"]
  node_use_subscribe["Subscribe hook<br/>Client hook<br/>[useSubscribe.ts]"]
end

subgraph group_grp_data["Data services"]
  node_email_subscription["Newsletter UI<br/>Subscription UI<br/>[EmailSubs.tsx]"]
  node_like_ui["Likes UI<br/>Engagement UI<br/>[LikeCount.tsx]"]
  node_convertkit_route["ConvertKit API<br/>Route handler<br/>[route.ts]"]
  node_likes_api["Likes API<br/>Route handlers<br/>[route.ts]"]
  node_likes_store[("Likes store<br/>Redis helper<br/>[redis.ts]")]
end

subgraph group_grp_platform["Platform"]
  node_middleware["Locale middleware<br/>Routing middleware<br/>[middleware.ts]"]
  node_i18n_config["Locale config<br/>i18n config<br/>[i18n-config.ts]"]
  node_get_dictionary["Dictionary loader<br/>i18n helper<br/>[get-dictionary.ts]"]
  node_dictionaries["Translations<br/>JSON dictionaries<br/>[en.json]"]
  node_site_config["Site config<br/>App config<br/>[site.config.ts]"]
  node_styles["Styles<br/>CSS pipeline<br/>[globals.css]"]
end

node_middleware -->|"locale rules"| node_i18n_config
node_middleware -->|"route into"| node_app_lang_layout
node_app_lang_layout -->|"wraps"| node_app_lang_providers
node_app_lang_layout -->|"loads copy"| node_get_dictionary
node_get_dictionary -->|"reads"| node_dictionaries
node_app_lang_page -->|"lists posts"| node_get_post_metadata
node_app_lang_page -->|"renders cards"| node_post_preview
node_app_lang_slug_page -->|"reads markdown"| node_posts_store
node_app_lang_slug_page -->|"resolves metadata"| node_get_post_metadata
node_get_post_metadata -->|"shapes"| node_post_metadata
node_get_post_metadata -->|"scans"| node_posts_store
node_app_lang_page -->|"enables discovery"| node_search
node_header_footer -->|"uses"| node_site_config
node_locale_theme -->|"client state"| node_app_lang_providers
node_article_widgets -->|"enhances"| node_app_lang_slug_page
node_use_subscribe -->|"submits to"| node_convertkit_route
node_email_subscription -->|"drives"| node_use_subscribe
node_convertkit_route -->|"serves"| node_email_subscription
node_like_ui -->|"fetches updates"| node_likes_api
node_likes_api -->|"persists"| node_likes_store
node_styles -->|"skins"| node_app_lang_layout
node_styles -->|"skins"| node_search

click node_app_lang_layout "https://github.com/elizabthpazp/blog/blob/main/app/[lang]/layout.tsx"
click node_app_lang_page "https://github.com/elizabthpazp/blog/blob/main/app/[lang]/page.tsx"
click node_app_lang_slug_page "https://github.com/elizabthpazp/blog/blob/main/app/[lang]/[slug]/page.tsx"
click node_app_lang_providers "https://github.com/elizabthpazp/blog/blob/main/app/[lang]/providers.tsx"
click node_middleware "https://github.com/elizabthpazp/blog/blob/main/middleware.ts"
click node_i18n_config "https://github.com/elizabthpazp/blog/blob/main/i18n-config.ts"
click node_get_dictionary "https://github.com/elizabthpazp/blog/blob/main/get-dictionary.ts"
click node_dictionaries "https://github.com/elizabthpazp/blog/blob/main/dictionaries/en.json"
click node_posts_store "https://github.com/elizabthpazp/blog/blob/main/posts/como-desarrollar-una-web-desde-cero/en/como-desarrollar-una-web-desde-cero.md"
click node_post_metadata "https://github.com/elizabthpazp/blog/blob/main/PostMetadata.ts"
click node_get_post_metadata "https://github.com/elizabthpazp/blog/blob/main/getPostMetadata.ts"
click node_post_preview "https://github.com/elizabthpazp/blog/blob/main/components/PostPreview.tsx"
click node_search "https://github.com/elizabthpazp/blog/blob/main/components/Search.tsx"
click node_header_footer "https://github.com/elizabthpazp/blog/blob/main/components/Header.tsx"
click node_locale_theme "https://github.com/elizabthpazp/blog/blob/main/components/LocaleSwitcher.tsx"
click node_article_widgets "https://github.com/elizabthpazp/blog/blob/main/components/CodeHighlight.tsx"
click node_email_subscription "https://github.com/elizabthpazp/blog/blob/main/components/EmailSubs.tsx"
click node_like_ui "https://github.com/elizabthpazp/blog/blob/main/components/LikeCount.tsx"
click node_use_subscribe "https://github.com/elizabthpazp/blog/blob/main/app/hooks/useSubscribe.ts"
click node_convertkit_route "https://github.com/elizabthpazp/blog/blob/main/app/api/convertkit/route.ts"
click node_likes_api "https://github.com/elizabthpazp/blog/blob/main/app/api/get/route.ts"
click node_likes_store "https://github.com/elizabthpazp/blog/blob/main/utils/redis.ts"
click node_site_config "https://github.com/elizabthpazp/blog/blob/main/app/site.config.ts"
click node_styles "https://github.com/elizabthpazp/blog/blob/main/styles/globals.css"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_app_lang_layout,node_app_lang_page,node_app_lang_slug_page,node_app_lang_providers toneBlue
class node_posts_store,node_post_metadata,node_get_post_metadata toneAmber
class node_post_preview,node_search,node_header_footer,node_locale_theme,node_article_widgets,node_use_subscribe toneMint
class node_email_subscription,node_like_ui,node_convertkit_route,node_likes_api,node_likes_store toneRose
class node_middleware,node_i18n_config,node_get_dictionary,node_dictionaries,node_site_config,node_styles toneIndigo
```

## Components

### Next.js app

Localized application shell, pages, providers, middleware, and route handlers.

- [Localized shell](https://github.com/elizabthpazp/blog/blob/main/app/[lang]/layout.tsx): Next layout · Shared layout for language-scoped pages. · `app/[lang]/layout.tsx`
- [Home page](https://github.com/elizabthpazp/blog/blob/main/app/[lang]/page.tsx): Next page · Localized index page for posts and site content. · `app/[lang]/page.tsx`
- [Article page](https://github.com/elizabthpazp/blog/blob/main/app/[lang]/[slug]/page.tsx): Next page · Renders individual markdown posts under a language and slug. · `app/[lang]/[slug]/page.tsx`
- [Providers](https://github.com/elizabthpazp/blog/blob/main/app/[lang]/providers.tsx): Client providers · Client-side providers and shared runtime state for localized pages. · `app/[lang]/providers.tsx`

### Content

Markdown posts and metadata extraction for the blog index and article pages.

- [Markdown posts](https://github.com/elizabthpazp/blog/blob/main/posts/como-desarrollar-una-web-desde-cero/en/como-desarrollar-una-web-desde-cero.md): Content store · Repository-hosted articles organized by slug and language. · `posts/como-desarrollar-una-web-desde-cero/en/como-desarrollar-una-web-desde-cero.md`
- [Metadata model](https://github.com/elizabthpazp/blog/blob/main/PostMetadata.ts): Post metadata · Shared post metadata shape used across listings and detail pages. · `PostMetadata.ts`
- [Post index](https://github.com/elizabthpazp/blog/blob/main/getPostMetadata.ts): Content indexer · Extracts frontmatter and builds the post listing/index. · `getPostMetadata.ts`

### UI

Reusable components and client-side interaction boundaries.

- [Post preview](https://github.com/elizabthpazp/blog/blob/main/components/PostPreview.tsx): Card component · Preview card used on listing and index pages. · `components/PostPreview.tsx`
- [Search](https://github.com/elizabthpazp/blog/blob/main/components/Search.tsx): Client component · Site search boundary for finding articles and content. · `components/Search.tsx`
- [Shell chrome](https://github.com/elizabthpazp/blog/blob/main/components/Header.tsx): Navigation components · Global header and footer navigation components. · `components/Header.tsx`
- [Locale/theme UI](https://github.com/elizabthpazp/blog/blob/main/components/LocaleSwitcher.tsx): Client controls · Locale switcher, theme switcher, and related toggles. · `components/LocaleSwitcher.tsx`
- [Article widgets](https://github.com/elizabthpazp/blog/blob/main/components/CodeHighlight.tsx): Presentation widgets · Code highlighting, copy, slider, panel, and loading helpers for richer posts. · `components/CodeHighlight.tsx`
- [Subscribe hook](https://github.com/elizabthpazp/blog/blob/main/app/hooks/useSubscribe.ts): Client hook · Reusable hook for newsletter subscription flow. · `app/hooks/useSubscribe.ts`

### Data services

Engagement APIs and server-side persistence helpers.

- [Newsletter UI](https://github.com/elizabthpazp/blog/blob/main/components/EmailSubs.tsx): Subscription UI · Newsletter form and email template components. · `components/EmailSubs.tsx`
- [Likes UI](https://github.com/elizabthpazp/blog/blob/main/components/LikeCount.tsx): Engagement UI · Like count and likes list components for post engagement. · `components/LikeCount.tsx`
- [ConvertKit API](https://github.com/elizabthpazp/blog/blob/main/app/api/convertkit/route.ts): Route handler · Server endpoint for newsletter subscription requests. · `app/api/convertkit/route.ts`
- [Likes API](https://github.com/elizabthpazp/blog/blob/main/app/api/get/route.ts): Route handlers · Server endpoints for reading and posting like data. · `app/api/get/route.ts`
- [Likes store](https://github.com/elizabthpazp/blog/blob/main/utils/redis.ts): Redis helper · Server-side persistence/caching used by the likes subsystem. · `utils/redis.ts`

### Platform

Localization, styling, build, and deployment-related files.

- [Locale middleware](https://github.com/elizabthpazp/blog/blob/main/middleware.ts): Routing middleware · Detects or enforces locale-aware routing. · `middleware.ts`
- [Locale config](https://github.com/elizabthpazp/blog/blob/main/i18n-config.ts): i18n config · Supported locales and routing configuration. · `i18n-config.ts`
- [Dictionary loader](https://github.com/elizabthpazp/blog/blob/main/get-dictionary.ts): i18n helper · Loads translated UI copy for the active language. · `get-dictionary.ts`
- [Translations](https://github.com/elizabthpazp/blog/blob/main/dictionaries/en.json): JSON dictionaries · Localized UI strings for English and Spanish. · `dictionaries/en.json`
- [Site config](https://github.com/elizabthpazp/blog/blob/main/app/site.config.ts): App config · Central site configuration used by the app shell and metadata. · `app/site.config.ts`
- [Styles](https://github.com/elizabthpazp/blog/blob/main/styles/globals.css): CSS pipeline · Global styles and feature-specific CSS modules for the UI. · `styles/globals.css`

## Connections

- Locale middleware → Locale config: locale rules · Middleware uses the supported locale configuration.
- Locale middleware → Localized shell: route into · Locale-aware requests are routed into the localized app shell.
- Localized shell → Providers: wraps · The localized layout provides shared client runtime state.
- Localized shell → Dictionary loader: loads copy · The shell resolves translated strings for the active language.
- Dictionary loader → Translations: reads · Dictionary helper loads JSON translation files.
- Home page → Post index: lists posts · The home page builds its article list from repository metadata.
- Home page → Post preview: renders cards · Listing output is composed with preview cards.
- Article page → Markdown posts: reads markdown · Article detail pages load the post content from disk.
- Article page → Post index: resolves metadata · Detail pages use post metadata for titles and routing.
- Post index → Metadata model: shapes · The indexer produces the shared metadata model.
- Post index → Markdown posts: scans · Repository markdown is scanned to build the index.
- Home page → Search: enables discovery · The localized index page exposes search over content.
- Shell chrome → Site config: uses · Navigation and shell chrome follow central site configuration.
- Locale/theme UI → Providers: client state · Switchers and toggles rely on provider-level runtime state.
- Article widgets → Article page: enhances · Richer article presentation is composed on the post page.
- Subscribe hook → ConvertKit API: submits to · The subscription hook posts form data to the newsletter API.
- Newsletter UI → Subscribe hook: drives · Newsletter UI uses the reusable subscribe hook.
- ConvertKit API → Newsletter UI: serves · The route supports the newsletter subscription flow from the UI.
- Likes UI → Likes API: fetches updates · Like components read and update counts through the API boundary.
- Likes API → Likes store: persists · Like data is stored through the server-side persistence layer.
- Styles → Localized shell: skins · Global and feature styles shape the localized app shell.
- Styles → Search: skins · Search uses dedicated styling alongside the global stylesheet.
