- Add back-to-generators link on EN and RU blog index pages - Update all 16 blog post dates to 2026-05-14 with staggered times - Sync EN and RU post dates so matching topics have identical timestamps
51 KiB
SEO + Blog + Categories for Randify.pro
TL;DR
Quick Summary: Improve Randify.pro's SEO and content depth to pass Yandex Partner Network (РСЯ) moderation and attract organic search traffic. Fix critical SEO gaps (Open Graph, hreflang, thin content signals), add a bilingual blog with Astro Content Collections, categorize all 28 generators, and enrich page structure with breadcrumbs and related content.
Deliverables:
- Fixed SEO metadata (OG tags, Twitter Cards, x-default hreflang, sitemap i18n)
- Blog infrastructure (content collections, layouts, pages, RSS feeds for EN + RU)
- 8 blog post templates with correct frontmatter (EN + RU)
- 5 category pages for generators (EN + RU)
- Visual breadcrumbs component
- Related generators + related posts components
- Custom 404 page
- Fixed data integrity issues (duplicate JSON keys)
Estimated Effort: Large Parallel Execution: YES — 6 waves Critical Path: Wave 1 (fixes) → Wave 2 (schema) → Wave 3 (blog) → Wave 4 (categories) → Wave 5 (content) → Wave FINAL
Context
Original Request
User was rejected by Yandex Partner Network (РСЯ) without reason specified. Wants organic search traffic instead of paid ads. Needs SEO improvements + blog + generator categorization.
Interview Summary
Key Discussions:
- Rejection reason unknown; SEO audit identified thin content as primary suspect
- Blog articles about randomness topics; user will generate content via neural networks
- 5 categories confirmed: Gaming, Security, Decision Making, Creative, Utility
- Initial batch: 8 blog post templates with placeholder content
Research Findings:
- SEO audit (explore agent): 8 CRITICAL issues including missing OG tags, thin content, duplicate JSON keys, missing
<main>landmarks - Blog best practices (librarian): Astro Content Collections with Zod,
/blog/[slug]routing,@astrojs/rss,BlogPostingschema
Metis Review
- No gaps identified after user confirmation of categories and content workflow
Work Objectives
Core Objective
Improve Randify.pro's SEO and content depth to pass Yandex Partner Network (РСЯ) moderation and attract organic search traffic.
Concrete Deliverables
src/layouts/BaseLayout.astro— updated with OG tags, Twitter Cards, x-default hreflangastro.config.mjs— sitemap with i18n hreflang annotationssrc/content/config.ts— content collections with blog + generator schemassrc/lib/generator-schema.ts— updated withcategoryfield- 28 updated
src/content/generators/*.jsonfiles with category assignments - Fixed
dice.json,list.json,colors.json(duplicate keys merged) src/pages/blog/[slug].astro+src/pages/ru/blog/[slug].astro— blog post pagessrc/pages/blog/index.astro+src/pages/ru/blog/index.astro— blog index pagessrc/pages/rss.xml.ts+src/pages/ru/rss.xml.ts— RSS feedssrc/layouts/BlogLayout.astro— blog-specific layout withBlogPostingschemasrc/components/Breadcrumbs.astro— visual breadcrumb navigationsrc/components/RelatedGenerators.astro— cross-link box for generator pagessrc/components/RelatedPosts.astro— tag-based related posts for blog- 5 category pages:
src/pages/generators/category/[category].astro+ RU mirror src/pages/404.astro+src/pages/ru/404.astro— custom 404 pages- 8 blog post templates in
src/content/blog/en/andsrc/content/blog/ru/
Definition of Done
npm run build→ 70+ pages (62 existing + blog + categories + 404)npm run lint→ 0 errors- OG tags present on all page types (verified via grep on build output)
- RSS feeds accessible at
/rss.xmland/ru/rss.xml - All 28 generators have category assigned
- No duplicate keys in any generator JSON
- Blog index and post pages render correctly
- Category pages filter generators correctly
Must Have
- Open Graph and Twitter Card meta tags on every page
- x-default hreflang annotation
- Sitemap with hreflang alternates
- Blog content collections with Zod schema
- RSS feeds for both EN and RU
- 5 category pages with generator filtering
- Visual breadcrumbs on generator and blog pages
- Related generators on each generator page
- Custom 404 page with navigation
- Fixed duplicate JSON keys in dice.json, list.json, colors.json
<main>landmarks on about/privacy pages- Blog post templates with correct frontmatter structure
Must NOT Have (Guardrails)
- Do NOT remove YandexRTB or AdBanner components
- Do NOT change generator interactive behavior
- Do NOT break existing build (must maintain all existing pages)
- Do NOT add external SEO tools or services
- Do NOT write full blog article content (user generates via neural networks)
- Do NOT use dynamic
[slug].astrofor generator pages (maintain separate EN/RU files)
Verification Strategy
Test Decision
- Infrastructure exists: YES (vitest, eslint)
- Automated tests: NO (infrastructure work, no new utilities requiring TDD)
- Agent QA: YES — every task includes agent-executed verification scenarios
QA Policy
Every task MUST include agent-executed QA scenarios.
- Build verification:
npm run build→ count pages, check for errors - Lint verification:
npm run lint→ 0 errors - HTML inspection: grep build output for OG tags, schema markup, hreflang
- Functional verification: curl or playwright to verify blog/category pages render
Execution Strategy
Parallel Execution Waves
Wave 1 (Foundation fixes — can start immediately):
├── Task 1: Fix duplicate JSON keys in 3 generator files [quick]
├── Task 2: Fix <main> landmarks on about/privacy pages [quick]
├── Task 3: Fix ad placement on homepage [quick]
├── Task 4: Add x-default hreflang to BaseLayout [quick]
├── Task 5: Fix sitemap i18n config in astro.config.mjs [quick]
└── Task 6: Add Open Graph + Twitter Card meta tags [quick]
Wave 2 (Schema + data — after Wave 1):
├── Task 7: Update generatorSchema.ts with category field [quick]
├── Task 8: Update all 28 generator JSON files with categories [quick]
├── Task 9: Add Organization schema to BaseLayout [quick]
└── Task 10: Create custom 404 page [visual-engineering]
Wave 3 (Blog infrastructure — after Wave 2):
├── Task 11: Install @astrojs/rss, set up content collections config [quick]
├── Task 12: Create BlogLayout.astro with BlogPosting schema [visual-engineering]
├── Task 13: Create blog post page EN ([slug].astro) [unspecified-high]
├── Task 14: Create blog post page RU ([slug].astro) [unspecified-high]
├── Task 15: Create blog index pages (EN + RU) [unspecified-high]
└── Task 16: Create RSS feeds (EN + RU) [quick]
Wave 4 (Categories + content + related components — after Wave 2 + 3):
├── Task 17: Create category pages for generators (EN + RU) [unspecified-high]
├── Task 18: Add category navigation to homepage [visual-engineering]
├── Task 19: Create Breadcrumbs component [visual-engineering]
├── Task 20: Create RelatedGenerators component [unspecified-high]
├── Task 21: Create RelatedPosts component [unspecified-high]
├── Task 22: Create 8 blog post templates EN [writing]
├── Task 23: Create 8 blog post templates RU [writing]
└── Task 24: Add blog link to navigation [quick]
Wave 5 (Integration — after Wave 4):
├── Task 25: Add related generators to generator pages [unspecified-high]
└── Task 26: Add breadcrumbs to generator and blog layouts [unspecified-high]
Wave FINAL (After ALL tasks — 4 parallel reviews, then user okay):
├── Task F1: Plan compliance audit (oracle)
├── Task F2: Code quality review (unspecified-high)
├── Task F3: Real manual QA (unspecified-high)
└── Task F4: Scope fidelity check (deep)
-> Present results -> Get explicit user okay
Critical Path: Wave 1 → Wave 2 → Wave 3 + Wave 4 (parallel) → Wave 5 → F1-F4 → user okay
Parallel Speedup: Waves 3 and 4 run in parallel after Wave 2. Wave 4 absorbs blog content tasks.
Max Concurrent: 6 (Wave 1), 4 (Wave 2), 6 (Wave 3), 8 (Wave 4), 2 (Wave 5)
Dependency Matrix
- 1-6: None → 7-10
- 7-10: 1-6 → 11-24
- 11-16: 7-10 → 22-24, 25-26
- 17-21: 7-10, 11-16 → 25-26
- 22-24: 11-16 → 25-26 (content ready for integration)
- 25-26: 17-21, 22-24 → F1-F4
- F1-F4: 25-26 → user okay
TODOs
-
1. Fix duplicate JSON keys in 3 generator files
What to do:
- Read
src/content/generators/dice.json,list.json,colors.json - Each file has duplicate
faqandruFaqkeys (second pair overwrites first) - Merge both FAQ blocks into single
faqand singleruFaqarrays - Verify with
npm run buildthat no Zod.strict()errors occur
Must NOT do:
- Do NOT delete any FAQ content — merge both blocks
- Do NOT change other generator JSON files
Recommended Agent Profile:
- Category:
quick
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 1
- Blocks: None
- Blocked By: None
References:
src/content/generators/dice.json— duplicate keys at lines 29-37 and 53-57src/content/generators/list.json— duplicate keys at lines 27-31 and 48-52src/content/generators/colors.json— duplicate keys at lines 26-35 and 46-55src/lib/generator-schema.ts—.strict()will throw on unknown fields
Acceptance Criteria:
dice.json,list.json,colors.jsonhave singlefaqand singleruFaqkeys- All original FAQ items preserved (merged, not deleted)
npm run build→ PASS (0 Zod errors)
QA Scenarios:
Scenario: Build passes after JSON fix Tool: Bash Preconditions: None Steps: 1. Run: npm run build 2. Assert: no Zod validation errors for dice/list/colors Expected Result: 62 pages built successfully Evidence: .sisyphus/evidence/task-1-build.txtCommit: YES (Wave 1)
- Read
-
2. Fix
<main>landmarks on about/privacy pagesWhat to do:
- Update
src/pages/about.astroandsrc/pages/ru/about.astro: wrap primary content in<main> - Update
src/pages/privacy.astroandsrc/pages/ru/privacy.astro: wrap primary content in<main> - Ensure
<main>contains the actual content, not the breadcrumb nav
Must NOT do:
- Do NOT change content or styling
- Do NOT affect generator pages (they already have
<main>)
Recommended Agent Profile:
- Category:
quick
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 1
- Blocks: None
- Blocked By: None
References:
src/pages/about.astro— lines 21-94, no<main>tagsrc/pages/privacy.astro— lines 11-84, no<main>tagsrc/layouts/GeneratorLayout.astro— lines 113-116, correct<main>usage
Acceptance Criteria:
- About page (EN + RU) has
<main>landmark - Privacy page (EN + RU) has
<main>landmark npm run lint→ PASS
QA Scenarios:
Scenario: HTML validation shows main landmarks Tool: Bash Preconditions: None Steps: 1. Run: npm run build 2. Grep dist/about/index.html for '<main>' 3. Grep dist/privacy/index.html for '<main>' 4. Grep dist/ru/about/index.html for '<main>' Expected Result: Each file contains exactly one <main> tag Evidence: .sisyphus/evidence/task-2-main.txtCommit: YES (Wave 1)
- Update
-
3. Fix ad placement on homepage
What to do:
- In
src/pages/index.astro, move<YandexRTB />from line 50 (before<main>) to after the<main>catalog content - Ensure ad appears below the generator grid, not above it
Must NOT do:
- Do NOT remove YandexRTB component
- Do NOT change YandexRTB component itself
Recommended Agent Profile:
- Category:
quick
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 1
- Blocks: None
- Blocked By: None
References:
src/pages/index.astro— line 50:<YandexRTB />before<main>src/components/YandexRTB.astro— ad block component
Acceptance Criteria:
- YandexRTB renders after
<main>content on homepage npm run build→ PASS
QA Scenarios:
Scenario: Ad placement is after main content Tool: Bash Preconditions: None Steps: 1. Run: npm run build 2. Read dist/index.html 3. Assert: <main> appears before YandexRTB ad block div Expected Result: Ad block is after the generator catalog grid Evidence: .sisyphus/evidence/task-3-ad.txtCommit: YES (Wave 1)
- In
-
4. Add x-default hreflang to BaseLayout
What to do:
- In
src/layouts/BaseLayout.astro, add<link rel="alternate" hreflang="x-default" href={enUrl} />after the existing en/ru hreflang links - The x-default should point to the English version as the fallback
Must NOT do:
- Do NOT remove existing en/ru hreflang links
- Do NOT change canonical URL logic
Recommended Agent Profile:
- Category:
quick
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 1
- Blocks: None
- Blocked By: None
References:
src/layouts/BaseLayout.astro— lines 48-50: canonical + hreflang- Google hreflang guidelines: x-default points to fallback page
Acceptance Criteria:
- x-default hreflang link present in all page
<head>elements npm run build→ PASS
QA Scenarios:
Scenario: x-default hreflang present in output Tool: Bash Preconditions: None Steps: 1. Run: npm run build 2. Grep dist/index.html for 'hreflang="x-default"' 3. Grep dist/generators/dice/index.html for 'hreflang="x-default"' Expected Result: Both files contain x-default hreflang link Evidence: .sisyphus/evidence/task-4-hreflang.txtCommit: YES (Wave 1)
- In
-
5. Fix sitemap i18n config
What to do:
- Update
astro.config.mjs: passi18noption tositemap()integration - Configuration:
sitemap({ i18n: { defaultLocale: "en", locales: { en: "en-US", ru: "ru-RU" } } }) - Verify build output includes
<xhtml:link rel="alternate" hreflang="...">in sitemap
Must NOT do:
- Do NOT change other sitemap options
- Do NOT remove
@astrojs/sitemap
Recommended Agent Profile:
- Category:
quick
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 1
- Blocks: None
- Blocked By: None
References:
astro.config.mjs— line 7:sitemap()with no options@astrojs/sitemapi18n docs: https://docs.astro.build/en/guides/integrations-guide/sitemap/#i18n
Acceptance Criteria:
dist/sitemap-0.xmlcontains<xhtml:link rel="alternate" hreflang="...">entriesnpm run build→ PASS
QA Scenarios:
Scenario: Sitemap contains hreflang alternates Tool: Bash Preconditions: None Steps: 1. Run: npm run build 2. Read dist/sitemap-0.xml 3. Assert: contains '<xhtml:link rel="alternate"' for both en and ru Expected Result: hreflang annotations present in sitemap XML Evidence: .sisyphus/evidence/task-5-sitemap.txtCommit: YES (Wave 1)
- Update
-
6. Add Open Graph + Twitter Card meta tags
What to do:
- Extend
src/layouts/BaseLayout.astroto accept optionalogImageandarticleprops - Add OG tags:
og:site_name,og:locale,og:type,og:title,og:description,og:url,og:image - Add Twitter Card tags:
twitter:card,twitter:title,twitter:description,twitter:image - Create default OG image (1200x630) and store in
public/og-default.jpg - For generator pages, pass
ogImagefrom GeneratorLayout
Must NOT do:
- Do NOT remove existing meta tags (description, canonical, etc.)
- Do NOT change existing
<head>structure beyond adding new meta tags
Recommended Agent Profile:
- Category:
visual-engineering
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 1
- Blocks: None
- Blocked By: None
References:
src/layouts/BaseLayout.astro— lines 36-64: current<head>content- astro-paper Layout.astro: https://github.com/satnaing/astro-paper/blob/f3005328e548805226aba54414122c7174645e83/src/layouts/Layout.astro#L71-L106
- AstroWind Metadata.astro: https://github.com/arthelokyo/astrowind/blob/32a3bb96a000c2f5416ea1f795d18666c75ec713/src/components/common/Metadata.astro
Acceptance Criteria:
- OG tags present in all built HTML pages
- Twitter Card tags present in all built HTML pages
- Default OG image exists at
public/og-default.jpg npm run build→ PASS
QA Scenarios:
Scenario: OG tags present on homepage Tool: Bash Preconditions: None Steps: 1. Run: npm run build 2. Grep dist/index.html for 'property="og:title"' 3. Grep dist/index.html for 'property="og:description"' 4. Grep dist/index.html for 'property="og:image"' 5. Grep dist/index.html for 'property="twitter:card"' Expected Result: All OG and Twitter tags present Evidence: .sisyphus/evidence/task-6-og.txt Scenario: OG tags present on generator page Tool: Bash Preconditions: None Steps: 1. Grep dist/generators/dice/index.html for 'property="og:title"' 2. Assert: og:title contains "Dice Roller" Expected Result: OG tags populated with generator-specific data Evidence: .sisyphus/evidence/task-6-og-gen.txtCommit: YES (Wave 1)
- Extend
-
7. Update generatorSchema.ts with category field
What to do:
- Add
categoryfield togeneratorSchemainsrc/lib/generator-schema.ts - Type:
z.enum(["gaming", "security", "decision-making", "creative", "utility"]) - Add
categoryto the TypeScriptGeneratortype inference - Ensure
.strict()still works (category must be in all JSON files before build)
Must NOT do:
- Do NOT remove
.strict()from schema - Do NOT add other new fields
Recommended Agent Profile:
- Category:
quick
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 2
- Blocks: 8
- Blocked By: 1-6
References:
src/lib/generator-schema.ts— current schema with.strict()src/data/generators.ts— imports and usesgeneratorSchema.parse()
Acceptance Criteria:
categoryfield added to schema- TypeScript
Generatortype includescategory npm run lint→ PASS
QA Scenarios:
Scenario: Schema compiles without errors Tool: Bash Preconditions: None Steps: 1. Run: npm run lint 2. Assert: 0 errors Expected Result: lint passes Evidence: .sisyphus/evidence/task-7-schema.txtCommit: YES (Wave 2)
- Add
-
8. Update all 28 generator JSON files with categories
What to do:
- Add
"category"field to ALL 28 files insrc/content/generators/*.json - Categories per generator (confirmed by user):
- gaming: dice, cards, lottery, wheel, magic8ball, rps
- security: password, hash, uuid
- decision-making: coin, yesno, weighted, teams
- creative: colors, gradient, palette, fontpair, lorem
- utility: numbers, date, time, shuffler, letter, names, meal, emoji, country, list
- Verify
npm run buildpasses after all updates
Must NOT do:
- Do NOT change any other fields in JSON files
- Do NOT skip any generator file
Recommended Agent Profile:
- Category:
quick
Parallelization:
- Can Run In Parallel: YES (after Task 7)
- Parallel Group: Wave 2
- Blocks: 17-18
- Blocked By: 7
References:
src/content/generators/*.json— all 28 filessrc/lib/generator-schema.ts— updated schema with category field
Acceptance Criteria:
- All 28 JSON files have
"category"field npm run build→ PASS (62 pages, 0 Zod errors)
QA Scenarios:
Scenario: Build passes with all categories Tool: Bash Preconditions: Task 7 completed Steps: 1. Run: npm run build 2. Assert: 62 pages built, no Zod validation errors Expected Result: Build succeeds Evidence: .sisyphus/evidence/task-8-build.txtCommit: YES (Wave 2)
- Add
-
9. Add Organization schema to BaseLayout
What to do:
- Add
OrganizationJSON-LD schema tosrc/layouts/BaseLayout.astro - Include:
@type: "Organization",name: "Randify",url,logo - Inject via
<script type="application/ld+json">in<head>
Must NOT do:
- Do NOT remove existing WebPage schema
- Do NOT hardcode sensitive data
Recommended Agent Profile:
- Category:
quick
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 2
- Blocks: None
- Blocked By: 1-6
References:
src/layouts/BaseLayout.astro— existing WebPage schema (lines 24-31)- Schema.org Organization docs: https://schema.org/Organization
Acceptance Criteria:
- Organization schema present on all pages
npm run build→ PASS
QA Scenarios:
Scenario: Organization schema in output Tool: Bash Preconditions: None Steps: 1. Run: npm run build 2. Grep dist/index.html for '"@type":"Organization"' Expected Result: Organization schema found Evidence: .sisyphus/evidence/task-9-org.txtCommit: YES (Wave 2)
- Add
-
10. Create custom 404 page
What to do:
- Create
src/pages/404.astrowith BaseLayout, friendly message, link to homepage, link to blog - Create
src/pages/ru/404.astro— copy EN file (identical content due to@/aliases and locale detection) - Use
T.notFoundTitle,T.notFoundMessage,T.backToHomefrom translations
Must NOT do:
- Do NOT add complex logic
- Do NOT break existing routing
Recommended Agent Profile:
- Category:
visual-engineering
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 2
- Blocks: None
- Blocked By: 1-6
References:
src/layouts/BaseLayout.astro— layout with i18nsrc/i18n/translations.ts— add not-found translation keys- Existing about.astro pattern for page structure
Acceptance Criteria:
src/pages/404.astroexists and renderssrc/pages/ru/404.astroexists and rendersnpm run build→ PASS (64 pages: 62 + 2x 404)
QA Scenarios:
Scenario: 404 page builds correctly Tool: Bash Preconditions: None Steps: 1. Run: npm run build 2. Assert: dist/404/index.html exists 3. Assert: dist/ru/404/index.html exists 4. Grep dist/404/index.html for 'not found' or equivalent Expected Result: Both 404 pages built with friendly message Evidence: .sisyphus/evidence/task-10-404.txtCommit: YES (Wave 2)
- Create
-
11. Install @astrojs/rss, set up content collections config
What to do:
- Run
npm install @astrojs/rss - Create
src/content/config.tswith blog collection schema:import { defineCollection, z } from "astro:content"; import { generatorSchema } from "@/lib/generator-schema"; const generators = defineCollection({ type: "data", schema: generatorSchema }); const blog = defineCollection({ type: "content", schema: ({ image }) => z.object({ title: z.string().max(120), description: z.string().max(160), pubDate: z.date(), modDate: z.date().optional(), draft: z.boolean().default(false), lang: z.enum(["en", "ru"]), category: z.enum(["tutorial", "guide", "news", "tips"]), tags: z.array(z.string()).default([]), ogImage: image().optional(), relatedGenerators: z.array(z.string()).optional(), relatedPosts: z.array(z.string()).optional(), }), }); export const collections = { generators, blog }; - Create
src/content/blog/en/andsrc/content/blog/ru/directories
Must NOT do:
- Do NOT change existing generator collection definition
- Do NOT remove
src/data/generators.ts(keep existing loader)
Recommended Agent Profile:
- Category:
quick
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 3
- Blocks: 12-16, 22-23
- Blocked By: 7-10
References:
src/lib/generator-schema.ts— existing schema- Astro v4 Content Collections docs
package.json— add@astrojs/rssto dependencies
Acceptance Criteria:
@astrojs/rssinstalledsrc/content/config.tscreated with blog + generator collectionsnpm run build→ PASS
QA Scenarios:
Scenario: Content collections compile Tool: Bash Preconditions: None Steps: 1. Run: npm run build 2. Assert: no TypeScript or Zod errors Expected Result: Build succeeds Evidence: .sisyphus/evidence/task-11-collections.txtCommit: YES (Wave 3)
- Run
-
12. Create BlogLayout.astro with BlogPosting schema
What to do:
- Create
src/layouts/BlogLayout.astro - Wraps BaseLayout with blog-specific SEO:
BlogPostingJSON-LD schema withheadline,author,publisher,datePublished,dateModified- OG type:
article(notwebsite) - Article-specific meta:
article:published_time,article:modified_time
- Accept props:
title,description,pubDate,modDate,ogImage,lang
Must NOT do:
- Do NOT duplicate BaseLayout head elements
- Do NOT remove existing OG tags from BaseLayout
Recommended Agent Profile:
- Category:
visual-engineering
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 3
- Blocks: 13-15
- Blocked By: 11
References:
src/layouts/BaseLayout.astro— existing layoutsrc/layouts/GeneratorLayout.astro— example of wrapping BaseLayout- astro-paper Layout.astro: https://github.com/satnaing/astro-paper/blob/f3005328e548805226aba54414122c7174645e83/src/layouts/Layout.astro
Acceptance Criteria:
- BlogLayout.astro exists and compiles
- BlogPosting schema present in output HTML
npm run build→ PASS
QA Scenarios:
Scenario: BlogPosting schema present Tool: Bash Preconditions: Task 11 completed Steps: 1. Run: npm run build (after creating a test blog post) 2. Grep dist/blog/test-post/index.html for '"@type":"BlogPosting"' Expected Result: BlogPosting schema found Evidence: .sisyphus/evidence/task-12-schema.txtCommit: YES (Wave 3)
- Create
-
13. Create blog post page EN ([slug].astro)
What to do:
- Create
src/pages/blog/[slug].astro - Use
getStaticPathsto querygetCollection("blog")filtered bylang === "en" - Render post using
BlogLayoutwith post data - Include prev/next navigation (previous and next posts by date)
- Include RelatedPosts component (Task 21)
Must NOT do:
- Do NOT import generator components (safe for dynamic routes)
- Do NOT hardcode post slugs
Recommended Agent Profile:
- Category:
unspecified-high
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 3
- Blocks: 22-23
- Blocked By: 11-12
References:
- astro-paper
[...slug]/index.astro: https://github.com/satnaing/astro-paper/blob/f3005328e548805226aba54414122c7174645e83/src/pages/posts/%5B...slug%5D/index.astro src/layouts/BlogLayout.astro— created in Task 12src/content/config.ts— blog collection schema
Acceptance Criteria:
- EN blog post page renders markdown content correctly
- Prev/next navigation works
npm run build→ PASS
QA Scenarios:
Scenario: Blog post renders Tool: Bash Preconditions: Task 12 completed, at least one EN blog post exists Steps: 1. Run: npm run build 2. Assert: dist/blog/[post-slug]/index.html exists 3. Grep output for post title Expected Result: Post page built with content Evidence: .sisyphus/evidence/task-13-post.txtCommit: YES (Wave 3)
- Create
-
14. Create blog post page RU ([slug].astro)
What to do:
- Create
src/pages/ru/blog/[slug].astro - Same structure as EN but filter by
lang === "ru" - Use identical template (BaseLayout derives locale from
Astro.currentLocale)
Must NOT do:
- Do NOT duplicate template logic — copy EN file exactly
- Do NOT hardcode Russian text in template
Recommended Agent Profile:
- Category:
unspecified-high
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 3
- Blocks: 22-23
- Blocked By: 11-12
References:
src/pages/blog/[slug].astro— EN version (Task 13)- Existing RU generator page pattern:
src/pages/ru/generators/*.astro
Acceptance Criteria:
- RU blog post page renders correctly
npm run build→ PASS
QA Scenarios:
Scenario: RU blog post renders Tool: Bash Preconditions: Task 13 completed, at least one RU blog post exists Steps: 1. Run: npm run build 2. Assert: dist/ru/blog/[post-slug]/index.html exists 3. Grep output for Russian post title Expected Result: RU post page built Evidence: .sisyphus/evidence/task-14-ru-post.txtCommit: YES (Wave 3)
- Create
-
15. Create blog index pages (EN + RU)
What to do:
- Create
src/pages/blog/index.astro— list all EN blog posts sorted by date (newest first) - Create
src/pages/ru/blog/index.astro— list all RU blog posts - Include pagination if needed (start simple: show all)
- Each post card shows: title, description, date, category, tags
Must NOT do:
- Do NOT show draft posts
- Do NOT mix EN and RU posts on same index
Recommended Agent Profile:
- Category:
unspecified-high
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 3
- Blocks: 24
- Blocked By: 11-14
References:
src/pages/index.astro— existing generator grid pattern- astro-paper index page: https://github.com/satnaing/astro-paper/blob/f3005328e548805226aba54414122c7174645e83/src/pages/index.astro
Acceptance Criteria:
- EN blog index lists all non-draft EN posts
- RU blog index lists all non-draft RU posts
- Posts sorted by pubDate descending
npm run build→ PASS
QA Scenarios:
Scenario: Blog index renders Tool: Bash Preconditions: Tasks 13-14 completed Steps: 1. Run: npm run build 2. Assert: dist/blog/index.html exists 3. Assert: dist/ru/blog/index.html exists 4. Grep dist/blog/index.html for post titles Expected Result: Both indices built with post listings Evidence: .sisyphus/evidence/task-15-index.txtCommit: YES (Wave 3)
- Create
-
16. Create RSS feeds (EN + RU)
What to do:
- Create
src/pages/rss.xml.ts— English RSS feed - Create
src/pages/ru/rss.xml.ts— Russian RSS feed - Each feed queries blog collection filtered by language
- Include: title, description, pubDate, link
- Add
<language>en</language>/<language>ru</language>customData - Add RSS auto-discovery links to BaseLayout:
<link rel="alternate" type="application/rss+xml" title="Randify Blog (EN)" href="/rss.xml" />
Must NOT do:
- Do NOT include draft posts
- Do NOT mix languages in same feed
Recommended Agent Profile:
- Category:
quick
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 3
- Blocks: None
- Blocked By: 11, 13-15
References:
- Astro RSS docs: https://docs.astro.build/en/guides/rss/
src/layouts/BaseLayout.astro— add RSS links in<head>package.json—@astrojs/rssdependency (Task 11)
Acceptance Criteria:
/rss.xmlserves valid RSS 2.0 with EN posts/ru/rss.xmlserves valid RSS 2.0 with RU posts- RSS auto-discovery links present in all pages
npm run build→ PASS
QA Scenarios:
Scenario: RSS feeds generated Tool: Bash Preconditions: Task 11 completed, blog posts exist Steps: 1. Run: npm run build 2. Assert: dist/rss.xml exists 3. Assert: dist/ru/rss.xml exists 4. Grep dist/rss.xml for '<language>en</language>' 5. Grep dist/ru/rss.xml for '<language>ru</language>' Expected Result: Both feeds built with correct language tags Evidence: .sisyphus/evidence/task-16-rss.txtCommit: YES (Wave 3)
- Create
-
17. Create category pages for generators (EN + RU)
What to do:
- Create
src/pages/generators/category/[category].astro - Create
src/pages/ru/generators/category/[category].astro - Use
getStaticPathswith 5 categories: gaming, security, decision-making, creative, utility - Filter generators by
data.category === category - Display category name, description, and matching generators in a grid
- Add category description text (e.g., "Gaming generators for tabletop RPGs, card games, and lotteries")
Must NOT do:
- Do NOT hardcode generator lists — filter dynamically from collection
- Do NOT skip any category
Recommended Agent Profile:
- Category:
unspecified-high
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 4
- Blocks: 18, 24
- Blocked By: 8
References:
src/pages/index.astro— generator grid rendering patternsrc/components/GeneratorCard.astro— card componentsrc/data/generators.ts— generator data access
Acceptance Criteria:
- 5 EN category pages built:
/generators/category/gaming/, etc. - 5 RU category pages built:
/ru/generators/category/gaming/, etc. - Each page shows correct generators for that category
npm run build→ PASS (74 pages cumulative: 62 existing + 2x 404 + 10 categories)
QA Scenarios:
Scenario: Category page shows correct generators Tool: Bash Preconditions: Task 8 completed Steps: 1. Run: npm run build 2. Read dist/generators/category/gaming/index.html 3. Assert: contains "Dice Roller" or "Кубик" 4. Assert: does NOT contain "Password Generator" Expected Result: Only gaming generators shown Evidence: .sisyphus/evidence/task-17-category.txtCommit: YES (Wave 4)
- Create
-
18. Add category navigation to homepage
What to do:
- Update
src/pages/index.astroto show category pills/links above or below the generator grid - Each pill links to
/generators/category/[category]/ - Show category count (e.g., "Gaming (6)")
- Style with Tailwind to match existing design
Must NOT do:
- Do NOT remove the existing generator grid
- Do NOT break mobile layout
Recommended Agent Profile:
- Category:
visual-engineering
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 4
- Blocks: None
- Blocked By: 17
References:
src/pages/index.astro— current homepage layoutsrc/components/GeneratorCard.astro— existing card styling
Acceptance Criteria:
- Category navigation visible on homepage
- Each category links to correct category page
- Mobile-responsive
npm run build→ PASS
QA Scenarios:
Scenario: Category navigation renders Tool: Bash Preconditions: Task 17 completed Steps: 1. Run: npm run build 2. Read dist/index.html 3. Assert: contains link to /generators/category/gaming/ Expected Result: Category links present Evidence: .sisyphus/evidence/task-18-nav.txtCommit: YES (Wave 4)
- Update
-
19. Create Breadcrumbs component
What to do:
- Create
src/components/Breadcrumbs.astro - Accept props:
items: Array<{ label: string, href?: string }> - Render as
<nav aria-label="Breadcrumb">with<ol>list - Style with Tailwind: small text, separators between items
- Use on generator pages and blog pages
- For generators: Home > [Category] > [Generator Name]
Must NOT do:
- Do NOT add breadcrumbs to homepage or about/privacy (not needed)
Recommended Agent Profile:
- Category:
visual-engineering
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 4
- Blocks: 26
- Blocked By: None
References:
src/layouts/GeneratorLayout.astro— existing breadcrumb schema (lines 37-54)src/pages/index.astro— backToAll link pattern
Acceptance Criteria:
- Breadcrumbs component renders correctly
- Accessible (aria-label, nav landmark)
- Matches existing design system
npm run build→ PASS
QA Scenarios:
Scenario: Breadcrumbs accessible Tool: Bash Preconditions: None Steps: 1. Create test page with Breadcrumbs 2. Run: npm run build 3. Grep output for 'aria-label="Breadcrumb"' Expected Result: Breadcrumb nav found with correct ARIA Evidence: .sisyphus/evidence/task-19-breadcrumbs.txtCommit: YES (Wave 4)
- Create
-
20. Create RelatedGenerators component
What to do:
- Create
src/components/RelatedGenerators.astro - Accept prop:
currentSlug: stringorcategory: string - Show 3-4 generators from the same category (excluding current)
- Render as small cards or list with icon + title + link
- Add to GeneratorLayout.astro at bottom of page
Must NOT do:
- Do NOT show current generator in related list
- Do NOT show generators from other categories
Recommended Agent Profile:
- Category:
unspecified-high
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 4
- Blocks: 25
- Blocked By: 8
References:
src/components/GeneratorCard.astro— card patternsrc/layouts/GeneratorLayout.astro— where to place componentsrc/data/generators.ts— generator data access
Acceptance Criteria:
- Related generators shown on every generator page
- Same-category generators only
- Current generator excluded
npm run build→ PASS
QA Scenarios:
Scenario: Related generators on dice page Tool: Bash Preconditions: Task 8 completed Steps: 1. Run: npm run build 2. Read dist/generators/dice/index.html 3. Assert: contains links to other gaming generators (cards, lottery, etc.) 4. Assert: does NOT contain link to dice page itself Expected Result: Related gaming generators shown Evidence: .sisyphus/evidence/task-20-related.txtCommit: YES (Wave 4)
- Create
-
21. Create RelatedPosts component
What to do:
- Create
src/components/RelatedPosts.astro - Accept prop:
post: CollectionEntry<"blog"> - Find related posts by tag overlap scoring:
const related = allPosts .filter(p => p.id !== post.id && p.data.lang === post.data.lang) .map(p => ({ post: p, score: p.data.tags.filter(t => post.data.tags.includes(t)).length })) .filter(({ score }) => score > 0) .sort((a, b) => b.score - a.score) .slice(0, 3) .map(({ post }) => post); - Render as small cards with title, date, description
- Add to BlogLayout.astro at bottom of post
Must NOT do:
- Do NOT show current post
- Do NOT mix EN and RU posts
Recommended Agent Profile:
- Category:
unspecified-high
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 4
- Blocks: None
- Blocked By: 11
References:
- astro-paper PostDetails.astro: https://github.com/satnaing/astro-paper/blob/f3005328e548805226aba54414122c7174645e83/src/layouts/PostDetails.astro#L70-L83
src/layouts/BlogLayout.astro— where to place component
Acceptance Criteria:
- Related posts shown on blog post pages
- Tag overlap scoring works
- Same language only
npm run build→ PASS
QA Scenarios:
Scenario: Related posts by tag Tool: Bash Preconditions: Task 11 completed, multiple posts with shared tags Steps: 1. Create test posts with shared tags 2. Run: npm run build 3. Read dist/blog/test-post/index.html 4. Assert: contains links to posts with matching tags Expected Result: Related posts displayed Evidence: .sisyphus/evidence/task-21-related-posts.txtCommit: YES (Wave 4)
- Create
-
22. Create 8 blog post templates EN
What to do:
- Create 8 markdown files in
src/content/blog/en/with correct frontmatter:--- title: "What is Cryptographically Secure Randomness and Why It Matters" description: "Learn why cryptographically secure random number generators are essential for passwords, gaming, and security." pubDate: 2025-01-15 modDate: 2025-01-15 draft: false lang: en category: guide tags: ["randomness", "security", "crypto"] relatedGenerators: ["password", "hash", "uuid"] --- - Fill body with placeholder content (Lorem ipsum style paragraphs)
- Topics:
- Cryptographically secure randomness
- Strong password creation guide
- Dice notation explained
- Psychology of randomness
- RNG in gaming
- Random team picker guide
- Color theory and palettes
- UUID vs sequential IDs
Must NOT do:
- Do NOT write full article content (user generates via neural networks)
- Do NOT set draft: true
Recommended Agent Profile:
- Category:
writing
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 4
- Blocks: None
- Blocked By: 11-16
References:
src/content/config.ts— blog collection schemasrc/content/generators/*.json— existing content file pattern
Acceptance Criteria:
- 8 EN blog posts exist in
src/content/blog/en/ - All have valid frontmatter matching schema
npm run build→ PASS (84 pages cumulative: 62 existing + 2x 404 + 10 categories + 2x blog index + 8 EN posts)
QA Scenarios:
Scenario: Blog posts build correctly Tool: Bash Preconditions: Tasks 11-16 completed Steps: 1. Run: npm run build 2. Assert: dist/blog/ contains 8 post directories 3. Grep dist/blog/[first-post]/index.html for post title Expected Result: All posts built successfully Evidence: .sisyphus/evidence/task-22-posts.txtCommit: YES (Wave 5)
- Create 8 markdown files in
-
23. Create 8 blog post templates RU
What to do:
- Create 8 markdown files in
src/content/blog/ru/with Russian titles/descriptions - Same structure as EN but with
lang: ru - Topics mirror EN:
- "Что такое криптографически стойкая случайность и почему это важно"
- "Как создавать надёжные пароли: полное руководство"
- "Нотация кубиков: от d4 до взрывающихся кубиков"
- "Психология случайности: почему люди плохо справляются со случайностью"
- "Генераторы случайных чисел в играх: честность и алгоритмы"
- "Как использовать случайный выбор команд для спорта и мероприятий"
- "Теория цвета: как создавать гармоничные палитры"
- "UUID против последовательных ID: когда что использовать"
Must NOT do:
- Do NOT write full article content
- Do NOT set draft: true
Recommended Agent Profile:
- Category:
writing
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 4
- Blocks: None
- Blocked By: 11-16
References:
src/content/blog/en/— EN templates (Task 22)src/i18n/translations.ts— existing i18n pattern
Acceptance Criteria:
- 8 RU blog posts exist in
src/content/blog/ru/ - All have valid frontmatter with
lang: ru npm run build→ PASS (92 pages cumulative: 84 + 8 RU posts)
QA Scenarios:
Scenario: RU blog posts build correctly Tool: Bash Preconditions: Task 22 completed Steps: 1. Run: npm run build 2. Assert: dist/ru/blog/ contains 8 post directories 3. Grep dist/ru/blog/[first-post]/index.html for Russian title Expected Result: All RU posts built Evidence: .sisyphus/evidence/task-23-ru-posts.txtCommit: YES (Wave 5)
- Create 8 markdown files in
-
24. Add blog link to navigation
What to do:
- Update
src/components/LanguageSwitcher.astroor add a new nav component - Add "Blog" / "Блог" link pointing to
/blog/and/ru/blog/ - Style to match existing design (accent color, hover states)
- Position logically (e.g., next to language switcher or in header)
Must NOT do:
- Do NOT break existing LanguageSwitcher functionality
- Do NOT add heavy client-side logic
Recommended Agent Profile:
- Category:
quick
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 4
- Blocks: None
- Blocked By: 15
References:
src/components/LanguageSwitcher.astro— existing nav componentsrc/i18n/translations.ts— add "blog" translation keysrc/layouts/BaseLayout.astro— where nav is rendered
Acceptance Criteria:
- Blog link visible on all pages
- Link switches language correctly with locale
npm run build→ PASS
QA Scenarios:
Scenario: Blog link present on homepage Tool: Bash Preconditions: Task 15 completed Steps: 1. Run: npm run build 2. Read dist/index.html 3. Assert: contains link to /blog/ 4. Read dist/ru/index.html 5. Assert: contains link to /ru/blog/ Expected Result: Blog links present on both EN and RU pages Evidence: .sisyphus/evidence/task-24-nav.txtCommit: YES (Wave 5)
- Update
-
25. Add related generators to generator pages
What to do:
- Update
src/layouts/GeneratorLayout.astroto import and render<RelatedGenerators /> - Pass current generator's category to component
- Place after SeoBlock and before FAQ (or after FAQ)
Must NOT do:
- Do NOT duplicate RelatedGenerators logic
- Do NOT show on pages without generators
Recommended Agent Profile:
- Category:
unspecified-high
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 5
- Blocks: None
- Blocked By: 20
References:
src/components/RelatedGenerators.astro— created in Task 20src/layouts/GeneratorLayout.astro— where to place component
Acceptance Criteria:
- RelatedGenerators rendered on all 56 generator pages (EN + RU)
- Correct category filtering
npm run build→ PASS
QA Scenarios:
Scenario: Related generators on every generator page Tool: Bash Preconditions: Task 20 completed Steps: 1. Run: npm run build 2. Read dist/generators/password/index.html 3. Assert: contains links to hash and uuid generators 4. Read dist/generators/coin/index.html 5. Assert: contains links to yesno and teams generators Expected Result: Related generators shown with correct filtering Evidence: .sisyphus/evidence/task-25-related.txtCommit: YES (Wave 5)
- Update
-
26. Add breadcrumbs to generator and blog layouts
What to do:
- Update
src/layouts/GeneratorLayout.astroto include<Breadcrumbs /> - Breadcrumbs: Home > [Category] > [Generator Title]
- Update
src/layouts/BlogLayout.astroto include<Breadcrumbs /> - Breadcrumbs: Home > Blog > [Post Title]
- Ensure breadcrumbs don't break existing layout
Must NOT do:
- Do NOT add breadcrumbs to BaseLayout (not all pages need them)
Recommended Agent Profile:
- Category:
unspecified-high
Parallelization:
- Can Run In Parallel: YES
- Parallel Group: Wave 5
- Blocks: None
- Blocked By: 19
References:
src/components/Breadcrumbs.astro— created in Task 19src/layouts/GeneratorLayout.astro— generator page wrappersrc/layouts/BlogLayout.astro— blog page wrapper
Acceptance Criteria:
- Breadcrumbs visible on all generator pages
- Breadcrumbs visible on all blog post pages
- Correct breadcrumb items per page type
npm run build→ PASS
QA Scenarios:
Scenario: Breadcrumbs on generator page Tool: Bash Preconditions: Task 19 completed Steps: 1. Run: npm run build 2. Read dist/generators/dice/index.html 3. Assert: contains breadcrumb with "Home", "Gaming", "Dice" Expected Result: Breadcrumbs rendered correctly Evidence: .sisyphus/evidence/task-26-breadcrumbs.txtCommit: YES (Wave 5)
- Update
Final Verification Wave
-
F1. Plan Compliance Audit —
oracleRead the plan end-to-end. For each "Must Have": verify implementation exists (read file, curl endpoint, run command). For each "Must NOT Have": search codebase for forbidden patterns — reject with file:line if found. Check evidence files exist in .sisyphus/evidence/. Compare deliverables against plan. Output:Must Have [N/N] | Must NOT Have [N/N] | Tasks [N/N] | VERDICT: APPROVE/REJECT -
F2. Code Quality Review —
unspecified-highRuntsc --noEmit+npm run lint+npm run test+npm run build. Review all changed files for:as any/@ts-ignore, empty catches, console.log in prod, commented-out code, unused imports. Check AI slop: excessive comments, over-abstraction, generic names. Output:Build [PASS/FAIL] | Lint [PASS/FAIL] | Tests [N pass/N fail] | Files [N clean/N issues] | VERDICT -
F3. Real Manual QA —
unspecified-highStart from clean state. Execute EVERY QA scenario from EVERY task — follow exact steps, capture evidence. Test cross-task integration (blog + categories + generators). Test edge cases: empty blog, category with no generators, 404 page. Save to.sisyphus/evidence/final-qa/. Output:Scenarios [N/N pass] | Integration [N/N] | Edge Cases [N tested] | VERDICT -
F4. Scope Fidelity Check —
deepFor each task: read "What to do", read actual diff (git log/diff). Verify 1:1 — everything in spec was built (no missing), nothing beyond spec was built (no creep). Check "Must NOT do" compliance. Detect cross-task contamination. Output:Tasks [N/N compliant] | Contamination [CLEAN/N issues] | Unaccounted [CLEAN/N files] | VERDICT
Commit Strategy
- Wave 1:
fix(seo): fix critical SEO gaps — duplicate keys, landmarks, OG tags, hreflang - Wave 2:
feat(schema): add generator categories and Organization schema - Wave 3:
feat(blog): add blog infrastructure with RSS feeds - Wave 4:
feat(categories): add generator category pages and breadcrumbs - Wave 5:
feat(content): add blog templates and navigation links - Wave FINAL:
chore(review): final verification and fixes
Success Criteria
Verification Commands
npm run lint # Expected: 0 errors
npm run build # Expected: 70+ pages
npm run test # Expected: 51/51 pass (existing tests unchanged)
Final Checklist
- All "Must Have" present
- All "Must NOT Have" absent
- Build passes with 70+ pages
- Lint passes with 0 errors
- OG tags present on all page types
- RSS feeds accessible
- All 28 generators categorized
- No duplicate JSON keys
- Blog index and post pages render
- Category pages filter correctly