@aureuma/svelta 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.changeset/README.md +8 -0
- package/.changeset/config.json +14 -0
- package/.changeset/publish-blogkit.md +5 -0
- package/.github/workflows/release.yml +65 -0
- package/LICENSE +22 -0
- package/README.md +35 -0
- package/docs/mintlify-blog-study.md +697 -0
- package/package.json +59 -0
- package/packages/blogkit/CHANGELOG.md +6 -0
- package/packages/blogkit/LICENSE +22 -0
- package/packages/blogkit/README.md +93 -0
- package/packages/blogkit/dist/components/blog/Avatar.svelte +15 -0
- package/packages/blogkit/dist/components/blog/Avatar.svelte.d.ts +22 -0
- package/packages/blogkit/dist/components/blog/BackLink.svelte +23 -0
- package/packages/blogkit/dist/components/blog/BackLink.svelte.d.ts +21 -0
- package/packages/blogkit/dist/components/blog/BlogCard.svelte +37 -0
- package/packages/blogkit/dist/components/blog/BlogCard.svelte.d.ts +22 -0
- package/packages/blogkit/dist/components/blog/BlogHeroCard.svelte +36 -0
- package/packages/blogkit/dist/components/blog/BlogHeroCard.svelte.d.ts +21 -0
- package/packages/blogkit/dist/components/blog/Container.svelte +8 -0
- package/packages/blogkit/dist/components/blog/Container.svelte.d.ts +29 -0
- package/packages/blogkit/dist/components/blog/ImageLightbox.svelte +58 -0
- package/packages/blogkit/dist/components/blog/ImageLightbox.svelte.d.ts +24 -0
- package/packages/blogkit/dist/components/blog/MorePosts.svelte +15 -0
- package/packages/blogkit/dist/components/blog/MorePosts.svelte.d.ts +21 -0
- package/packages/blogkit/dist/components/blog/ShareButtons.svelte +113 -0
- package/packages/blogkit/dist/components/blog/ShareButtons.svelte.d.ts +23 -0
- package/packages/blogkit/dist/components/blog/SummaryCard.svelte +11 -0
- package/packages/blogkit/dist/components/blog/SummaryCard.svelte.d.ts +20 -0
- package/packages/blogkit/dist/components/blog/TagTabs.svelte +32 -0
- package/packages/blogkit/dist/components/blog/TagTabs.svelte.d.ts +23 -0
- package/packages/blogkit/dist/index.d.ts +11 -0
- package/packages/blogkit/dist/index.js +11 -0
- package/packages/blogkit/dist/server/blog.d.ts +39 -0
- package/packages/blogkit/dist/server/blog.js +222 -0
- package/packages/blogkit/dist/server/index.d.ts +1 -0
- package/packages/blogkit/dist/server/index.js +1 -0
- package/packages/blogkit/dist/theme/ThemeSwitcher.svelte +34 -0
- package/packages/blogkit/dist/theme/ThemeSwitcher.svelte.d.ts +21 -0
- package/packages/blogkit/dist/theme/index.d.ts +2 -0
- package/packages/blogkit/dist/theme/index.js +2 -0
- package/packages/blogkit/dist/theme/store.d.ts +12 -0
- package/packages/blogkit/dist/theme/store.js +50 -0
- package/packages/blogkit/dist/types/blog.d.ts +31 -0
- package/packages/blogkit/dist/types/blog.js +1 -0
- package/packages/blogkit/package.json +66 -0
- package/packages/blogkit/src/lib/components/blog/Avatar.svelte +15 -0
- package/packages/blogkit/src/lib/components/blog/BackLink.svelte +23 -0
- package/packages/blogkit/src/lib/components/blog/BlogCard.svelte +37 -0
- package/packages/blogkit/src/lib/components/blog/BlogHeroCard.svelte +36 -0
- package/packages/blogkit/src/lib/components/blog/Container.svelte +8 -0
- package/packages/blogkit/src/lib/components/blog/ImageLightbox.svelte +58 -0
- package/packages/blogkit/src/lib/components/blog/MorePosts.svelte +15 -0
- package/packages/blogkit/src/lib/components/blog/ShareButtons.svelte +113 -0
- package/packages/blogkit/src/lib/components/blog/SummaryCard.svelte +11 -0
- package/packages/blogkit/src/lib/components/blog/TagTabs.svelte +32 -0
- package/packages/blogkit/src/lib/index.ts +15 -0
- package/packages/blogkit/src/lib/server/blog.ts +264 -0
- package/packages/blogkit/src/lib/server/index.ts +2 -0
- package/packages/blogkit/src/lib/theme/ThemeSwitcher.svelte +34 -0
- package/packages/blogkit/src/lib/theme/index.ts +3 -0
- package/packages/blogkit/src/lib/theme/store.ts +64 -0
- package/packages/blogkit/src/lib/types/blog.ts +36 -0
- package/packages/blogkit/svelte.config.js +8 -0
- package/packages/blogkit/tsconfig.json +5 -0
- package/playwright.config.ts +24 -0
- package/postcss.config.cjs +6 -0
- package/src/app.css +146 -0
- package/src/app.d.ts +13 -0
- package/src/app.html +26 -0
- package/src/content/blog/ai-summary-cards-with-frontmatter.md +32 -0
- package/src/content/blog/announcing-svelta-blog.md +19 -0
- package/src/content/blog/best-practices-ship-with-checklists.md +26 -0
- package/src/content/blog/building-a-mintlify-inspired-blog.md +49 -0
- package/src/content/blog/design-tokens-that-scale.md +47 -0
- package/src/content/blog/for-founders-why-speed-matters.md +23 -0
- package/src/content/blog/infinite-scroll-with-intersection-observer.md +37 -0
- package/src/content/blog/markdown-kitchen-sink.md +101 -0
- package/src/content/blog/markdown-pipeline-mdsvex-shiki.md +39 -0
- package/src/content/blog/rss-feeds-that-actually-work.md +25 -0
- package/src/content/blog/tag-tabs-and-mobile-fade-masks.md +25 -0
- package/src/lib/assets/favicon.svg +1 -0
- package/src/lib/components/site/SiteFooter.svelte +24 -0
- package/src/lib/components/site/SiteHeader.svelte +36 -0
- package/src/lib/content/authors.ts +28 -0
- package/src/lib/index.ts +1 -0
- package/src/lib/server/blog.ts +22 -0
- package/src/lib/server/rss.ts +58 -0
- package/src/lib/server/seo.ts +31 -0
- package/src/lib/stores/theme.ts +10 -0
- package/src/lib/types/blog.ts +1 -0
- package/src/routes/+layout.svelte +31 -0
- package/src/routes/+page.svelte +44 -0
- package/src/routes/blog/+page.server.ts +28 -0
- package/src/routes/blog/+page.svelte +122 -0
- package/src/routes/blog/[slug]/+page.server.ts +39 -0
- package/src/routes/blog/[slug]/+page.svelte +118 -0
- package/src/routes/blog/posts.json/+server.ts +32 -0
- package/src/routes/feed.xml/+server.ts +21 -0
- package/static/blog/authors/alex.svg +13 -0
- package/static/blog/authors/maria.svg +13 -0
- package/static/blog/authors/shawn.svg +13 -0
- package/static/blog/covers/ai-summary.svg +38 -0
- package/static/blog/covers/design-tokens.svg +37 -0
- package/static/blog/covers/infinite-scroll.svg +38 -0
- package/static/blog/covers/kitchen-sink.svg +36 -0
- package/static/blog/covers/markdown-pipeline.svg +41 -0
- package/static/blog/covers/mintlify-style.svg +35 -0
- package/static/blog/covers/rss.svg +34 -0
- package/static/robots.txt +3 -0
- package/svelte.config.js +70 -0
- package/tailwind.config.cjs +133 -0
- package/tests/blog.spec.ts +63 -0
- package/tsconfig.json +21 -0
- package/vite.config.ts +14 -0
|
@@ -0,0 +1,697 @@
|
|
|
1
|
+
# Mintlify Blog Study (Design + Implementation Notes for svelta)
|
|
2
|
+
|
|
3
|
+
Date: 2026-02-08
|
|
4
|
+
|
|
5
|
+
Scope: Build a SvelteKit + Markdown blogging system inspired by `https://www.mintlify.com/blog` (layout, typography scale, theming, cards, tagging, reading-time, RSS, post structure, share UI, responsive behavior, image framing).
|
|
6
|
+
|
|
7
|
+
Method: I used the Playwright MCP browser to inspect the blog index, multiple post pages, responsive breakpoints (desktop + mobile), and crawled a sample set of **36 posts** (latest + mid + older) to validate patterns across content types.
|
|
8
|
+
|
|
9
|
+
## Guardrails (Important)
|
|
10
|
+
|
|
11
|
+
- “Inspired by” means we replicate **patterns** (layout rules, component roles, proportions), not Mintlify’s brand assets or content.
|
|
12
|
+
- Do not copy Mintlify’s copy, images, or proprietary CSS. Use our own components/tokens while matching the *system behavior*.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 1) Expansion Of Each Requested Item (What You Mean) + Mintlify Lessons + How We’ll Implement
|
|
17
|
+
|
|
18
|
+
Each section follows:
|
|
19
|
+
|
|
20
|
+
- **What you mean**: clarified requirement
|
|
21
|
+
- **Mintlify lesson (observed)**: what Mintlify does in practice (numbers, placement, behavior)
|
|
22
|
+
- **Implementation notes (SvelteKit)**: concrete code approach (components, routes, data model)
|
|
23
|
+
|
|
24
|
+
### 1. Element Placement
|
|
25
|
+
|
|
26
|
+
- **What you mean**: the page layout “grid” and where each UI chunk sits (hero, tag bar, cards; or back link, meta, title, author/share, content, more-posts).
|
|
27
|
+
- **Mintlify lesson (observed)**:
|
|
28
|
+
- Blog index: `max-w-5xl mx-auto px-6` container; hero card first; tag bar next; then a 2-col grid of cards.
|
|
29
|
+
- Post page: header stack (back link → category/read-time → title → date), then separator, then 2-col layout: content column + sticky author/share column.
|
|
30
|
+
- Post content column max width is **~628px** within an overall `max-w-4xl` container. The sticky side column is narrow (~150–160px) with a generous horizontal gap.
|
|
31
|
+
- **Implementation notes (SvelteKit)**:
|
|
32
|
+
- Blog index route: `src/routes/blog/+page.svelte`
|
|
33
|
+
- Post route: `src/routes/blog/[slug]/+page.svelte`
|
|
34
|
+
- Shared layout primitives: `src/lib/components/blog/Container.svelte`, `.../BlogHeroCard.svelte`, `.../BlogCard.svelte`, `.../PostLayout.svelte`.
|
|
35
|
+
|
|
36
|
+
### 2. Design (Overall Visual Language)
|
|
37
|
+
|
|
38
|
+
- **What you mean**: the “feel”: minimal, crisp, high contrast, lots of whitespace, rounded media, small mono metadata.
|
|
39
|
+
- **Mintlify lesson (observed)**:
|
|
40
|
+
- Minimal chrome; strong hierarchy: hero image + title as primary attention.
|
|
41
|
+
- Rounded corners are consistent and token-like (24px for hero, 16px for card thumbnails).
|
|
42
|
+
- Metadata is “quiet” (mono uppercase, small size), while titles are clean and medium weight.
|
|
43
|
+
- **Implementation notes (SvelteKit)**:
|
|
44
|
+
- Tailwind + CSS variables for tokens; keep UI components small and composable.
|
|
45
|
+
- Avoid heavy component libraries; implement the specific widgets we need.
|
|
46
|
+
|
|
47
|
+
### 3. Theming (Light/Dark/System)
|
|
48
|
+
|
|
49
|
+
- **What you mean**: global theme with correct contrasts across backgrounds, text, borders, code blocks, and cards; ideally includes system preference.
|
|
50
|
+
- **Mintlify lesson (observed)**:
|
|
51
|
+
- Theme switcher exists with **three modes**: system / light / dark.
|
|
52
|
+
- The site toggles by applying an `html` class (`light` or `dark`).
|
|
53
|
+
- Colors are tokenized (classes like `bg-background-soft`, `text-text-sub`, `text-brand`).
|
|
54
|
+
- **Implementation notes (SvelteKit)**:
|
|
55
|
+
- Theme store that applies `document.documentElement.classList` (`light`/`dark`) and supports `system`.
|
|
56
|
+
- A footer (or header) `ThemeSwitcher.svelte` with radio buttons.
|
|
57
|
+
- Code blocks: Shiki dual theme (one-light + github-dark-default) to match Mintlify’s behavior.
|
|
58
|
+
|
|
59
|
+
### 4. Typeface, Sizes, Proportions
|
|
60
|
+
|
|
61
|
+
- **What you mean**: exact hierarchy for headings/body/meta, line-heights, tracking, and spacing.
|
|
62
|
+
- **Mintlify lesson (observed)**:
|
|
63
|
+
- Sans font: **Inter** (body + titles).
|
|
64
|
+
- Mono font: **Geist Mono** (category/read time/date + “SUMMARY” label + share heading).
|
|
65
|
+
- Post title (`h1`) approx: `font-weight 600`, **40px** size, **44px** line-height, `letter-spacing ~ -0.8px`.
|
|
66
|
+
- Content headings:
|
|
67
|
+
- `h2`: **24px**, `font-weight 500`, `line-height 31.2px`, `letter-spacing -0.24px`, `scroll-mt-20`.
|
|
68
|
+
- `h3`: **20px**, `font-weight 500`, `line-height 26px`, `letter-spacing -0.24px`.
|
|
69
|
+
- Card title: **20px** / 30px, medium weight; excerpt: **14px** / 21px.
|
|
70
|
+
- Meta pills (category/read): mono **12px**, uppercase, tracking **0.6px**.
|
|
71
|
+
- **Implementation notes (SvelteKit)**:
|
|
72
|
+
- Install `@fontsource/inter` and `@fontsource/geist-mono`.
|
|
73
|
+
- Define Tailwind typography scale for `h1/h2/h3/p` inside blog content.
|
|
74
|
+
|
|
75
|
+
### 5. Tags (Categories) + Filtering
|
|
76
|
+
|
|
77
|
+
- **What you mean**: tagging posts and browsing by tag via a tag bar and tag display on cards/posts.
|
|
78
|
+
- **Mintlify lesson (observed)**:
|
|
79
|
+
- Uses a **category tab bar**: “All articles”, “AI trends”, “Announcements”, “For founders”, “Engineering”, “Design”, “Best practices”.
|
|
80
|
+
- Category is shown above titles as a mono uppercase label (brand color).
|
|
81
|
+
- Category filtering does **not** change URL on Mintlify (client-side tab state).
|
|
82
|
+
- Note: category capitalization varies across older posts (“Best Practices” vs “Best practices”, “For Founders” vs “For founders”).
|
|
83
|
+
- **Implementation notes (SvelteKit)**:
|
|
84
|
+
- Frontmatter fields: `category` (single) + optional `tags` (list).
|
|
85
|
+
- UI: tabs filter the card grid; hero card remains fixed (matches Mintlify).
|
|
86
|
+
- Normalize categories (slugify + canonical casing) to avoid duplicates.
|
|
87
|
+
- We can optionally reflect filter in URL query `?category=` for shareability while keeping UX identical.
|
|
88
|
+
|
|
89
|
+
### 6. Color Contrasts
|
|
90
|
+
|
|
91
|
+
- **What you mean**: correct AA-level readability, subtle borders, muted text for metadata, brand accent usage.
|
|
92
|
+
- **Mintlify lesson (observed)**:
|
|
93
|
+
- Brand accent used sparingly (category label).
|
|
94
|
+
- Meta text uses reduced opacity (e.g., ~60% for secondary).
|
|
95
|
+
- Borders are extremely subtle (e.g., ~7% opacity frame border on content images).
|
|
96
|
+
- **Implementation notes (SvelteKit)**:
|
|
97
|
+
- Define tokens:
|
|
98
|
+
- `--background-main`, `--background-soft`, `--background-invert`
|
|
99
|
+
- `--text-main`, `--text-sub`, `--muted`
|
|
100
|
+
- `--border-soft`
|
|
101
|
+
- `--brand`
|
|
102
|
+
- Use Tailwind color mapping to CSS vars: `text-text-sub`, `bg-background-soft`, etc.
|
|
103
|
+
|
|
104
|
+
### 7. View Widgets (Metadata Widgets)
|
|
105
|
+
|
|
106
|
+
- **What you mean**: the small informational UI bits: read time, date, category, maybe views; where they appear.
|
|
107
|
+
- **Mintlify lesson (observed)**:
|
|
108
|
+
- Post header shows: `CATEGORY / N minutes read` (mono uppercase).
|
|
109
|
+
- Post header also shows date (mono uppercase) beneath title.
|
|
110
|
+
- Index hero shows `Date • N min read`.
|
|
111
|
+
- No “view count” in the UI (from what we observed); the “widget” is mostly read time + date + category.
|
|
112
|
+
- **Implementation notes (SvelteKit)**:
|
|
113
|
+
- Compute reading time from markdown word count (server-side).
|
|
114
|
+
- Date formatting helper (e.g., “February 7, 2026”).
|
|
115
|
+
- Optional extension: view counts can be added later via an analytics service; keep UI slot reserved but hidden by default.
|
|
116
|
+
|
|
117
|
+
### 8. Content Loading (Infinite Scroll / “Recycled Scroll”)
|
|
118
|
+
|
|
119
|
+
- **What you mean**: blog index should progressively load content; ideally efficient rendering as list grows.
|
|
120
|
+
- **Mintlify lesson (observed)**:
|
|
121
|
+
- As you scroll down `/blog`, more post cards appear; there is **no Load More button**.
|
|
122
|
+
- On mobile, the tag bar is horizontally scrollable with fade-mask edges and no scrollbar.
|
|
123
|
+
- **Implementation notes (SvelteKit)**:
|
|
124
|
+
- Server: expose an endpoint `GET /blog/posts.json?offset=&limit=&category=` returning metadata.
|
|
125
|
+
- Client: `IntersectionObserver` sentinel triggers fetch and appends.
|
|
126
|
+
- Keep DOM light:
|
|
127
|
+
- MVP: pagination + append (fast enough for ~100–300 posts).
|
|
128
|
+
- Optional: virtualization later if needed (e.g. `@tanstack/svelte-virtual`).
|
|
129
|
+
|
|
130
|
+
### 9. Author Profile Avatar
|
|
131
|
+
|
|
132
|
+
- **What you mean**: consistent author identity visuals (avatar image, fallback initials, sizing, rounding).
|
|
133
|
+
- **Mintlify lesson (observed)**:
|
|
134
|
+
- Avatars are circular with `rounded-full`, size **48x48** (`size-12`).
|
|
135
|
+
- Some cards use author image `/blog/authors/*.webp`; fallback initials appear in snapshots for some cases.
|
|
136
|
+
- **Implementation notes (SvelteKit)**:
|
|
137
|
+
- Authors registry (`src/lib/content/authors.ts`) with `id`, `name`, `title`, `avatar`.
|
|
138
|
+
- `Avatar.svelte`:
|
|
139
|
+
- render `<img>` if available
|
|
140
|
+
- fallback to initials with subtle background.
|
|
141
|
+
|
|
142
|
+
### 10. Author Name + Title Showing
|
|
143
|
+
|
|
144
|
+
- **What you mean**: show author identity both on cards and on post page.
|
|
145
|
+
- **Mintlify lesson (observed)**:
|
|
146
|
+
- Cards show author name + role underneath excerpt.
|
|
147
|
+
- Post page sticky column shows author name + title above share buttons.
|
|
148
|
+
- On mobile, author block moves into header area under title.
|
|
149
|
+
- **Implementation notes (SvelteKit)**:
|
|
150
|
+
- `AuthorChip.svelte` used by cards and post layout.
|
|
151
|
+
- Responsive rendering: `md:hidden` vs `hidden md:flex` blocks.
|
|
152
|
+
|
|
153
|
+
### 11. Article Formatting (Markdown Typesetting)
|
|
154
|
+
|
|
155
|
+
- **What you mean**: clean rendering for headings, paragraphs, lists, blockquotes, code, tables, and links.
|
|
156
|
+
- **Mintlify lesson (observed)**:
|
|
157
|
+
- Headings have anchor links (each heading is linkable); `scroll-mt-20` offsets the fixed header.
|
|
158
|
+
- Inline code has subtle background, padding, and radius.
|
|
159
|
+
- Blockquotes use a left border and padding-left.
|
|
160
|
+
- Code blocks use **Shiki** (`pre.shiki shiki-themes one-light github-dark-default`), ~14px font, 24px line-height, `border-radius: 6px`, `padding: 12px 16px`.
|
|
161
|
+
- Tables exist in some posts; must be styled.
|
|
162
|
+
- **Implementation notes (SvelteKit)**:
|
|
163
|
+
- Use `mdsvex` + `remark-gfm` + `rehype-slug` + `rehype-autolink-headings`.
|
|
164
|
+
- Use Shiki to highlight fenced code blocks; match Mintlify’s pre styling.
|
|
165
|
+
- Add a small CSS layer for `.blog-prose` to tune margins and colors.
|
|
166
|
+
|
|
167
|
+
### 12. Content Format + Display
|
|
168
|
+
|
|
169
|
+
- **What you mean**: the pipeline from markdown/frontmatter to rendered post, including excerpt generation and cover images.
|
|
170
|
+
- **Mintlify lesson (observed)**:
|
|
171
|
+
- Every post has a hero image at top (alt equals title), with rounded 24px, object-cover, max height ~360.
|
|
172
|
+
- Most posts have an AI “SUMMARY” card after hero; at least one post (`/blog/mintlify-for-marketers`) does not.
|
|
173
|
+
- **Implementation notes (SvelteKit)**:
|
|
174
|
+
- Frontmatter:
|
|
175
|
+
- required: `title`, `date`, `category`, `author`, `cover`
|
|
176
|
+
- optional: `excerpt`, `summaryAI`, `tags`, `featured`
|
|
177
|
+
- Render hero image from `cover`.
|
|
178
|
+
- Render summary card only when `summaryAI` is present.
|
|
179
|
+
|
|
180
|
+
### 13. Edges, Margins, Paddings
|
|
181
|
+
|
|
182
|
+
- **What you mean**: exact spacing tokens so the pages feel “Mintlify-tight” and not generic.
|
|
183
|
+
- **Mintlify lesson (observed)**:
|
|
184
|
+
- Index:
|
|
185
|
+
- hero has `my-12`, `p-8`, fixed height `h-[480px]`.
|
|
186
|
+
- grid uses `gap-x-5` and `gap-y-12`, and `pb-32`.
|
|
187
|
+
- Post:
|
|
188
|
+
- container: `mt-[4.5rem]`, `pb-[7.5rem]`, `px-6`, `max-w-4xl`.
|
|
189
|
+
- content + side: `gap-x-16`.
|
|
190
|
+
- “More posts” cards are ~306px wide with thumbnail height ~190.
|
|
191
|
+
- **Implementation notes (SvelteKit)**:
|
|
192
|
+
- Use these as baseline Tailwind classes to match spacing.
|
|
193
|
+
- Avoid adding extra wrappers that break the rhythm.
|
|
194
|
+
|
|
195
|
+
### 14. Time-To-Read Estimation
|
|
196
|
+
|
|
197
|
+
- **What you mean**: show “N min read / N minutes read” consistently across list and post.
|
|
198
|
+
- **Mintlify lesson (observed)**:
|
|
199
|
+
- Post header: “N minutes read”
|
|
200
|
+
- Index hero: “N min read”
|
|
201
|
+
- **Implementation notes (SvelteKit)**:
|
|
202
|
+
- `readingTimeMinutes = max(1, ceil(words / 200))`
|
|
203
|
+
- Render as:
|
|
204
|
+
- index: `${n} min read`
|
|
205
|
+
- post header: `${n} minutes read`
|
|
206
|
+
|
|
207
|
+
### 15. RSS Feed + Icon Placement + Functionality
|
|
208
|
+
|
|
209
|
+
- **What you mean**: generate RSS, expose feed URL, add an icon button in the blog header row.
|
|
210
|
+
- **Mintlify lesson (observed)**:
|
|
211
|
+
- RSS lives at `/feed.xml`.
|
|
212
|
+
- The RSS icon sits to the right of the tag bar row; icon is small (~16px).
|
|
213
|
+
- Feed is RSS 2.0 with `atom:link rel="self"` and per-item: title, description, link/guid, pubDate, category, author.
|
|
214
|
+
- **Implementation notes (SvelteKit)**:
|
|
215
|
+
- Implement route `src/routes/feed.xml/+server.ts`.
|
|
216
|
+
- Add RSS icon link next to tag bar.
|
|
217
|
+
|
|
218
|
+
### 16. Date Display
|
|
219
|
+
|
|
220
|
+
- **What you mean**: consistent formatting and placement.
|
|
221
|
+
- **Mintlify lesson (observed)**:
|
|
222
|
+
- Post page: date is shown below title, mono uppercase, subdued color.
|
|
223
|
+
- Suggested posts (bottom): show date under excerpt.
|
|
224
|
+
- **Implementation notes (SvelteKit)**:
|
|
225
|
+
- Store date as ISO in frontmatter; format via `Intl.DateTimeFormat('en-US', { month:'long', day:'numeric', year:'numeric' })`.
|
|
226
|
+
- For card suggestion: show date only (no author) to reduce clutter.
|
|
227
|
+
|
|
228
|
+
### 17. Hero Article
|
|
229
|
+
|
|
230
|
+
- **What you mean**: a featured post at top of index, bigger than normal cards.
|
|
231
|
+
- **Mintlify lesson (observed)**:
|
|
232
|
+
- Large image card (full width) with overlay text and author block; height 480.
|
|
233
|
+
- Appears regardless of which tab is selected (filter applies to the grid, not hero).
|
|
234
|
+
- **Implementation notes (SvelteKit)**:
|
|
235
|
+
- Choose hero post: `featured: true` else newest by date.
|
|
236
|
+
- `BlogHeroCard.svelte` overlay gradient + white title.
|
|
237
|
+
|
|
238
|
+
### 18. Size Of Each Article Thumbnail
|
|
239
|
+
|
|
240
|
+
- **What you mean**: consistent thumbnail aspect, border radius, and sizing for each card type.
|
|
241
|
+
- **Mintlify lesson (observed)**:
|
|
242
|
+
- Index grid cards: thumbnail height **280px**, rounded **16px**, object-cover.
|
|
243
|
+
- Suggested cards: thumbnail height **190px**, rounded **16px**, object-cover.
|
|
244
|
+
- **Implementation notes (SvelteKit)**:
|
|
245
|
+
- `BlogCard` accepts `variant: 'default' | 'suggestion'` and sets fixed heights.
|
|
246
|
+
|
|
247
|
+
### 19. Picture Frame For Each Image + Corner Radius
|
|
248
|
+
|
|
249
|
+
- **What you mean**: images should have consistent framing; content images should look “mounted”.
|
|
250
|
+
- **Mintlify lesson (observed)**:
|
|
251
|
+
- Hero image: rounded **24px**.
|
|
252
|
+
- Card thumbnails: rounded **16px**.
|
|
253
|
+
- In-content images (non-hero) often have:
|
|
254
|
+
- `border-radius: ~10px`
|
|
255
|
+
- a subtle 1px border (low opacity)
|
|
256
|
+
- `cursor: zoom-in` (image zoom affordance).
|
|
257
|
+
- **Implementation notes (SvelteKit)**:
|
|
258
|
+
- CSS: `.blog-prose img { border-radius: 10px; border: 1px solid var(--border-soft); cursor: zoom-in; }`
|
|
259
|
+
- Lightbox: simple modal that opens on image click; close on escape/click outside.
|
|
260
|
+
|
|
261
|
+
### 20. Title (Placement + Styling)
|
|
262
|
+
|
|
263
|
+
- **What you mean**: title should be dominant in post header and clear in cards.
|
|
264
|
+
- **Mintlify lesson (observed)**:
|
|
265
|
+
- Post H1: 40px/44, weight 600, negative tracking.
|
|
266
|
+
- Card titles: 20px/30, weight 500.
|
|
267
|
+
- **Implementation notes (SvelteKit)**:
|
|
268
|
+
- Tokenize title styles and reuse.
|
|
269
|
+
|
|
270
|
+
### 21. Tag Showing Top Of Article
|
|
271
|
+
|
|
272
|
+
- **What you mean**: show category/tag near top of post, above title.
|
|
273
|
+
- **Mintlify lesson (observed)**:
|
|
274
|
+
- Category label appears above title as part of `CATEGORY / N minutes read`.
|
|
275
|
+
- Category itself is brand-colored, mono uppercase.
|
|
276
|
+
- **Implementation notes (SvelteKit)**:
|
|
277
|
+
- Render category as a clickable filter link (optional) or just label.
|
|
278
|
+
|
|
279
|
+
### 22. URL Paths
|
|
280
|
+
|
|
281
|
+
- **What you mean**: predictable routes for index, posts, and feeds.
|
|
282
|
+
- **Mintlify lesson (observed)**:
|
|
283
|
+
- Index: `/blog`
|
|
284
|
+
- Post: `/blog/<slug>`
|
|
285
|
+
- RSS: `/feed.xml`
|
|
286
|
+
- **Implementation notes (SvelteKit)**:
|
|
287
|
+
- `src/routes/blog/+page.svelte`
|
|
288
|
+
- `src/routes/blog/[slug]/+page.svelte`
|
|
289
|
+
- `src/routes/feed.xml/+server.ts`
|
|
290
|
+
|
|
291
|
+
### 23. AI Summary At The Top + Placement
|
|
292
|
+
|
|
293
|
+
- **What you mean**: show a short summary block above the body to help scanning and AI/SEO; visual should be distinct but subtle.
|
|
294
|
+
- **Mintlify lesson (observed)**:
|
|
295
|
+
- Summary card (when present) is placed **immediately after the hero image**, before the main body.
|
|
296
|
+
- Card style: `p-4`, `rounded-2xl`, soft background, “SUMMARY” label in mono uppercase.
|
|
297
|
+
- It is **optional** (at least one post lacked it).
|
|
298
|
+
- **Implementation notes (SvelteKit)**:
|
|
299
|
+
- Use frontmatter `summaryAI`.
|
|
300
|
+
- Render `SummaryCard.svelte` only if set.
|
|
301
|
+
|
|
302
|
+
### 24. “More Posts To Read” + Recommendations
|
|
303
|
+
|
|
304
|
+
- **What you mean**: show a recommended section at end of every post.
|
|
305
|
+
- **Mintlify lesson (observed)**:
|
|
306
|
+
- Heading: “More blog posts to read”
|
|
307
|
+
- Exactly **2** suggested posts shown (in our sample set), using the smaller card variant.
|
|
308
|
+
- **Implementation notes (SvelteKit)**:
|
|
309
|
+
- Recommend by:
|
|
310
|
+
- same category first
|
|
311
|
+
- then tag overlap
|
|
312
|
+
- fallback to most recent excluding current
|
|
313
|
+
- Render 2 cards with `variant='suggestion'`.
|
|
314
|
+
|
|
315
|
+
### 25. Blog Post Card Widgets (Thumbnail + Author + Title + Excerpt)
|
|
316
|
+
|
|
317
|
+
- **What you mean**: the main discoverability UI on index and in recommendations.
|
|
318
|
+
- **Mintlify lesson (observed)**:
|
|
319
|
+
- Card structure:
|
|
320
|
+
1) rounded thumbnail
|
|
321
|
+
2) mono uppercase category label (brand color)
|
|
322
|
+
3) title
|
|
323
|
+
4) excerpt (muted)
|
|
324
|
+
5) author avatar + name + title
|
|
325
|
+
- Suggestion cards omit author and show date instead.
|
|
326
|
+
- **Implementation notes (SvelteKit)**:
|
|
327
|
+
- `BlogCard.svelte` uses composition:
|
|
328
|
+
- `CardMedia`, `CardMeta`, `CardTitle`, `CardExcerpt`, `CardFooter`.
|
|
329
|
+
|
|
330
|
+
### 26. Tags Bar At Top Of Main Blog Page
|
|
331
|
+
|
|
332
|
+
- **What you mean**: horizontal filter bar with strong active state.
|
|
333
|
+
- **Mintlify lesson (observed)**:
|
|
334
|
+
- Tabs are pill-shaped with `px-3 py-1`, `rounded-full`, height ~31px.
|
|
335
|
+
- Inactive: muted text.
|
|
336
|
+
- Active: background invert + text invert.
|
|
337
|
+
- Mobile: horizontally scrollable, scrollbar hidden, fade mask edges.
|
|
338
|
+
- RSS icon sits to the right of this row.
|
|
339
|
+
- **Implementation notes (SvelteKit)**:
|
|
340
|
+
- `TagTabs.svelte`:
|
|
341
|
+
- uses a scroll container on small screens with a fade mask.
|
|
342
|
+
- uses a simple `activeCategory` state.
|
|
343
|
+
|
|
344
|
+
### 27. Integration Into The Rest Of The SPA Site
|
|
345
|
+
|
|
346
|
+
- **What you mean**: blog should feel like part of the site (shared header/footer/theme), not a separate theme.
|
|
347
|
+
- **Mintlify lesson (observed)**:
|
|
348
|
+
- Blog uses the same global header navigation and footer as the rest of the Mintlify marketing site.
|
|
349
|
+
- Footer includes theme switcher.
|
|
350
|
+
- **Implementation notes (SvelteKit)**:
|
|
351
|
+
- Root layout provides header/footer; blog pages are just routes beneath.
|
|
352
|
+
- `src/routes/+layout.svelte` should import global CSS and render header/footer around `children`.
|
|
353
|
+
|
|
354
|
+
### 28. Responsive Design (Index + Post Page)
|
|
355
|
+
|
|
356
|
+
- **What you mean**: layout adapts cleanly to mobile; side column collapses into header; filters become horizontal scroll; cards become 1 column.
|
|
357
|
+
- **Mintlify lesson (observed)**:
|
|
358
|
+
- Index: grid becomes 1 column on mobile.
|
|
359
|
+
- Filters: scrollable pill tabs with fade.
|
|
360
|
+
- Post page:
|
|
361
|
+
- Desktop: author/share is sticky side column.
|
|
362
|
+
- Mobile: author + share appear under title; side column is hidden.
|
|
363
|
+
- **Implementation notes (SvelteKit)**:
|
|
364
|
+
- Tailwind `md:` breakpoints for layout switches.
|
|
365
|
+
- Ensure touch-friendly tap targets for pills and share buttons.
|
|
366
|
+
|
|
367
|
+
### 29. Thumbnails + Visual Identity
|
|
368
|
+
|
|
369
|
+
- **What you mean**: cards must feel like one system; consistent rounded frames, consistent aspect/height; subtle hover feedback.
|
|
370
|
+
- **Mintlify lesson (observed)**:
|
|
371
|
+
- Cards use rounded thumbnails and subtle overlay gradient on hover/focus (`bg-linear-to-t … opacity-0 group-hover:opacity-70`).
|
|
372
|
+
- **Implementation notes (SvelteKit)**:
|
|
373
|
+
- Add hover/focus overlay gradient layer for thumbnails.
|
|
374
|
+
- Use `focus-visible` outlines for keyboard navigation.
|
|
375
|
+
|
|
376
|
+
### 30. Back Button (Post → Blog Index)
|
|
377
|
+
|
|
378
|
+
- **What you mean**: clear “return to index” affordance in predictable location.
|
|
379
|
+
- **Mintlify lesson (observed)**:
|
|
380
|
+
- Labeled “All articles” with a left arrow icon.
|
|
381
|
+
- Placed above meta row.
|
|
382
|
+
- **Implementation notes (SvelteKit)**:
|
|
383
|
+
- `BackLink.svelte` in post header, route to `/blog`.
|
|
384
|
+
|
|
385
|
+
### 31. “Share This Article” Buttons + SVG Icons
|
|
386
|
+
|
|
387
|
+
- **What you mean**: share UI that matches the design system; icons are inline SVG.
|
|
388
|
+
- **Mintlify lesson (observed)**:
|
|
389
|
+
- 4 icon buttons, circular, `size-8` (32px).
|
|
390
|
+
- Background is soft; icons are muted and brighten on hover.
|
|
391
|
+
- Title “Share this article” is mono uppercase 12px.
|
|
392
|
+
- **Implementation notes (SvelteKit)**:
|
|
393
|
+
- Use inline SVG icons (do not depend on remote image URLs).
|
|
394
|
+
- Provide at least: X, LinkedIn, Copy link, Reddit (or Email).
|
|
395
|
+
- Add `aria-label` for accessibility.
|
|
396
|
+
|
|
397
|
+
### 32. Anything Else Crucial
|
|
398
|
+
|
|
399
|
+
- **What you mean**: missing but important: SEO, OpenGraph, accessibility, performance.
|
|
400
|
+
- **Mintlify lesson (observed/inferred)**:
|
|
401
|
+
- Headings are linkable (good for navigation + sharing).
|
|
402
|
+
- RSS exists (distribution).
|
|
403
|
+
- Strong keyboard focus styles on interactive elements.
|
|
404
|
+
- Posts are highly scannable with summary + strong hierarchy.
|
|
405
|
+
- **Implementation notes (SvelteKit)**:
|
|
406
|
+
- Per-post `<svelte:head>` with `title`, `meta description`, `og:*`, `twitter:*`.
|
|
407
|
+
- `sitemap.xml` can be added later; RSS is required now.
|
|
408
|
+
- Add keyboard focus rings for tabs/buttons.
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
## 2) Consolidated Findings (Categorized)
|
|
413
|
+
|
|
414
|
+
This section reorganizes the above into implementation-ready categories (instead of item order).
|
|
415
|
+
|
|
416
|
+
### A. Information Architecture + Routing
|
|
417
|
+
|
|
418
|
+
- `/blog`: index with hero + filters + infinite scroll grid.
|
|
419
|
+
- `/blog/[slug]`: post page with header meta, hero image, optional AI summary, markdown body, “More posts” section.
|
|
420
|
+
- `/feed.xml`: RSS feed (RSS 2.0 + atom self link).
|
|
421
|
+
|
|
422
|
+
### B. Content Model (Frontmatter)
|
|
423
|
+
|
|
424
|
+
Recommended required frontmatter:
|
|
425
|
+
|
|
426
|
+
```yaml
|
|
427
|
+
title: "..."
|
|
428
|
+
date: "2026-02-07" # ISO
|
|
429
|
+
category: "Best Practices"
|
|
430
|
+
author: "peri" # author id
|
|
431
|
+
cover: "/images/blog/real-llms.png"
|
|
432
|
+
excerpt: "..." # optional, else derive
|
|
433
|
+
summaryAI: "..." # optional
|
|
434
|
+
tags: ["llms.txt", "SEO"] # optional
|
|
435
|
+
featured: false # optional
|
|
436
|
+
draft: false # optional
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### C. Global Tokens (Theme + Typography)
|
|
440
|
+
|
|
441
|
+
- Fonts:
|
|
442
|
+
- Sans: Inter
|
|
443
|
+
- Mono: Geist Mono
|
|
444
|
+
- Theme modes: `system`, `light`, `dark`
|
|
445
|
+
- Key sizes:
|
|
446
|
+
- Post H1: 40/44, 600, tracking -0.8
|
|
447
|
+
- H2: 24/31.2, 500, tracking -0.24
|
|
448
|
+
- H3: 20/26, 500
|
|
449
|
+
- Body: 16 with generous line-height (Mintlify often uses ~28px for paragraphs)
|
|
450
|
+
- Meta: mono 12 uppercase tracking 0.6
|
|
451
|
+
|
|
452
|
+
### D. Components (UI System)
|
|
453
|
+
|
|
454
|
+
- Blog index:
|
|
455
|
+
- `BlogHeroCard`
|
|
456
|
+
- `TagTabs` (scrollable on mobile)
|
|
457
|
+
- `BlogCard` (default variant)
|
|
458
|
+
- `RssIconLink`
|
|
459
|
+
- `InfiniteScrollSentinel`
|
|
460
|
+
- Post page:
|
|
461
|
+
- `BackLink`
|
|
462
|
+
- `PostMetaRow` (category / read-time)
|
|
463
|
+
- `PostDate`
|
|
464
|
+
- `PostHeroImage`
|
|
465
|
+
- `SummaryCard` (optional)
|
|
466
|
+
- `ShareButtons` (desktop sticky + mobile header)
|
|
467
|
+
- `AuthorBlock`
|
|
468
|
+
- `MorePosts` (2 suggestion cards)
|
|
469
|
+
- `ImageLightbox` (for zoomable content images)
|
|
470
|
+
|
|
471
|
+
### E. Media Styling Rules
|
|
472
|
+
|
|
473
|
+
- Hero image: `rounded-3xl` (24px), object-cover, max height ~360.
|
|
474
|
+
- Card thumbnail: `rounded-2xl` (16px), fixed height 280 (default) / 190 (suggestion).
|
|
475
|
+
- In-content images:
|
|
476
|
+
- radius ~10px
|
|
477
|
+
- subtle border
|
|
478
|
+
- zoom cursor + lightbox.
|
|
479
|
+
|
|
480
|
+
### F. Performance + Loading
|
|
481
|
+
|
|
482
|
+
- Index uses infinite scroll; fetch next pages via JSON endpoint.
|
|
483
|
+
- Keep SSR fast: load only metadata for index; load full markdown only on post page.
|
|
484
|
+
|
|
485
|
+
### G. SEO + Syndication
|
|
486
|
+
|
|
487
|
+
- RSS at `/feed.xml`.
|
|
488
|
+
- Per-post meta tags + canonical.
|
|
489
|
+
|
|
490
|
+
---
|
|
491
|
+
|
|
492
|
+
## 3) Fully Detailed Implementation Plan (Workstreams)
|
|
493
|
+
|
|
494
|
+
Workstreams are ordered to keep momentum and reduce rework.
|
|
495
|
+
|
|
496
|
+
### Workstream 1: Project + Tooling Baseline
|
|
497
|
+
|
|
498
|
+
1. Add Tailwind + typography plugin; set up `src/app.css` tokens for light/dark.
|
|
499
|
+
2. Add Inter + Geist Mono fonts (self-hosted via `@fontsource/*`).
|
|
500
|
+
3. Add global layout with header/footer and theme switcher.
|
|
501
|
+
|
|
502
|
+
Deliverables:
|
|
503
|
+
- `tailwind.config.cjs`, `postcss.config.cjs`, `src/app.css`
|
|
504
|
+
- `src/lib/components/ThemeSwitcher.svelte`
|
|
505
|
+
- `src/lib/stores/theme.svelte.ts` (or similar)
|
|
506
|
+
|
|
507
|
+
### Workstream 2: Content Pipeline (Markdown + Frontmatter)
|
|
508
|
+
|
|
509
|
+
1. Add `mdsvex` to compile `.md` to Svelte components.
|
|
510
|
+
2. Add remark/rehype:
|
|
511
|
+
- `remark-gfm` (tables, task lists)
|
|
512
|
+
- `rehype-slug` + `rehype-autolink-headings` (heading permalinks)
|
|
513
|
+
3. Add Shiki highlighting to match Mintlify’s dual theme approach.
|
|
514
|
+
- Note: in this repo we intentionally **disable mdsvex’s metadata script injection** by setting `mdsvexConfig.frontmatter.parse` to return `undefined`, and we parse frontmatter with `gray-matter` in `src/lib/server/blog.ts`. This avoids `script_duplicate` errors when combining mdsvex frontmatter exports with `@shikijs/rehype`.
|
|
515
|
+
4. Implement server utilities:
|
|
516
|
+
- load all posts via `import.meta.glob`
|
|
517
|
+
- parse frontmatter (gray-matter)
|
|
518
|
+
- compute `readingTimeMinutes`, `excerpt`, `date` formatting
|
|
519
|
+
- expose `getAllPosts()`, `getPostBySlug()`
|
|
520
|
+
5. Author registry and lookup.
|
|
521
|
+
|
|
522
|
+
Deliverables:
|
|
523
|
+
- `svelte.config.js` updated for mdsvex
|
|
524
|
+
- `src/lib/server/blog.ts` (loader + model)
|
|
525
|
+
- `src/lib/content/authors.ts`
|
|
526
|
+
- sample posts in `src/content/blog/*.md`
|
|
527
|
+
|
|
528
|
+
### Workstream 3: Blog Index UI + Infinite Scroll
|
|
529
|
+
|
|
530
|
+
1. `/blog` SSR loads:
|
|
531
|
+
- hero post
|
|
532
|
+
- initial page of card posts
|
|
533
|
+
- category list
|
|
534
|
+
2. Implement tag tabs:
|
|
535
|
+
- active state pill styling
|
|
536
|
+
- mobile scroll + fade mask
|
|
537
|
+
3. Implement card grid:
|
|
538
|
+
- default card variant matches Mintlify structure
|
|
539
|
+
4. Implement JSON pagination endpoint to load more.
|
|
540
|
+
|
|
541
|
+
Deliverables:
|
|
542
|
+
- `src/routes/blog/+page.server.ts`
|
|
543
|
+
- `src/routes/blog/+page.svelte`
|
|
544
|
+
- `src/routes/blog/posts.json/+server.ts` (or similar)
|
|
545
|
+
- `src/lib/components/blog/TagTabs.svelte`, `BlogCard.svelte`, `BlogHeroCard.svelte`
|
|
546
|
+
|
|
547
|
+
### Workstream 4: Post Page UI (Layout + Summary + Share + More Posts)
|
|
548
|
+
|
|
549
|
+
1. `/blog/[slug]` loads post component + metadata + recommended posts.
|
|
550
|
+
2. Render header:
|
|
551
|
+
- back link
|
|
552
|
+
- category/read-time row
|
|
553
|
+
- title + date
|
|
554
|
+
3. Render body layout:
|
|
555
|
+
- hero image
|
|
556
|
+
- optional AI summary card
|
|
557
|
+
- markdown content
|
|
558
|
+
4. Render “More posts to read” (2 suggestion cards).
|
|
559
|
+
5. Share UI:
|
|
560
|
+
- desktop: sticky side panel
|
|
561
|
+
- mobile: header block under title
|
|
562
|
+
- implement share links + copy-to-clipboard
|
|
563
|
+
|
|
564
|
+
Deliverables:
|
|
565
|
+
- `src/routes/blog/[slug]/+page.server.ts`
|
|
566
|
+
- `src/routes/blog/[slug]/+page.svelte`
|
|
567
|
+
- `src/lib/components/blog/PostHeader.svelte`, `SummaryCard.svelte`, `ShareButtons.svelte`, `MorePosts.svelte`
|
|
568
|
+
|
|
569
|
+
### Workstream 5: Media UX (Image Framing + Lightbox)
|
|
570
|
+
|
|
571
|
+
1. Apply CSS for in-content images (frame + radius + zoom cursor).
|
|
572
|
+
2. Add a lightweight `ImageLightbox`:
|
|
573
|
+
- opens when clicking content images
|
|
574
|
+
- supports escape key, backdrop close
|
|
575
|
+
- supports scroll locking
|
|
576
|
+
|
|
577
|
+
Deliverables:
|
|
578
|
+
- `src/lib/components/blog/ImageLightbox.svelte`
|
|
579
|
+
- a small enhancement script in post page that binds click handlers to `.blog-prose img`.
|
|
580
|
+
|
|
581
|
+
### Workstream 6: RSS Feed
|
|
582
|
+
|
|
583
|
+
1. Generate RSS 2.0 XML at `/feed.xml`.
|
|
584
|
+
2. Ensure item fields match Mintlify:
|
|
585
|
+
- title, description, link/guid, pubDate, category, author
|
|
586
|
+
- atom:link self
|
|
587
|
+
3. Add RSS icon link to blog index header row.
|
|
588
|
+
|
|
589
|
+
Deliverables:
|
|
590
|
+
- `src/routes/feed.xml/+server.ts`
|
|
591
|
+
- `src/lib/server/rss.ts`
|
|
592
|
+
|
|
593
|
+
### Workstream 7: Polish (A11y + SEO + QA)
|
|
594
|
+
|
|
595
|
+
1. Ensure focus-visible rings on tabs/buttons.
|
|
596
|
+
2. Add per-post meta tags for SEO and social.
|
|
597
|
+
3. Validate:
|
|
598
|
+
- RSS validates
|
|
599
|
+
- dark mode readability for prose + code blocks
|
|
600
|
+
- mobile layout matches fold behavior
|
|
601
|
+
|
|
602
|
+
Deliverables:
|
|
603
|
+
- `src/lib/server/seo.ts` helpers
|
|
604
|
+
- updates in blog routes for `<svelte:head>`
|
|
605
|
+
|
|
606
|
+
---
|
|
607
|
+
|
|
608
|
+
## Acceptance Checklist (Mintlify-Consistency Targets)
|
|
609
|
+
|
|
610
|
+
- Blog index:
|
|
611
|
+
- hero card (480px height, rounded 24, overlay text)
|
|
612
|
+
- tag tabs with pill active state; scrollable on mobile with fade mask
|
|
613
|
+
- 2-col grid on desktop, 1-col on mobile
|
|
614
|
+
- infinite scroll loads more posts
|
|
615
|
+
- RSS icon links to `/feed.xml`
|
|
616
|
+
- Post page:
|
|
617
|
+
- back link (“All articles”) at top
|
|
618
|
+
- meta row: `CATEGORY / N minutes read` (mono uppercase)
|
|
619
|
+
- title (40px) + date (mono uppercase)
|
|
620
|
+
- hero image (rounded 24, max height ~360)
|
|
621
|
+
- optional AI summary card (rounded 16, soft background)
|
|
622
|
+
- markdown rendering with heading anchors, shiki code blocks, styled tables/quotes
|
|
623
|
+
- sticky author/share column on desktop; folded into header on mobile
|
|
624
|
+
- “More blog posts to read” with 2 suggestion cards
|
|
625
|
+
|
|
626
|
+
---
|
|
627
|
+
|
|
628
|
+
## 4) Plan Status (As Of 2026-02-09)
|
|
629
|
+
|
|
630
|
+
### Workstream 1: Foundations (SvelteKit + Theme)
|
|
631
|
+
|
|
632
|
+
Status: Done
|
|
633
|
+
|
|
634
|
+
Implementation notes:
|
|
635
|
+
- Theme-aware light/dark/system is implemented via an early script in `src/app.html` plus a runtime store in `src/lib/stores/theme.ts`.
|
|
636
|
+
- Global tokens live in `src/app.css` and are applied via `html.light` / `html.dark`.
|
|
637
|
+
|
|
638
|
+
### Workstream 2: Content Pipeline (Markdown + Frontmatter)
|
|
639
|
+
|
|
640
|
+
Status: Done
|
|
641
|
+
|
|
642
|
+
Implementation notes:
|
|
643
|
+
- `.md` is compiled via mdsvex in `svelte.config.js` and server-rendered to HTML strings for the post route.
|
|
644
|
+
- Frontmatter is parsed with `gray-matter` in `src/lib/server/blog.ts` (not mdsvex metadata exports) to avoid `script_duplicate` issues with Shiki.
|
|
645
|
+
|
|
646
|
+
### Workstream 3: Blog Index UI + Infinite Scroll
|
|
647
|
+
|
|
648
|
+
Status: Done
|
|
649
|
+
|
|
650
|
+
Implementation notes:
|
|
651
|
+
- `/blog` uses SSR for hero + initial list and a paginated JSON endpoint for additional loads.
|
|
652
|
+
- Category pills are scrollable on mobile with edge fade masking (`fade-mask-x` in `src/app.css`).
|
|
653
|
+
|
|
654
|
+
### Workstream 4: Post Page UI (Layout + Summary + Share + More Posts)
|
|
655
|
+
|
|
656
|
+
Status: Done
|
|
657
|
+
|
|
658
|
+
Implementation notes:
|
|
659
|
+
- Desktop: sticky author/share rail; Mobile: author + share fold into the main column.
|
|
660
|
+
- AI summary is conditional on `summaryAI` in frontmatter.
|
|
661
|
+
|
|
662
|
+
### Workstream 5: Media UX (Image Framing + Lightbox)
|
|
663
|
+
|
|
664
|
+
Status: Done
|
|
665
|
+
|
|
666
|
+
Implementation notes:
|
|
667
|
+
- In-content images are framed via typography + `.blog-prose` tweaks and open a simple lightbox on click.
|
|
668
|
+
|
|
669
|
+
### Workstream 6: RSS Feed
|
|
670
|
+
|
|
671
|
+
Status: Done
|
|
672
|
+
|
|
673
|
+
Implementation notes:
|
|
674
|
+
- RSS lives at `src/routes/feed.xml/+server.ts`.
|
|
675
|
+
- Auto-discovery is provided via `<link rel="alternate">` in `src/routes/+layout.svelte`.
|
|
676
|
+
- RSS XML generation is factored into `src/lib/server/rss.ts`.
|
|
677
|
+
|
|
678
|
+
### Workstream 7: Polish (A11y + SEO + QA)
|
|
679
|
+
|
|
680
|
+
Status: Done (with ongoing content-driven tweaks as new post types are added)
|
|
681
|
+
|
|
682
|
+
Implementation notes:
|
|
683
|
+
- Per-post SEO meta tags are set in `src/routes/blog/[slug]/+page.svelte` using `src/lib/server/seo.ts`.
|
|
684
|
+
- E2E coverage is added via Playwright in `tests/blog.spec.ts` and includes theme toggling, RSS, and mobile folding checks.
|
|
685
|
+
- Markdown edge cases are validated via `src/content/blog/markdown-kitchen-sink.md` and table/URL hardening in `src/app.css`.
|
|
686
|
+
|
|
687
|
+
### Workstream 8: Library Packaging (Reuse Across Repos)
|
|
688
|
+
|
|
689
|
+
Status: Done
|
|
690
|
+
|
|
691
|
+
Implementation notes:
|
|
692
|
+
- Reusable blog components + content loader helpers are packaged as a local workspace library: `packages/blogkit` (`@aureuma/blogkit`).
|
|
693
|
+
- The demo app consumes the library via thin glue modules:
|
|
694
|
+
- `src/lib/server/blog.ts` wraps `createBlog()` from `@aureuma/blogkit/server`
|
|
695
|
+
- `src/lib/stores/theme.ts` wraps `createThemeController()` from `@aureuma/blogkit/theme`
|
|
696
|
+
- `src/lib/types/blog.ts` re-exports library types
|
|
697
|
+
- See `packages/blogkit/README.md` for integration guidance.
|