From 25fd24d2361a18c481d92d8a70cf146a8600b297 Mon Sep 17 00:00:00 2001 From: emil Date: Thu, 14 May 2026 03:19:06 +0300 Subject: [PATCH] =?UTF-8?q?feat(blog+categories):=20Wave=203-5=20=E2=80=94?= =?UTF-8?q?=20blog=20infrastructure,=20categories,=20content,=20navigation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Install @astrojs/rss and setup content collections (blog + generators) - Create BlogLayout with BlogPosting schema, article OG tags, prev/next nav - Create blog post pages EN/RU ([slug].astro) with dynamic routing - Create blog index pages EN/RU with post cards and filtering - Create RSS feeds EN/RU with auto-discovery links - Create generator category pages EN/RU (5 categories each) - Add category navigation pills to homepage - Create Breadcrumbs, RelatedGenerators, RelatedPosts components - Add breadcrumbs to GeneratorLayout and BlogLayout - Wire RelatedGenerators into GeneratorLayout - Wire RelatedPosts into blog post pages - Create 8 EN + 8 RU blog post templates with placeholder content - Add blog link to LanguageSwitcher navigation - Add category and blog translation keys --- .sisyphus/boulder.json | 16 +- .sisyphus/evidence/task-11-collections.txt | 10 + .sisyphus/evidence/task-12-schema.txt | 38 ++++ .sisyphus/evidence/task-13-post.txt | 7 + .sisyphus/evidence/task-14-ru-post.txt | 16 ++ .sisyphus/evidence/task-15-index.txt | 36 +++ .sisyphus/evidence/task-16-rss.txt | 20 ++ .sisyphus/evidence/task-17-category.txt | 26 +++ .sisyphus/evidence/task-18-nav.txt | 16 ++ .sisyphus/evidence/task-19-breadcrumbs.txt | 28 +++ .sisyphus/evidence/task-20-related.txt | 19 ++ .sisyphus/evidence/task-21-related-posts.txt | 24 ++ .sisyphus/evidence/task-22-posts.txt | 25 +++ .sisyphus/evidence/task-23-ru-posts.txt | 20 ++ .sisyphus/evidence/task-24-nav.txt | 16 ++ .sisyphus/evidence/task-26-breadcrumbs.txt | 17 ++ .../notepads/seo-blog-categories/learnings.md | 151 +++++++++++++ .sisyphus/plans/seo-blog-categories.md | 32 +-- package-lock.json | 119 ++++++++++ package.json | 1 + src/components/Breadcrumbs.astro | 44 ++++ src/components/LanguageSwitcher.astro | 7 + src/components/RelatedGenerators.astro | 77 +++++++ src/components/RelatedPosts.astro | 69 ++++++ src/content/blog/en/color-theory-palettes.md | 17 ++ .../blog/en/dice-notation-explained.md | 17 ++ .../blog/en/how-to-create-strong-passwords.md | 17 ++ .../blog/en/psychology-of-randomness.md | 17 ++ src/content/blog/en/random-team-picker.md | 17 ++ src/content/blog/en/rng-in-gaming.md | 17 ++ src/content/blog/en/test-post.md | 12 + src/content/blog/en/uuid-vs-sequential-ids.md | 17 ++ ...-is-cryptographically-secure-randomness.md | 17 ++ src/content/blog/ru/color-theory-guide.md | 17 ++ src/content/blog/ru/dice-notation-guide.md | 17 ++ .../blog/ru/how-to-create-strong-passwords.md | 17 ++ .../blog/ru/psychology-of-randomness.md | 17 ++ src/content/blog/ru/random-team-selection.md | 17 ++ src/content/blog/ru/rng-in-gaming.md | 17 ++ src/content/blog/ru/uuid-vs-sequential-ids.md | 17 ++ ...-is-cryptographically-secure-randomness.md | 17 ++ src/content/config.ts | 21 +- src/i18n/translations.ts | 20 ++ src/layouts/BaseLayout.astro | 11 +- src/layouts/BlogLayout.astro | 210 ++++++++++++++++++ src/layouts/GeneratorLayout.astro | 30 ++- src/pages/blog/[slug].astro | 49 ++++ src/pages/blog/index.astro | 109 +++++++++ .../generators/category/[category].astro | 141 ++++++++++++ src/pages/index.astro | 23 ++ src/pages/rss.xml.ts | 24 ++ src/pages/ru/blog/[slug].astro | 49 ++++ src/pages/ru/blog/index.astro | 109 +++++++++ .../ru/generators/category/[category].astro | 145 ++++++++++++ src/pages/ru/index.astro | 23 ++ src/pages/ru/rss.xml.ts | 24 ++ 56 files changed, 2078 insertions(+), 28 deletions(-) create mode 100644 .sisyphus/evidence/task-11-collections.txt create mode 100644 .sisyphus/evidence/task-12-schema.txt create mode 100644 .sisyphus/evidence/task-13-post.txt create mode 100644 .sisyphus/evidence/task-14-ru-post.txt create mode 100644 .sisyphus/evidence/task-15-index.txt create mode 100644 .sisyphus/evidence/task-16-rss.txt create mode 100644 .sisyphus/evidence/task-17-category.txt create mode 100644 .sisyphus/evidence/task-18-nav.txt create mode 100644 .sisyphus/evidence/task-19-breadcrumbs.txt create mode 100644 .sisyphus/evidence/task-20-related.txt create mode 100644 .sisyphus/evidence/task-21-related-posts.txt create mode 100644 .sisyphus/evidence/task-22-posts.txt create mode 100644 .sisyphus/evidence/task-23-ru-posts.txt create mode 100644 .sisyphus/evidence/task-24-nav.txt create mode 100644 .sisyphus/evidence/task-26-breadcrumbs.txt create mode 100644 src/components/Breadcrumbs.astro create mode 100644 src/components/RelatedGenerators.astro create mode 100644 src/components/RelatedPosts.astro create mode 100644 src/content/blog/en/color-theory-palettes.md create mode 100644 src/content/blog/en/dice-notation-explained.md create mode 100644 src/content/blog/en/how-to-create-strong-passwords.md create mode 100644 src/content/blog/en/psychology-of-randomness.md create mode 100644 src/content/blog/en/random-team-picker.md create mode 100644 src/content/blog/en/rng-in-gaming.md create mode 100644 src/content/blog/en/test-post.md create mode 100644 src/content/blog/en/uuid-vs-sequential-ids.md create mode 100644 src/content/blog/en/what-is-cryptographically-secure-randomness.md create mode 100644 src/content/blog/ru/color-theory-guide.md create mode 100644 src/content/blog/ru/dice-notation-guide.md create mode 100644 src/content/blog/ru/how-to-create-strong-passwords.md create mode 100644 src/content/blog/ru/psychology-of-randomness.md create mode 100644 src/content/blog/ru/random-team-selection.md create mode 100644 src/content/blog/ru/rng-in-gaming.md create mode 100644 src/content/blog/ru/uuid-vs-sequential-ids.md create mode 100644 src/content/blog/ru/what-is-cryptographically-secure-randomness.md create mode 100644 src/layouts/BlogLayout.astro create mode 100644 src/pages/blog/[slug].astro create mode 100644 src/pages/blog/index.astro create mode 100644 src/pages/generators/category/[category].astro create mode 100644 src/pages/rss.xml.ts create mode 100644 src/pages/ru/blog/[slug].astro create mode 100644 src/pages/ru/blog/index.astro create mode 100644 src/pages/ru/generators/category/[category].astro create mode 100644 src/pages/ru/rss.xml.ts diff --git a/.sisyphus/boulder.json b/.sisyphus/boulder.json index 438994f..178e64c 100644 --- a/.sisyphus/boulder.json +++ b/.sisyphus/boulder.json @@ -157,7 +157,7 @@ "plan_name": "seo-blog-categories", "status": "active", "started_at": "2026-05-13T23:32:06.345Z", - "updated_at": "2026-05-13T23:47:20.362Z", + "updated_at": "2026-05-14T00:06:43.314Z", "session_ids": [ "ses_1de6ede59ffexUwt5C0sddEWwR" ], @@ -183,12 +183,12 @@ "task_key": "todo:7", "task_label": "7", "task_title": "Update generatorSchema.ts with category field", - "session_id": "ses_1dc44f7c9ffeRvYIFc2EOUSbNd", + "session_id": "ses_1dc34addfffegfOdNPOQJJYU66", "agent": "Sisyphus-Junior", - "category": "quick", + "category": "visual-engineering", "started_at": "2026-05-13T23:42:40.563Z", "status": "running", - "updated_at": "2026-05-13T23:47:20.363Z" + "updated_at": "2026-05-14T00:06:43.315Z" } } } @@ -196,7 +196,7 @@ "active_plan": "/home/emil/Desktop/Coding/AI/Randify.pro/.sisyphus/plans/seo-blog-categories.md", "started_at": "2026-05-13T23:32:06.345Z", "status": "active", - "updated_at": "2026-05-13T23:47:20.362Z", + "updated_at": "2026-05-14T00:06:43.314Z", "session_ids": [ "ses_1de6ede59ffexUwt5C0sddEWwR" ], @@ -222,12 +222,12 @@ "task_key": "todo:7", "task_label": "7", "task_title": "Update generatorSchema.ts with category field", - "session_id": "ses_1dc44f7c9ffeRvYIFc2EOUSbNd", + "session_id": "ses_1dc34addfffegfOdNPOQJJYU66", "agent": "Sisyphus-Junior", - "category": "quick", + "category": "visual-engineering", "started_at": "2026-05-13T23:42:40.563Z", "status": "running", - "updated_at": "2026-05-13T23:47:20.363Z" + "updated_at": "2026-05-14T00:06:43.315Z" } }, "agent": "atlas" diff --git a/.sisyphus/evidence/task-11-collections.txt b/.sisyphus/evidence/task-11-collections.txt new file mode 100644 index 0000000..f0e354c --- /dev/null +++ b/.sisyphus/evidence/task-11-collections.txt @@ -0,0 +1,10 @@ +Task 11: Install @astrojs/rss and set up content collections config + +- Package installed: @astrojs/rss (added 9 packages, 511 total) +- File updated: src/content/config.ts + - Imported z from astro:content + - Added blog collection with type: "content" + - Blog schema fields: title (max 120), description (max 160), pubDate, modDate (optional), draft (default false), lang (en/ru), category (tutorial/guide/news/tips), tags (default []), ogImage (optional, image()), relatedGenerators (optional), relatedPosts (optional) + - Preserved existing generators collection (type: "data", schema: generatorSchema) +- Directories created: src/content/blog/en/ and src/content/blog/ru/ +- Build verification: npm run build passed with 64 pages, 0 errors diff --git a/.sisyphus/evidence/task-12-schema.txt b/.sisyphus/evidence/task-12-schema.txt new file mode 100644 index 0000000..741079d --- /dev/null +++ b/.sisyphus/evidence/task-12-schema.txt @@ -0,0 +1,38 @@ +Task 12: BlogLayout.astro with BlogPosting JSON-LD and Article OG Meta Tags + +Verification: npm run build — PASSED (64 pages built) + +File: src/layouts/BlogLayout.astro + +Features implemented: +1. Wraps BaseLayout, passing title, description, ogImage. +2. Injects BlogPosting JSON-LD schema via slot="head" with: + - @type: BlogPosting + - headline (from title prop) + - author: Organization { name: "Randify" } + - publisher: Organization { name: "Randify", logo: ImageObject } + - datePublished (ISO 8601) + - dateModified (ISO 8601, falls back to datePublished) + - url (canonical) + - description + - inLanguage +3. OG type set to "article" via in slot="head". +4. Article-specific meta tags added: + - article:published_time + - article:modified_time +5. Styled container: max-w-2xl mx-auto, matching GeneratorLayout spacing. +6. Header with title, accent dot, publication date, and conditional "Updated" label. +7. Prev/next post navigation with bilingual labels (EN/RU), arrow icons, and focus rings. +8. Named slot "related" for RelatedPosts component. + +Props accepted: +- title: string +- description: string +- pubDate: Date | string +- modDate?: Date | string +- ogImage?: string +- lang?: Lang +- prevPost?: { slug: string; title: string } +- nextPost?: { slug: string; title: string } + +Build output: 64 pages, 0 errors. diff --git a/.sisyphus/evidence/task-13-post.txt b/.sisyphus/evidence/task-13-post.txt new file mode 100644 index 0000000..3e2162a --- /dev/null +++ b/.sisyphus/evidence/task-13-post.txt @@ -0,0 +1,7 @@ +Task 13: EN blog post page ([slug].astro) +- Build: PASS (77 pages) +- Generated: dist/blog/test-post/index.html +- Verified: post title present in HTML +- Verified: BlogPosting JSON-LD schema present +- Verified: article:published_time meta tag present +- Slug derived from post.id with en/ prefix and .md extension stripped diff --git a/.sisyphus/evidence/task-14-ru-post.txt b/.sisyphus/evidence/task-14-ru-post.txt new file mode 100644 index 0000000..76e9ebd --- /dev/null +++ b/.sisyphus/evidence/task-14-ru-post.txt @@ -0,0 +1,16 @@ +Task 14: Create RU blog post page src/pages/ru/blog/[slug].astro + +Build result: PASS +Pages built: 77 +RU blog post page: compiled successfully (no RU blog posts yet, so no static pages generated) +EN blog post page: /blog/test-post/index.html generated + +Files created/modified: +- src/pages/ru/blog/[slug].astro (created) +- src/layouts/BlogLayout.astro (fixed locale-aware prev/next links) + +Verification: +- npm run build exited with code 0 +- No TypeScript or Astro errors +- RU [slug].astro correctly filters getCollection("blog") by lang === "ru" +- BlogLayout prev/next navigation updated to use locale-aware paths (/ru/blog/ for RU, /blog/ for EN) diff --git a/.sisyphus/evidence/task-15-index.txt b/.sisyphus/evidence/task-15-index.txt new file mode 100644 index 0000000..4d11615 --- /dev/null +++ b/.sisyphus/evidence/task-15-index.txt @@ -0,0 +1,36 @@ +Task 15: Blog Index Pages — Evidence +====================================== + +Build Status: PASS (76 pages, exit code 0) + +Files Created: +- src/pages/blog/index.astro +- src/pages/ru/blog/index.astro + +Files Modified: +- src/i18n/translations.ts (added blogDesc, readMore, noPosts keys for EN + RU) + +Build Output Verification: +- dist/blog/index.html (6893 bytes) +- dist/ru/blog/index.html (7342 bytes) + +EN Page Features: +- Queries getCollection("blog"), filters lang === "en" and draft !== true +- Sorts by pubDate descending +- Links to /blog/[slug]/ +- Date formatting: toLocaleDateString("en-US", ...) +- JSON-LD Blog schema with blogPost array + +RU Page Features: +- Queries getCollection("blog"), filters lang === "ru" and draft !== true +- Sorts by pubDate descending +- Links to /ru/blog/[slug]/ +- Date formatting: toLocaleDateString("ru-RU", ...) +- JSON-LD Blog schema with blogPost array + +Both pages: +- Use BaseLayout with title and description props +- Include OG/Twitter Card meta tags (inherited from BaseLayout) +- Include canonical + hreflang alternates (inherited from BaseLayout) +- Show empty state "No posts yet" / "Пока нет записей." when collection is empty +- Display category badge + tag badges per post card diff --git a/.sisyphus/evidence/task-16-rss.txt b/.sisyphus/evidence/task-16-rss.txt new file mode 100644 index 0000000..4676c58 --- /dev/null +++ b/.sisyphus/evidence/task-16-rss.txt @@ -0,0 +1,20 @@ +Task 16: RSS Feeds + +Files created: +- src/pages/rss.xml.ts (EN feed) +- src/pages/ru/rss.xml.ts (RU feed) + +File modified: +- src/layouts/BaseLayout.astro (added for both EN and RU feeds) + +Build: PASS (npm run build exited 0) + +Generated feeds: +- dist/rss.xml exists (287 bytes) +- dist/ru/rss.xml exists (404 bytes) + +Feed content verified: +- EN: title="Randify Blog", language="en", description present, link=https://randify.pro/ +- RU: title="Блог Randify", language="ru", description present, link=https://randify.pro/ + +Note: Feeds are currently empty because no blog posts exist in src/content/blog/ yet. When posts are added with lang="en"/"ru" and draft !== true, they will appear automatically. diff --git a/.sisyphus/evidence/task-17-category.txt b/.sisyphus/evidence/task-17-category.txt new file mode 100644 index 0000000..553ed2d --- /dev/null +++ b/.sisyphus/evidence/task-17-category.txt @@ -0,0 +1,26 @@ +Task 17: Category Pages for Generators +====================================== + +Build Result: PASS +Pages built: 76 + +EN Category Pages Created: +- dist/generators/category/gaming/index.html +- dist/generators/category/security/index.html +- dist/generators/category/decision-making/index.html +- dist/generators/category/creative/index.html +- dist/generators/category/utility/index.html + +RU Category Pages Created: +- dist/ru/generators/category/gaming/index.html +- dist/ru/generators/category/security/index.html +- dist/ru/generators/category/decision-making/index.html +- dist/ru/generators/category/creative/index.html +- dist/ru/generators/category/utility/index.html + +Verification: +- EN gaming page contains: "Gaming generators for tabletop RPGs" and generator titles (Lottery, Rock Paper Scissors, etc.) +- RU gaming page contains: "Игровые генераторы для настольных RPG" and generator titles (Колесо фортуны, Лотерея, etc.) +- All 5 categories render correctly with getStaticPaths +- Breadcrumb JSON-LD schema included on each page +- Generators filtered dynamically by category field from src/data/generators.ts diff --git a/.sisyphus/evidence/task-18-nav.txt b/.sisyphus/evidence/task-18-nav.txt new file mode 100644 index 0000000..432e405 --- /dev/null +++ b/.sisyphus/evidence/task-18-nav.txt @@ -0,0 +1,16 @@ +Task 18: Category Navigation Pills on Homepage + +Files modified: +- src/pages/index.astro +- src/pages/ru/index.astro +- src/i18n/translations.ts + +Build result: PASS (85 pages, 0 errors) + +Verification: +- dist/index.html contains category navigation pills +- dist/ru/index.html contains localized category navigation pills +- All 5 categories present: Gaming (6), Security (3), Decision Making (4), Creative (5), Utility (10) +- Links point to /generators/category/[category]/ (EN) and /ru/generators/category/[category]/ (RU) +- Pills styled with Tailwind: rounded-full, bg-zinc-800/60, border-zinc-700/50, hover:bg-accent/20, hover:text-accent +- Responsive flex-wrap layout diff --git a/.sisyphus/evidence/task-19-breadcrumbs.txt b/.sisyphus/evidence/task-19-breadcrumbs.txt new file mode 100644 index 0000000..00b453f --- /dev/null +++ b/.sisyphus/evidence/task-19-breadcrumbs.txt @@ -0,0 +1,28 @@ +Task 19: Create Breadcrumbs.astro Component — Evidence +===================================================== + +1. File Created +--------------- +Path: src/components/Breadcrumbs.astro + +2. Component Specification +-------------------------- +- Props interface: { items: Array<{ label: string, href?: string }> } +- Renders