fix(seo): Wave 1 — fix critical SEO gaps
- Fix duplicate faq/ruFaq keys in dice.json, list.json, colors.json - Add <main> landmarks to about/privacy pages (EN + RU) - Move YandexRTB after <main> on homepage - Add x-default hreflang to BaseLayout - Configure sitemap i18n with hreflang alternates - Add Open Graph + Twitter Card meta tags - Create default OG image (1200x630)
This commit is contained in:
+41
-134
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schema_version": 2,
|
||||
"active_work_id": "critical-refactor-f063daf0",
|
||||
"active_work_id": "seo-blog-categories-9c7476b9",
|
||||
"works": {
|
||||
"critical-refactor-f063daf0": {
|
||||
"work_id": "critical-refactor-f063daf0",
|
||||
@@ -150,152 +150,59 @@
|
||||
},
|
||||
"ended_at": "2026-05-13T18:03:08.059Z",
|
||||
"elapsed_ms": 5868793
|
||||
},
|
||||
"seo-blog-categories-9c7476b9": {
|
||||
"work_id": "seo-blog-categories-9c7476b9",
|
||||
"active_plan": "/home/emil/Desktop/Coding/AI/Randify.pro/.sisyphus/plans/seo-blog-categories.md",
|
||||
"plan_name": "seo-blog-categories",
|
||||
"status": "active",
|
||||
"started_at": "2026-05-13T23:32:06.345Z",
|
||||
"updated_at": "2026-05-13T23:36:41.704Z",
|
||||
"session_ids": [
|
||||
"ses_1de6ede59ffexUwt5C0sddEWwR"
|
||||
],
|
||||
"session_origins": {
|
||||
"ses_1de6ede59ffexUwt5C0sddEWwR": "direct"
|
||||
},
|
||||
"agent": "atlas",
|
||||
"task_sessions": {
|
||||
"todo:1": {
|
||||
"task_key": "todo:1",
|
||||
"task_label": "1",
|
||||
"task_title": "Fix duplicate JSON keys in 3 generator files",
|
||||
"session_id": "ses_1dc4ed5ddffe54aNbdrrVGPkpI",
|
||||
"agent": "Sisyphus-Junior",
|
||||
"category": "quick",
|
||||
"updated_at": "2026-05-13T23:36:41.704Z",
|
||||
"started_at": "2026-05-13T23:36:41.704Z",
|
||||
"status": "running"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"active_plan": "/home/emil/Desktop/Coding/AI/Randify.pro/.sisyphus/plans/critical-refactor.md",
|
||||
"started_at": "2026-05-13T16:25:19.266Z",
|
||||
"status": "completed",
|
||||
"updated_at": "2026-05-13T18:03:08.059Z",
|
||||
"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:36:41.704Z",
|
||||
"session_ids": [
|
||||
"ses_1de6ede59ffexUwt5C0sddEWwR"
|
||||
],
|
||||
"session_origins": {
|
||||
"ses_1de6ede59ffexUwt5C0sddEWwR": "direct"
|
||||
},
|
||||
"plan_name": "critical-refactor",
|
||||
"plan_name": "seo-blog-categories",
|
||||
"task_sessions": {
|
||||
"todo:1": {
|
||||
"task_key": "todo:1",
|
||||
"task_label": "1",
|
||||
"task_title": "Add missing dependencies to package.json",
|
||||
"session_id": "ses_1ddd57501ffeO4NlJDKb2pwLz2",
|
||||
"task_title": "Fix duplicate JSON keys in 3 generator files",
|
||||
"session_id": "ses_1dc4ed5ddffe54aNbdrrVGPkpI",
|
||||
"agent": "Sisyphus-Junior",
|
||||
"category": "writing",
|
||||
"started_at": "2026-05-13T16:27:48.876Z",
|
||||
"status": "completed",
|
||||
"updated_at": "2026-05-13T16:33:52.668Z",
|
||||
"ended_at": "2026-05-13T16:33:52.668Z",
|
||||
"elapsed_ms": 363792
|
||||
},
|
||||
"todo:4": {
|
||||
"task_key": "todo:4",
|
||||
"task_label": "4",
|
||||
"task_title": "Create ResultBox.astro shared component",
|
||||
"session_id": "ses_1ddce8961ffeoaXaB2Rxgt684X",
|
||||
"agent": "Sisyphus-Junior",
|
||||
"category": "visual-engineering",
|
||||
"updated_at": "2026-05-13T16:42:05.595Z",
|
||||
"started_at": "2026-05-13T16:40:57.448Z",
|
||||
"status": "completed",
|
||||
"ended_at": "2026-05-13T16:42:05.595Z",
|
||||
"elapsed_ms": 68147
|
||||
},
|
||||
"todo:6": {
|
||||
"task_key": "todo:6",
|
||||
"task_label": "6",
|
||||
"task_title": "Refactor CardGenerator.astro",
|
||||
"session_id": "ses_1ddc76889ffe240ehScl9taAza",
|
||||
"agent": "Sisyphus-Junior",
|
||||
"category": "unspecified-high",
|
||||
"updated_at": "2026-05-13T16:47:10.433Z",
|
||||
"started_at": "2026-05-13T16:44:57.812Z",
|
||||
"status": "completed",
|
||||
"ended_at": "2026-05-13T16:47:10.433Z",
|
||||
"elapsed_ms": 132621
|
||||
},
|
||||
"todo:10": {
|
||||
"task_key": "todo:10",
|
||||
"task_label": "10",
|
||||
"task_title": "Refactor DateGenerator.astro",
|
||||
"session_id": "ses_1ddc380cbffe0YA1da3ew6QlNf",
|
||||
"agent": "Sisyphus-Junior",
|
||||
"category": "unspecified-high",
|
||||
"updated_at": "2026-05-13T17:16:10.363Z",
|
||||
"started_at": "2026-05-13T16:49:43.859Z",
|
||||
"status": "completed",
|
||||
"ended_at": "2026-05-13T17:16:10.363Z",
|
||||
"elapsed_ms": 1586504
|
||||
},
|
||||
"todo:13": {
|
||||
"task_key": "todo:13",
|
||||
"task_label": "13",
|
||||
"task_title": "Refactor GradientGenerator.astro",
|
||||
"session_id": "ses_1dda85f21ffeEGeOWrbqmWAk02",
|
||||
"agent": "Sisyphus-Junior",
|
||||
"category": "unspecified-high",
|
||||
"updated_at": "2026-05-13T17:22:16.123Z",
|
||||
"started_at": "2026-05-13T17:19:45.020Z",
|
||||
"status": "completed",
|
||||
"ended_at": "2026-05-13T17:22:16.123Z",
|
||||
"elapsed_ms": 151103
|
||||
},
|
||||
"todo:17": {
|
||||
"task_key": "todo:17",
|
||||
"task_label": "17",
|
||||
"task_title": "Refactor LoremGenerator.astro",
|
||||
"session_id": "ses_1dda37bf2ffexATCZ3W4Z6EDu1",
|
||||
"agent": "Sisyphus-Junior",
|
||||
"category": "unspecified-high",
|
||||
"updated_at": "2026-05-13T17:25:32.173Z",
|
||||
"started_at": "2026-05-13T17:25:11.269Z",
|
||||
"status": "completed",
|
||||
"ended_at": "2026-05-13T17:25:32.173Z",
|
||||
"elapsed_ms": 20904
|
||||
},
|
||||
"todo:20": {
|
||||
"task_key": "todo:20",
|
||||
"task_label": "20",
|
||||
"task_title": "Refactor MealGenerator.astro",
|
||||
"session_id": "ses_1dda01e38ffeVc6AUwAlt7lQXl",
|
||||
"agent": "Sisyphus-Junior",
|
||||
"category": "unspecified-high",
|
||||
"updated_at": "2026-05-13T17:31:02.031Z",
|
||||
"started_at": "2026-05-13T17:30:26.005Z",
|
||||
"status": "completed",
|
||||
"ended_at": "2026-05-13T17:31:02.031Z",
|
||||
"elapsed_ms": 36026
|
||||
},
|
||||
"todo:24": {
|
||||
"task_key": "todo:24",
|
||||
"task_label": "24",
|
||||
"task_title": "Refactor PasswordGenerator.astro",
|
||||
"session_id": "ses_1dd9b7bb1ffez3Q0aayg7PZUIF",
|
||||
"agent": "Sisyphus-Junior",
|
||||
"category": "unspecified-high",
|
||||
"updated_at": "2026-05-13T17:34:08.166Z",
|
||||
"started_at": "2026-05-13T17:32:34.652Z",
|
||||
"status": "completed",
|
||||
"ended_at": "2026-05-13T17:34:08.166Z",
|
||||
"elapsed_ms": 93514
|
||||
},
|
||||
"todo:27": {
|
||||
"task_key": "todo:27",
|
||||
"task_label": "27",
|
||||
"task_title": "Refactor TeamsGenerator.astro",
|
||||
"session_id": "ses_1dd94b493ffemX2z2dEFdh8W7R",
|
||||
"agent": "Sisyphus-Junior",
|
||||
"category": "unspecified-high",
|
||||
"started_at": "2026-05-13T17:37:23.881Z",
|
||||
"status": "completed",
|
||||
"updated_at": "2026-05-13T17:41:13.262Z",
|
||||
"ended_at": "2026-05-13T17:41:13.262Z",
|
||||
"elapsed_ms": 229381
|
||||
},
|
||||
"final-wave:f1": {
|
||||
"task_key": "final-wave:f1",
|
||||
"task_label": "F1",
|
||||
"task_title": "**Plan Compliance Audit** — `oracle`",
|
||||
"session_id": "ses_1dd81d9e1ffeclA0rP510AXfNB",
|
||||
"agent": "Sisyphus-Junior",
|
||||
"category": "deep",
|
||||
"started_at": "2026-05-13T17:47:58.486Z",
|
||||
"status": "completed",
|
||||
"updated_at": "2026-05-13T18:02:13.341Z",
|
||||
"ended_at": "2026-05-13T18:02:13.341Z",
|
||||
"elapsed_ms": 854855
|
||||
"category": "quick",
|
||||
"updated_at": "2026-05-13T23:36:41.704Z",
|
||||
"started_at": "2026-05-13T23:36:41.704Z",
|
||||
"status": "running"
|
||||
}
|
||||
},
|
||||
"agent": "atlas",
|
||||
"ended_at": "2026-05-13T18:03:08.059Z",
|
||||
"elapsed_ms": 5868793
|
||||
"agent": "atlas"
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
|
||||
> randify@0.0.1 build
|
||||
> astro build
|
||||
|
||||
02:36:15 [types] Generated 342ms
|
||||
02:36:15 [build] output: "static"
|
||||
02:36:15 [build] directory: /home/emil/Desktop/Coding/AI/Randify.pro/dist/
|
||||
02:36:15 [build] Collecting build info...
|
||||
02:36:15 [build] ✓ Completed in 368ms.
|
||||
02:36:15 [build] Building static entrypoints...
|
||||
02:36:17 [vite] ✓ built in 2.10s
|
||||
02:36:17 [build] ✓ Completed in 2.15s.
|
||||
|
||||
building client (vite)
|
||||
02:36:17 [vite] transforming...
|
||||
02:36:17 [vite] ✓ 71 modules transformed.
|
||||
02:36:17 [vite] rendering chunks...
|
||||
02:36:17 [vite] computing gzip size...
|
||||
02:36:17 [vite] dist/_astro/hoisted.BKKrxAht.js 0.16 kB │ gzip: 0.15 kB
|
||||
02:36:17 [vite] dist/_astro/animations.JKmio82t.js 0.19 kB │ gzip: 0.13 kB
|
||||
02:36:17 [vite] dist/_astro/validation.plcuGzaj.js 0.20 kB │ gzip: 0.16 kB
|
||||
02:36:17 [vite] dist/_astro/clipboard.v9BZgIeL.js 0.43 kB │ gzip: 0.22 kB
|
||||
02:36:17 [vite] dist/_astro/random.PhfdigkC.js 0.50 kB │ gzip: 0.31 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.B5m2ZYh6.js 0.90 kB │ gzip: 0.56 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.CdG8uTdI.js 1.23 kB │ gzip: 0.61 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.CT9HX5_Y.js 1.38 kB │ gzip: 0.72 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.Cb7Tv2oN.js 1.48 kB │ gzip: 0.83 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.D82rtlIG.js 1.54 kB │ gzip: 0.84 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.uArMeWBD.js 1.63 kB │ gzip: 0.81 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.CwDo-_-Z.js 1.64 kB │ gzip: 0.73 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.j6ibv0wb.js 1.65 kB │ gzip: 0.81 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.BEwWV8JC.js 1.73 kB │ gzip: 0.90 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.6rLeMLDm.js 1.74 kB │ gzip: 0.86 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.DOtqogeQ.js 1.76 kB │ gzip: 0.99 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.CHG7AXVP.js 1.89 kB │ gzip: 1.05 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.DnGtBYme.js 1.99 kB │ gzip: 0.95 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.hrxZZFEF.js 2.19 kB │ gzip: 1.07 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.CjZD7f2g.js 2.33 kB │ gzip: 1.15 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.qLZXl1Do.js 2.88 kB │ gzip: 1.70 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.BKosNXxl.js 2.91 kB │ gzip: 1.41 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.CpSL7HYx.js 3.94 kB │ gzip: 1.95 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.DmqdUAAB.js 4.10 kB │ gzip: 1.70 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.COsV1Syq.js 4.30 kB │ gzip: 1.96 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.Ftg8tUcf.js 4.53 kB │ gzip: 1.97 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.3XDY-7Px.js 4.79 kB │ gzip: 1.97 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.mRfAHLMS.js 5.27 kB │ gzip: 2.20 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.B7vaoHN9.js 7.19 kB │ gzip: 2.54 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.DU8tsC8l.js 9.71 kB │ gzip: 3.84 kB
|
||||
02:36:17 [vite] dist/_astro/i18n.DYCg5-VL.js 10.76 kB │ gzip: 5.53 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.ChvQAxmv.js 10.92 kB │ gzip: 3.89 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.DdCnpAKh.js 11.83 kB │ gzip: 2.76 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.CvjQ9xHL.js 35.55 kB │ gzip: 17.46 kB
|
||||
02:36:17 [vite] dist/_astro/hoisted.Bdx021zL.js 45.26 kB │ gzip: 14.58 kB
|
||||
02:36:17 [vite] ✓ built in 438ms
|
||||
|
||||
generating static routes
|
||||
02:36:18 ▶ src/pages/about.astro
|
||||
02:36:18 └─ /about/index.html (+11ms)
|
||||
02:36:18 ▶ src/pages/generators/cards.astro
|
||||
02:36:18 └─ /generators/cards/index.html (+6ms)
|
||||
02:36:18 ▶ src/pages/generators/coin.astro
|
||||
02:36:18 └─ /generators/coin/index.html (+4ms)
|
||||
02:36:18 ▶ src/pages/generators/colors.astro
|
||||
02:36:18 └─ /generators/colors/index.html (+3ms)
|
||||
02:36:18 ▶ src/pages/generators/country.astro
|
||||
02:36:18 └─ /generators/country/index.html (+4ms)
|
||||
02:36:18 ▶ src/pages/generators/date.astro
|
||||
02:36:18 └─ /generators/date/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/dice.astro
|
||||
02:36:18 └─ /generators/dice/index.html (+3ms)
|
||||
02:36:18 ▶ src/pages/generators/emoji.astro
|
||||
02:36:18 └─ /generators/emoji/index.html (+3ms)
|
||||
02:36:18 ▶ src/pages/generators/fontpair.astro
|
||||
02:36:18 └─ /generators/fontpair/index.html (+3ms)
|
||||
02:36:18 ▶ src/pages/generators/gradient.astro
|
||||
02:36:18 └─ /generators/gradient/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/hash.astro
|
||||
02:36:18 └─ /generators/hash/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/letter.astro
|
||||
02:36:18 └─ /generators/letter/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/list.astro
|
||||
02:36:18 └─ /generators/list/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/lorem.astro
|
||||
02:36:18 └─ /generators/lorem/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/lottery.astro
|
||||
02:36:18 └─ /generators/lottery/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/magic8ball.astro
|
||||
02:36:18 └─ /generators/magic8ball/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/meal.astro
|
||||
02:36:18 └─ /generators/meal/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/names.astro
|
||||
02:36:18 └─ /generators/names/index.html (+3ms)
|
||||
02:36:18 ▶ src/pages/generators/numbers.astro
|
||||
02:36:18 └─ /generators/numbers/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/palette.astro
|
||||
02:36:18 └─ /generators/palette/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/password.astro
|
||||
02:36:18 └─ /generators/password/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/rps.astro
|
||||
02:36:18 └─ /generators/rps/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/shuffler.astro
|
||||
02:36:18 └─ /generators/shuffler/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/teams.astro
|
||||
02:36:18 └─ /generators/teams/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/time.astro
|
||||
02:36:18 └─ /generators/time/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/uuid.astro
|
||||
02:36:18 └─ /generators/uuid/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/weighted.astro
|
||||
02:36:18 └─ /generators/weighted/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/wheel.astro
|
||||
02:36:18 └─ /generators/wheel/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/generators/yesno.astro
|
||||
02:36:18 └─ /generators/yesno/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/privacy.astro
|
||||
02:36:18 └─ /privacy/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/about.astro
|
||||
02:36:18 └─ /ru/about/index.html (+3ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/cards.astro
|
||||
02:36:18 └─ /ru/generators/cards/index.html (+3ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/coin.astro
|
||||
02:36:18 └─ /ru/generators/coin/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/colors.astro
|
||||
02:36:18 └─ /ru/generators/colors/index.html (+3ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/country.astro
|
||||
02:36:18 └─ /ru/generators/country/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/date.astro
|
||||
02:36:18 └─ /ru/generators/date/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/dice.astro
|
||||
02:36:18 └─ /ru/generators/dice/index.html (+3ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/emoji.astro
|
||||
02:36:18 └─ /ru/generators/emoji/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/fontpair.astro
|
||||
02:36:18 └─ /ru/generators/fontpair/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/gradient.astro
|
||||
02:36:18 └─ /ru/generators/gradient/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/hash.astro
|
||||
02:36:18 └─ /ru/generators/hash/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/letter.astro
|
||||
02:36:18 └─ /ru/generators/letter/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/list.astro
|
||||
02:36:18 └─ /ru/generators/list/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/lorem.astro
|
||||
02:36:18 └─ /ru/generators/lorem/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/lottery.astro
|
||||
02:36:18 └─ /ru/generators/lottery/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/magic8ball.astro
|
||||
02:36:18 └─ /ru/generators/magic8ball/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/meal.astro
|
||||
02:36:18 └─ /ru/generators/meal/index.html (+3ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/names.astro
|
||||
02:36:18 └─ /ru/generators/names/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/numbers.astro
|
||||
02:36:18 └─ /ru/generators/numbers/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/palette.astro
|
||||
02:36:18 └─ /ru/generators/palette/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/password.astro
|
||||
02:36:18 └─ /ru/generators/password/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/rps.astro
|
||||
02:36:18 └─ /ru/generators/rps/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/shuffler.astro
|
||||
02:36:18 └─ /ru/generators/shuffler/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/teams.astro
|
||||
02:36:18 └─ /ru/generators/teams/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/time.astro
|
||||
02:36:18 └─ /ru/generators/time/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/uuid.astro
|
||||
02:36:18 └─ /ru/generators/uuid/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/weighted.astro
|
||||
02:36:18 └─ /ru/generators/weighted/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/wheel.astro
|
||||
02:36:18 └─ /ru/generators/wheel/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/generators/yesno.astro
|
||||
02:36:18 └─ /ru/generators/yesno/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/privacy.astro
|
||||
02:36:18 └─ /ru/privacy/index.html (+2ms)
|
||||
02:36:18 ▶ src/pages/ru/index.astro
|
||||
02:36:18 └─ /ru/index.html (+4ms)
|
||||
02:36:18 ▶ src/pages/index.astro
|
||||
02:36:18 └─ /index.html (+3ms)
|
||||
02:36:18 ✓ Completed in 381ms.
|
||||
|
||||
02:36:18 [@astrojs/sitemap] `sitemap-index.xml` created at `dist`
|
||||
02:36:18 [build] 62 page(s) built in 3.40s
|
||||
02:36:18 [build] Complete!
|
||||
@@ -0,0 +1,16 @@
|
||||
Task: Fix <main> landmarks on about/privacy pages
|
||||
|
||||
Files modified:
|
||||
- src/pages/about.astro
|
||||
- src/pages/ru/about.astro
|
||||
- src/pages/privacy.astro
|
||||
- src/pages/ru/privacy.astro
|
||||
|
||||
Verification:
|
||||
- npm run lint: 0 errors
|
||||
- npm run build: success
|
||||
- grep dist for <main> on about/privacy pages: all 4 files contain <main> tag
|
||||
|
||||
Pattern applied:
|
||||
- Breadcrumb nav and page header remain outside <main>
|
||||
- Content sections wrapped in <main> following GeneratorLayout.astro pattern
|
||||
@@ -0,0 +1,8 @@
|
||||
TASK: Fix ad placement on homepage
|
||||
FILE: src/pages/index.astro
|
||||
CHANGE: Moved <YandexRTB /> from before <main> to after </main>
|
||||
BUILD: PASS (npm run build exited 0)
|
||||
VERIFICATION:
|
||||
- dist/index.html: </main> at byte 43284
|
||||
- dist/index.html: yandex_rtb at byte 43335
|
||||
- Order correct: True (main content before ad block)
|
||||
@@ -0,0 +1,11 @@
|
||||
Task: Add x-default hreflang to BaseLayout
|
||||
Date: 2026-05-14
|
||||
|
||||
Verification:
|
||||
- npm run build: PASS (62 pages built)
|
||||
- grep dist/index.html for x-default: FOUND
|
||||
<link rel="alternate" hreflang="x-default" href="https://randify.pro/">
|
||||
- grep dist/generators/dice/index.html for x-default: FOUND
|
||||
- grep all dist/*.html for x-default: 62 matches across 62 files
|
||||
|
||||
All pages now include x-default hreflang fallback pointing to the English version.
|
||||
@@ -0,0 +1,13 @@
|
||||
# Task 5 Evidence: Sitemap i18n Config
|
||||
|
||||
## Build Status
|
||||
PASS
|
||||
|
||||
## Verification
|
||||
File: dist/sitemap-0.xml
|
||||
Contains <xhtml:link rel="alternate" hreflang="en-US"> and <xhtml:link rel="alternate" hreflang="ru-RU"> entries for all bilingual pages.
|
||||
|
||||
## Sample Entries
|
||||
- https://randify.pro/ -> en-US + ru-RU
|
||||
- https://randify.pro/about/ -> en-US + ru-RU
|
||||
- https://randify.pro/generators/coin/ -> en-US + ru-RU
|
||||
@@ -0,0 +1,31 @@
|
||||
Evidence: Open Graph and Twitter Card meta tags added successfully.
|
||||
|
||||
Build status: PASS (npm run build completed with exit 0)
|
||||
|
||||
--- dist/index.html ---
|
||||
<meta property="og:site_name" content="Randify">
|
||||
<meta property="og:locale" content="en_US">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:title" content="Randify — Random Value Generators">
|
||||
<meta property="og:description" content="Simple tools for raffles, games, and everything that needs randomness.">
|
||||
<meta property="og:url" content="https://randify.pro/">
|
||||
<meta property="og:image" content="https://randify.pro/og-default.jpg">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:title" content="Randify — Random Value Generators">
|
||||
<meta name="twitter:description" content="Simple tools for raffles, games, and everything that needs randomness.">
|
||||
<meta name="twitter:image" content="https://randify.pro/og-default.jpg">
|
||||
|
||||
--- dist/generators/dice/index.html ---
|
||||
<meta property="og:site_name" content="Randify">
|
||||
<meta property="og:locale" content="en_US">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:title" content="Dice Roller — d4 d6 d20 + Full Notation | D&D Dice | Randify">
|
||||
<meta property="og:description" content="Free online dice roller with full XdY+Z notation, keep/drop (4d6dl1), exploding dice (3d6!), reroll, advantage/disadvantage, and roll history. Perfect for D&D, Pathfinder, and Savage Worlds.">
|
||||
<meta property="og:url" content="https://randify.pro/generators/dice/">
|
||||
<meta property="og:image" content="https://randify.pro/og-default.jpg">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:title" content="Dice Roller — d4 d6 d20 + Full Notation | D&D Dice | Randify">
|
||||
<meta name="twitter:description" content="Free online dice roller with full XdY+Z notation, keep/drop (4d6dl1), exploding dice (3d6!), reroll, advantage/disadvantage, and roll history. Perfect for D&D, Pathfinder, and Savage Worlds.">
|
||||
<meta name="twitter:image" content="https://randify.pro/og-default.jpg">
|
||||
|
||||
All required tags present on both pages.
|
||||
@@ -0,0 +1,10 @@
|
||||
## Task 6: Open Graph + Twitter Card Meta Tags
|
||||
|
||||
- Added `ogImage?: string` prop to `BaseLayout.astro` Props interface.
|
||||
- Implemented full OG tag set: `og:site_name`, `og:locale`, `og:type`, `og:title`, `og:description`, `og:url`, `og:image`.
|
||||
- Implemented full Twitter Card tag set: `twitter:card` (summary_large_image), `twitter:title`, `twitter:description`, `twitter:image`.
|
||||
- Default OG image (`/og-default.jpg`) is used when `ogImage` prop is omitted.
|
||||
- `ogImageUrl` helper ensures absolute URLs by prefixing `https://randify.pro` to relative paths.
|
||||
- Default OG image generated via Node.js + sharp (1200x630, dark background with accent radial gradients and "Randify" branding).
|
||||
- Build passes; tags verified in `dist/index.html` and `dist/generators/dice/index.html`.
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
# Create AGENTS.md
|
||||
|
||||
## TL;DR
|
||||
|
||||
> Create `AGENTS.md` at repo root with compact, high-signal instructions for future OpenCode sessions. Replace stale `CLAUDE.md` claims. Verify all facts from executable sources.
|
||||
>
|
||||
> **Deliverables**: `AGENTS.md` (new file), committed and pushed to `main`
|
||||
>
|
||||
> **Estimated Effort**: Quick
|
||||
> **Parallel Execution**: NO — single task
|
||||
> **Critical Path**: Task 1 only
|
||||
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
### Original Request
|
||||
User: "обнови Agents.md" (Create or update `AGENTS.md` for this repository).
|
||||
|
||||
### Key Facts Discovered
|
||||
- **Project**: Astro 4 + Tailwind CSS 4 static site, 28 random-value generators (bilingual EN/RU)
|
||||
- **Deploy**: GitHub Actions + rsync to reg.ru on push to `main`
|
||||
- **CI gate order**: `npm ci` → `npm run lint` → `npm run test` → `npm run build` → `rsync`
|
||||
- **i18n**: Astro built-in routing, `defaultLocale: "en"`, `prefixDefaultLocale: false`. EN at `src/pages/`, RU at `src/pages/ru/`. Locale derived from `Astro.currentLocale`.
|
||||
- **CRITICAL quirk**: Never use shared dynamic `[slug].astro` for RU pages — Astro bundles all imported component scripts, causing every RU page to run all 28 generator scripts.
|
||||
- **Generators**: 28 live. Each requires 4 files: content JSON (EN+RU fields), component, EN page, RU page.
|
||||
- **Content schema**: Zod `.strict()` in `src/lib/generator-schema.ts` — unknown fields fail build.
|
||||
- **Shared utilities**: `src/lib/client/random.ts` (crypto `getRandomValues`), `src/lib/client/i18n.ts` (client locale helpers). All 28 generators refactored to use these (zero `Math.random`).
|
||||
- **Dice engine**: deduplicated into `src/lib/dice-engine.ts`, imported by `DiceGenerator.astro`.
|
||||
- **Test runner**: Vitest v4, `environment: "node"`, `include: ["src/**/*.test.ts"]`.
|
||||
- **Lint**: ESLint via `eslint.config.mjs`, ignores `dist/`, `.astro/`, `node_modules/`, `src/env.d.ts`.
|
||||
- **CLAUDE.md is stale**: claims "10 generators" and "No test runner or linter is configured" — both false.
|
||||
- **No existing agent instruction files**: no `.cursorrules`, `.cursor/rules/`, `.github/copilot-instructions.md`, `opencode.json`.
|
||||
|
||||
### Metis Review
|
||||
- No gaps identified — repo answers all important questions.
|
||||
|
||||
---
|
||||
|
||||
## Work Objectives
|
||||
|
||||
### Core Objective
|
||||
Write a compact `AGENTS.md` at repo root containing only high-signal, repo-specific guidance that future OpenCode agents would likely miss.
|
||||
|
||||
### Concrete Deliverables
|
||||
- `AGENTS.md` file at repo root
|
||||
|
||||
### Definition of Done
|
||||
- [ ] `AGENTS.md` exists at repo root
|
||||
- [ ] `npm run lint` passes (0 errors)
|
||||
- [ ] `npm run build` passes (62 pages)
|
||||
|
||||
### Must Have
|
||||
- Exact developer commands
|
||||
- CI gate order
|
||||
- i18n routing quirks and the `[slug].astro` prohibition
|
||||
- Generator addition workflow (4 steps)
|
||||
- Zod strict schema warning
|
||||
- Shared utilities architecture (random.ts, i18n.ts, dice-engine.ts)
|
||||
- Stale CLAUDE.md warnings
|
||||
|
||||
### Must NOT Have
|
||||
- Generic software advice
|
||||
- Long tutorials or exhaustive file trees
|
||||
- Obvious language conventions
|
||||
- Speculative claims
|
||||
|
||||
---
|
||||
|
||||
## Verification Strategy
|
||||
|
||||
### Test Decision
|
||||
- **Infrastructure exists**: YES
|
||||
- **Automated tests**: NO (not needed for doc file)
|
||||
- **Agent-Executed QA**: YES — verify lint and build pass after file creation
|
||||
|
||||
### QA Policy
|
||||
Every task MUST include agent-executed QA scenarios.
|
||||
|
||||
---
|
||||
|
||||
## Execution Strategy
|
||||
|
||||
### Wave 1 (Single Task)
|
||||
|
||||
- **Task 1**: Write `AGENTS.md`
|
||||
|
||||
---
|
||||
|
||||
## TODOs
|
||||
|
||||
- [ ] 1. Write AGENTS.md
|
||||
|
||||
**What to do**:
|
||||
- Create `/home/emil/Desktop/Coding/AI/Randify.pro/AGENTS.md` with the following verified content:
|
||||
- Project overview (28 generators, Astro 4 + Tailwind 4)
|
||||
- Developer commands (exact npm scripts)
|
||||
- CI gate order
|
||||
- i18n routing architecture and `[slug].astro` prohibition
|
||||
- Path alias `@/* → src/*`
|
||||
- Shared utilities table (random.ts, i18n.ts, dice-engine.ts)
|
||||
- Shared components (ResultBox.astro, CopyButton.astro)
|
||||
- Adding a generator: 4-step workflow
|
||||
- Key conventions (accent color, icons, analytics IDs)
|
||||
- Stale CLAUDE.md warnings
|
||||
- Testing, lint & format notes
|
||||
- Build artifacts and operational gotchas
|
||||
- Use compact bullets, not prose paragraphs.
|
||||
- Verify no generic advice included.
|
||||
|
||||
**Must NOT do**:
|
||||
- Do NOT include generic software advice
|
||||
- Do NOT write long tutorials
|
||||
- Do NOT include obvious conventions
|
||||
- Do NOT make speculative claims
|
||||
- Do NOT touch `CLAUDE.md` (leave it as-is; AGENTS.md is the new source of truth)
|
||||
|
||||
**Recommended Agent Profile**:
|
||||
- **Category**: `quick`
|
||||
- **Skills**: []
|
||||
|
||||
**Parallelization**:
|
||||
- **Can Run In Parallel**: NO
|
||||
- **Parallel Group**: Sequential
|
||||
- **Blocks**: None
|
||||
- **Blocked By**: None
|
||||
|
||||
**References**:
|
||||
- `CLAUDE.md` — existing guidance (partially stale, use for comparison only)
|
||||
- `package.json` — exact npm scripts
|
||||
- `astro.config.mjs` — i18n routing config
|
||||
- `vitest.config.ts` — test config
|
||||
- `eslint.config.mjs` — lint rules and ignores
|
||||
- `.github/workflows/deploy.yml` — CI gate order
|
||||
- `src/lib/generator-schema.ts` — Zod strict schema
|
||||
- `src/lib/client/random.ts` — crypto random utility
|
||||
- `src/lib/client/i18n.ts` — client i18n helper
|
||||
- `src/lib/dice-engine.ts` — canonical dice engine
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] `AGENTS.md` exists at `/home/emil/Desktop/Coding/AI/Randify.pro/AGENTS.md`
|
||||
- [ ] `npm run lint` → PASS (0 errors)
|
||||
- [ ] `npm run build` → PASS (62 pages generated)
|
||||
|
||||
**QA Scenarios**:
|
||||
|
||||
```
|
||||
Scenario: File created and lint passes
|
||||
Tool: Bash
|
||||
Preconditions: None
|
||||
Steps:
|
||||
1. Read AGENTS.md and verify it contains: "28 random-value generators", "CI gate order", "[slug].astro" warning, "Zod .strict()" warning, shared utilities table
|
||||
2. Run: npm run lint
|
||||
3. Assert: 0 errors
|
||||
Expected Result: lint exits 0, no errors
|
||||
Evidence: .sisyphus/evidence/agents-lint.txt
|
||||
|
||||
Scenario: Build passes after file creation
|
||||
Tool: Bash
|
||||
Preconditions: None
|
||||
Steps:
|
||||
1. Run: npm run build
|
||||
2. Assert: "62 pages" in output, exit code 0
|
||||
Expected Result: 62 pages generated, exit code 0
|
||||
Evidence: .sisyphus/evidence/agents-build.txt
|
||||
```
|
||||
|
||||
**Evidence to Capture**:
|
||||
- [ ] `.sisyphus/evidence/agents-lint.txt`
|
||||
- [ ] `.sisyphus/evidence/agents-build.txt`
|
||||
|
||||
**Commit**: YES
|
||||
- Message: `docs: add AGENTS.md with high-signal repo guidance`
|
||||
- Files: `AGENTS.md`
|
||||
- Pre-commit: `npm run lint && npm run build`
|
||||
|
||||
---
|
||||
|
||||
## Commit Strategy
|
||||
|
||||
- **1**: `docs: add AGENTS.md with high-signal repo guidance` — AGENTS.md, npm run lint && npm run build
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
### Verification Commands
|
||||
```bash
|
||||
npm run lint # Expected: 0 errors
|
||||
npm run build # Expected: 62 pages
|
||||
```
|
||||
|
||||
### Final Checklist
|
||||
- [ ] AGENTS.md exists at repo root
|
||||
- [ ] Contains 28 generators count (not 10)
|
||||
- [ ] Contains exact CI gate order
|
||||
- [ ] Contains [slug].astro prohibition
|
||||
- [ ] Contains Zod strict warning
|
||||
- [ ] Lint passes
|
||||
- [ ] Build passes
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"sessionID": "ses_1dca376a3ffewdLYKY0T5iMPdZ",
|
||||
"updatedAt": "2026-05-13T22:04:09.510Z",
|
||||
"sources": {
|
||||
"background-task": {
|
||||
"state": "idle",
|
||||
"updatedAt": "2026-05-13T22:04:09.510Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"sessionID": "ses_1de6ede59ffexUwt5C0sddEWwR",
|
||||
"updatedAt": "2026-05-13T13:53:55.077Z",
|
||||
"updatedAt": "2026-05-13T22:03:12.991Z",
|
||||
"sources": {
|
||||
"background-task": {
|
||||
"state": "idle",
|
||||
"updatedAt": "2026-05-13T13:53:55.077Z"
|
||||
"updatedAt": "2026-05-13T22:03:12.991Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-1
@@ -4,7 +4,15 @@ import sitemap from "@astrojs/sitemap";
|
||||
|
||||
export default defineConfig({
|
||||
site: "https://randify.pro",
|
||||
integrations: [sitemap()],
|
||||
integrations: [sitemap({
|
||||
i18n: {
|
||||
defaultLocale: "en",
|
||||
locales: {
|
||||
en: "en-US",
|
||||
ru: "ru-RU",
|
||||
},
|
||||
},
|
||||
})],
|
||||
vite: {
|
||||
plugins: [tailwindcss()],
|
||||
},
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
@@ -26,12 +26,18 @@
|
||||
"faq": [
|
||||
{ "q": "What color formats are supported?", "a": "HEX, RGB, and HSL. All three are shown at once, so you can copy the one you need." },
|
||||
{ "q": "Can I use the generated color in CSS?", "a": "Yes. Copy the HEX or RGB value and paste it directly into your stylesheet or design tool." },
|
||||
{ "q": "Are the colors truly random?", "a": "Yes. Each color is generated using a cryptographically secure random number generator, covering the entire color space." }
|
||||
{ "q": "Are the colors truly random?", "a": "Yes. Each color is generated using a cryptographically secure random number generator, covering the entire color space." },
|
||||
{ "q": "What color formats are supported?", "a": "HEX, RGB, and HSL. All three are shown simultaneously for every generated color." },
|
||||
{ "q": "Can I copy just one format?", "a": "Yes. Click the copy icon next to any format to copy only that value." },
|
||||
{ "q": "Are the colors truly random?", "a": "Yes. Each color is generated using random values for hue, saturation, and lightness." }
|
||||
],
|
||||
"ruFaq": [
|
||||
{ "q": "Какие форматы цветов поддерживаются?", "a": "HEX, RGB и HSL. Все три формата отображаются одновременно — скопируйте тот, который нужен." },
|
||||
{ "q": "Можно ли использовать сгенерированный цвет в CSS?", "a": "Да. Скопируйте значение HEX или RGB и вставьте его прямо в стили или графический редактор." },
|
||||
{ "q": "Цвета действительно случайные?", "a": "Да. Каждый цвет генерируется с помощью криптографически стойкого генератора случайных чисел, покрывая всё цветовое пространство." }
|
||||
{ "q": "Цвета действительно случайные?", "a": "Да. Каждый цвет генерируется с помощью криптографически стойкого генератора случайных чисел, покрывая всё цветовое пространство." },
|
||||
{ "q": "Какие форматы цветов поддерживаются?", "a": "HEX, RGB и HSL. Все три отображаются одновременно для каждого сгенерированного цвета." },
|
||||
{ "q": "Можно скопировать только один формат?", "a": "Да. Нажмите иконку копирования рядом с нужным форматом." },
|
||||
{ "q": "Цвета действительно случайные?", "a": "Да. Каждый цвет генерируется из случайных значений оттенка, насыщенности и освещённости." }
|
||||
],
|
||||
"ruHowTo": [
|
||||
"Нажмите «Сгенерировать», чтобы получить случайный цвет.",
|
||||
|
||||
@@ -29,12 +29,18 @@
|
||||
"faq": [
|
||||
{ "q": "What dice notation can I use?", "a": "You can use standard XdY+Z notation, plus modifiers like advantage, disadvantage, keep/drop (kh/kl/dl/dh), and exploding dice (!)." },
|
||||
{ "q": "Is this fair for D&D and other RPGs?", "a": "Yes. Randify uses the browser's cryptographically secure random number generator, so every roll is unbiased." },
|
||||
{ "q": "Can I roll multiple dice at once?", "a": "Absolutely. Enter something like 5d6 or click the die buttons and set the count to roll up to 20 dice in a single throw." }
|
||||
{ "q": "Can I roll multiple dice at once?", "a": "Absolutely. Enter something like 5d6 or click the die buttons and set the count to roll up to 20 dice in a single throw." },
|
||||
{ "q": "What dice notation is supported?", "a": "Standard XdY+Z, advantage/disadvantage, keep/drop (kh/kl/dh/dl), reroll (r), and exploding dice (!)." },
|
||||
{ "q": "Can I roll more than one type of die at once?", "a": "Yes. Enter multiple notations separated by spaces, like 2d6 1d20." },
|
||||
{ "q": "Is the roll history saved?", "a": "Yes. Your last rolls are shown below the results until you refresh the page." }
|
||||
],
|
||||
"ruFaq": [
|
||||
{ "q": "Какую нотацию кубиков поддерживает генератор?", "a": "Стандартную нотацию XdY+Z, а также модификаторы: преимущество, помеха, keep/drop (kh/kl/dl/dh) и взрывающиеся кубики (!)." },
|
||||
{ "q": "Подходит ли генератор для D&D и других НРИ?", "a": "Да. Randify использует криптографически стойкий генератор случайных чисел браузера, поэтому каждый бросок честный и непредвзятый." },
|
||||
{ "q": "Можно ли бросать несколько кубиков одновременно?", "a": "Конечно. Введите что-то вроде 5d6 или настройте кубики вручную — можно бросить до 20 кубиков за раз." }
|
||||
{ "q": "Можно ли бросать несколько кубиков одновременно?", "a": "Конечно. Введите что-то вроде 5d6 или настройте кубики вручную — можно бросить до 20 кубиков за раз." },
|
||||
{ "q": "Какая нотация кубиков поддерживается?", "a": "Стандартная XdY+Z, преимущество/помеха, keep/drop (kh/kl/dh/dl), переброс (r) и взрывающиеся кубики (!)." },
|
||||
{ "q": "Можно ли бросить несколько типов кубиков сразу?", "a": "Да. Введите несколько нотаций через пробел, например 2d6 1d20." },
|
||||
{ "q": "История бросков сохраняется?", "a": "Да. Последние броски отображаются под результатами до обновления страницы." }
|
||||
],
|
||||
"ruHowTo": [
|
||||
"Введите нотацию, например 2d6+3 или 1d20 — или настройте кубики вручную.",
|
||||
|
||||
@@ -27,12 +27,18 @@
|
||||
"faq": [
|
||||
{ "q": "Can the same item be picked more than once?", "a": "Only if you enable the 'Allow duplicates' toggle. By default, each item can be chosen only once per draw." },
|
||||
{ "q": "Is there a limit to how many items I can add?", "a": "You can add up to 1,000 items. For most use cases — giveaways, raffles, or team assignments — this is more than enough." },
|
||||
{ "q": "Can I pick multiple winners at once?", "a": "Yes. Set the 'Pick' field to any number up to the total count of items, and Randify will select that many winners in one go." }
|
||||
{ "q": "Can I pick multiple winners at once?", "a": "Yes. Set the 'Pick' field to any number up to the total count of items, and Randify will select that many winners in one go." },
|
||||
{ "q": "Can the same item be picked more than once?", "a": "Only if you toggle Allow duplicates. By default, each item is picked at most once." },
|
||||
{ "q": "Is there a limit to how many items I can add?", "a": "You can add up to 500 items, and pick up to the total number of unique items." },
|
||||
{ "q": "Does the order of items matter?", "a": "No. The selection is completely random regardless of the order you enter items." }
|
||||
],
|
||||
"ruFaq": [
|
||||
{ "q": "Может ли один и тот же элемент выпасть несколько раз?", "a": "Только если включён переключатель «Разрешить повторения». По умолчанию каждый элемент выбирается не более одного раза." },
|
||||
{ "q": "Есть ли ограничение на количество элементов в списке?", "a": "Можно добавить до 1 000 элементов. Для розыгрышей, жеребьёвок и распределения задач этого более чем достаточно." },
|
||||
{ "q": "Можно ли выбрать несколько победителей сразу?", "a": "Да. Укажите в поле «Выбрать» любое число до общего количества элементов — Randify выберет нужное количество победителей за один раз." }
|
||||
{ "q": "Можно ли выбрать несколько победителей сразу?", "a": "Да. Укажите в поле «Выбрать» любое число до общего количества элементов — Randify выберет нужное количество победителей за один раз." },
|
||||
{ "q": "Может ли один элемент выпасть несколько раз?", "a": "Только если включена опция «Разрешить повторения». По умолчанию каждый элемент выбирается не более одного раза." },
|
||||
{ "q": "Есть ли ограничение на количество элементов?", "a": "Можно добавить до 500 элементов и выбрать до общего числа уникальных элементов." },
|
||||
{ "q": "Имеет ли значение порядок элементов?", "a": "Нет. Выбор полностью случайный независимо от порядка ввода." }
|
||||
],
|
||||
"ruHowTo": [
|
||||
"Введите список элементов — по одному на строку.",
|
||||
|
||||
@@ -9,12 +9,15 @@ import type { Lang } from "../i18n/translations";
|
||||
interface Props {
|
||||
title?: string;
|
||||
description?: string;
|
||||
ogImage?: string;
|
||||
}
|
||||
|
||||
const lang = (Astro.currentLocale as Lang) || "en";
|
||||
const T = useT(lang);
|
||||
|
||||
const { title = T.defaultTitle, description = T.defaultDesc } = Astro.props;
|
||||
const { title = T.defaultTitle, description = T.defaultDesc, ogImage = "/og-default.jpg" } = Astro.props;
|
||||
|
||||
const ogImageUrl = ogImage.startsWith("http") ? ogImage : `https://randify.pro${ogImage}`;
|
||||
|
||||
const pathWithoutLocale = Astro.url.pathname.replace(/^\/ru/, "") || "/";
|
||||
const enUrl = `https://randify.pro${getRelativeLocaleUrl("en", pathWithoutLocale)}`;
|
||||
@@ -48,6 +51,7 @@ const webPageSchema = {
|
||||
<link rel="canonical" href={canonicalUrl} />
|
||||
<link rel="alternate" hreflang="en" href={enUrl} />
|
||||
<link rel="alternate" hreflang="ru" href={ruUrl} />
|
||||
<link rel="alternate" hreflang="x-default" href={enUrl} />
|
||||
<meta name="verification" content="er9ndnv9ih7agmh8" />
|
||||
<script
|
||||
type="application/ld+json"
|
||||
@@ -61,6 +65,17 @@ const webPageSchema = {
|
||||
<script src="https://yandex.ru/ads/system/context.js" async></script>
|
||||
<slot name="head" />
|
||||
<title>{title}</title>
|
||||
<meta property="og:site_name" content="Randify" />
|
||||
<meta property="og:locale" content={lang === "ru" ? "ru_RU" : "en_US"} />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:url" content={canonicalUrl} />
|
||||
<meta property="og:image" content={ogImageUrl} />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content={title} />
|
||||
<meta name="twitter:description" content={description} />
|
||||
<meta name="twitter:image" content={ogImageUrl} />
|
||||
<Analytics />
|
||||
<script>
|
||||
if ("serviceWorker" in navigator) {
|
||||
|
||||
@@ -59,6 +59,7 @@ const aboutSchema = {
|
||||
<div class="w-16 h-0.5 bg-accent/60 rounded-full mt-4" aria-hidden="true"></div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div class="border-t border-zinc-800/60 pt-8 mt-8 space-y-8">
|
||||
<section>
|
||||
<h2 class="text-lg font-semibold text-zinc-100 mb-2">Mission</h2>
|
||||
@@ -91,5 +92,6 @@ const aboutSchema = {
|
||||
</a>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</BaseLayout>
|
||||
|
||||
@@ -47,8 +47,6 @@ const webSiteSchema = {
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<YandexRTB />
|
||||
|
||||
<main class="mt-8">
|
||||
<div
|
||||
class="grid gap-3"
|
||||
@@ -65,5 +63,7 @@ const webSiteSchema = {
|
||||
}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<YandexRTB />
|
||||
</div>
|
||||
</BaseLayout>
|
||||
|
||||
@@ -49,6 +49,7 @@ const T = useT(lang);
|
||||
<div class="w-16 h-0.5 bg-accent/60 rounded-full mt-4" aria-hidden="true"></div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div class="border-t border-zinc-800/60 pt-8 mt-8 space-y-8">
|
||||
<section>
|
||||
<p class="text-zinc-400 leading-relaxed">{T.privacyIntro}</p>
|
||||
@@ -81,5 +82,6 @@ const T = useT(lang);
|
||||
<p class="text-zinc-400 leading-relaxed">{T.privacyChanges}</p>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</BaseLayout>
|
||||
|
||||
@@ -59,6 +59,7 @@ const aboutSchema = {
|
||||
<div class="w-16 h-0.5 bg-accent/60 rounded-full mt-4" aria-hidden="true"></div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div class="border-t border-zinc-800/60 pt-8 mt-8 space-y-8">
|
||||
<section>
|
||||
<h2 class="text-lg font-semibold text-zinc-100 mb-2">Миссия</h2>
|
||||
@@ -91,5 +92,6 @@ const aboutSchema = {
|
||||
</a>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</BaseLayout>
|
||||
|
||||
@@ -49,6 +49,7 @@ const T = useT(lang);
|
||||
<div class="w-16 h-0.5 bg-accent/60 rounded-full mt-4" aria-hidden="true"></div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<div class="border-t border-zinc-800/60 pt-8 mt-8 space-y-8">
|
||||
<section>
|
||||
<p class="text-zinc-400 leading-relaxed">{T.privacyIntro}</p>
|
||||
@@ -81,5 +82,6 @@ const T = useT(lang);
|
||||
<p class="text-zinc-400 leading-relaxed">{T.privacyChanges}</p>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</BaseLayout>
|
||||
|
||||
Reference in New Issue
Block a user