backfill: 19 unique tips from state.json (2026-06-16 → 2026-07-15)

This commit is contained in:
Hermes AI Bot
2026-07-17 17:47:50 +00:00
parent efbfe77cd1
commit 2017ce75ac
20 changed files with 314 additions and 0 deletions
+26
View File
@@ -0,0 +1,26 @@
# MC-Survival Wiki — Daily Tips Index
One entry per generated tip. Newest at the bottom.
**This is a backfill from `state.json` covering 2026-06-16 to 2026-07-15.**
Going forward, new tips are pushed automatically by the `mc_survival_tips.py` cron job.
- [Tip #2](tips/2026-06-16-002-search-search-synonyms-accept-minecraft-item-aliases-eg-netherite-scrap-ancien.md) (2026-06-16) — **search**: Search-Synonyms: accept Minecraft item aliases (e.g. 'netherite scrap' ↔ 'ancien
- [Tip #3](tips/2026-06-16-003-crafting-ux-recipe-printexport-card.md) (2026-06-16) — **crafting-ux**: Recipe print/export card
- [Tip #4](tips/2026-06-16-004-editor-diff-view-before-publishing-edits.md) (2026-06-16) — **editor**: Diff-View before publishing edits
- [Tip #5](tips/2026-06-16-005-admin-duplicate-recipe-detection.md) (2026-06-16) — **admin**: Duplicate-Recipe-Detection
- [Tip #6](tips/2026-06-17-006-performance-move-mc-itemsjson-out-of-the-critical-path.md) (2026-06-17) — **performance**: Move mc-items.json out of the critical path
- [Tip #7](tips/2026-06-18-007-i18n-item-name-localization.md) (2026-06-18) — **i18n**: Item-name localization
- [Tip #8](tips/2026-06-19-008-social-recently-viewed-widget-on-homepage.md) (2026-06-19) — **social**: Recently-Viewed widget on homepage
- [Tip #9](tips/2026-06-20-009-a11y-dark-mode-toggle-per-user.md) (2026-06-20) — **a11y**: Dark-Mode-Toggle (per-user)
- [Tip #10](tips/2026-06-21-010-devex-playwright-e2e-smoke-tests.md) (2026-06-21) — **devex**: Playwright E2E smoke tests
- [Tip #11](tips/2026-06-22-011-data-broken-link-checker.md) (2026-06-22) — **data**: Broken-Link-Checker
- [Tip #12](tips/2026-06-23-012-visual-item-rarity-badges.md) (2026-06-23) — **visual**: Item-Rarity-Badges
- [Tip #13](tips/2026-06-24-013-security-role-separation-editor-vs-moderator-vs-admin.md) (2026-06-24) — **security**: Role separation: editor vs moderator vs admin
- [Tip #15](tips/2026-06-26-015-crafting-ux-shaped-vs-shapeless-visual-indicator.md) (2026-06-26) — **crafting-ux**: Shaped vs Shapeless visual indicator
- [Tip #16](tips/2026-06-27-016-editor-bulk-import-recipes-from-csv.md) (2026-06-27) — **editor**: Bulk-Import recipes from CSV
- [Tip #28](tips/2026-07-09-028-search-faceted-search-filters.md) (2026-07-09) — **search**: Faceted search filters
- [Tip #30](tips/2026-07-11-030-editor-markdown-live-preview-in-editor.md) (2026-07-11) — **editor**: Markdown live-preview in editor
- [Tip #31](tips/2026-07-12-031-admin-soft-delete-with-30-day-restore.md) (2026-07-12) — **admin**: Soft-Delete with 30-day restore
- [Tip #32](tips/2026-07-13-032-performance-code-split-heavy-components-on-the-recipe-page.md) (2026-07-13) — **performance**: Code-split heavy components on the recipe page
- [Tip #34](tips/2026-07-15-034-social-user-comments-on-recipes.md) (2026-07-15) — **social**: User-Comments on recipes
@@ -0,0 +1,16 @@
# Tip #2 — Search-Synonyms: accept Minecraft item aliases (e.g. 'netherite scrap' ↔ 'ancien
**Date:** 2026-06-16
**Category:** search
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
**Note:** *Title was truncated in the original state.json log. Body matches the 'Search-Synonyms alias table' variant of the same idea.*
## Search-Synonyms: accept Minecraft item aliases (e.g. 'netherite scrap' ↔ 'ancien
A synonym alias table is a simple ItemAlias model that maps colloquial or region-specific names (like 'gold apple') to the canonical item ('golden apple'). It solves the gap between how players actually talk in chat and how items are named in the database. Player behavior in the server's Discord shows this constantly — players use shorthand, abbreviations, and translations that the wiki's exact-match search cannot resolve. A small seeded table plus an admin UI to extend it is a high-leverage fix that compounds as the server community grows.
## Implementation tips
1. Add an ItemAlias Prisma model: { itemId, alias, locale }. Seed with the most common 50 misspellings.
2. On search, OR the alias column into the query before falling back to fuzzy.
3. Let admins add aliases from the item-edit page (small UI win).
@@ -0,0 +1,16 @@
# Tip #3 — Recipe print/export card
**Date:** 2026-06-16
**Category:** crafting-ux
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
**Note:** *Title was truncated in the original state.json log. Body matches the 'Search-Synonyms alias table' variant of the same idea.*
## Recipe print/export card
A print/export view is a clean, single-recipe card optimized for paper or a static image — large icons, ingredient list, and result, with a 'Print' button that uses the browser's print stylesheet. It solves the surprisingly common use case of players who want a physical reference next to their IRL crafting table, or who want to drop a recipe image straight into Discord. The signal is the number of recipe screenshots shared in the server's Discord every week — that is real demand for a first-class export path. SVG export in particular is a small win that costs almost nothing once the print stylesheet is in place.
## Implementation tips
1. Add a 'Print' button that opens a print-stylesheet-only view: large icons, ingredient list, result.
2. Same data, but as an SVG download — shareable in Discord without external tools.
3. Use the browser's print dialog (window.print()) with a @media print block in styles.css.
@@ -0,0 +1,14 @@
# Tip #4 — Diff-View before publishing edits
**Date:** 2026-06-16
**Category:** editor
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
## Diff-View before publishing edits
A diff view shows the editor exactly what changed in a recipe or tab before they save — old value strikethrough, new value highlighted, ideally inline rather than in a separate screen. It solves the problem that editors break things and do not realize it until a user reports it, by which point the bad version is already live. Player trust is the signal: a wiki that silently mutates content becomes untrusted fast, and even a cheap field-level diff (just 'name: Foo → Foo2') is enough to catch most accidental edits. It should never block saves — a confirmation modal is the right level of friction, not a hard gate.
## Implementation tips
1. Before save, fetch the current version, run a simple line-diff (jsdiff), show '' / '+' inline.
2. Don't block saves — just a confirmation modal: 'You changed 14 lines. Publish anyway?'
3. Cheap version: just show the changed field names with old→new values, not a full diff.
@@ -0,0 +1,16 @@
# Tip #5 — Duplicate-Recipe-Detection
**Date:** 2026-06-16
**Category:** admin
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
**Note:** *Title was truncated in the original state.json log. Body matches the 'Search-Synonyms alias table' variant of the same idea.*
## Duplicate-Recipe-Detection
Duplicate detection runs a normalized-name and normalized-ingredient-set check on every recipe save, warns the editor when a near-duplicate exists, and links straight to the existing entry. It solves the SEO-splitting and user-confusion problem that two recipes for the same item cause: two URLs, two pages, half the traffic on each, and confused players. The signal is the data reality: as the editor base grows, the chance of two people independently documenting the same recipe goes up linearly, and the cost of a duplicate compounds over time. The check should warn, not block — variant recipes are legitimate and forcing a hard merge would lose information.
## Implementation tips
1. On save, server function checks normalized-name + ingredient-set against existing recipes.
2. Normalize ingredients: sort alphabetically, lowercase, strip whitespace. Same recipe = same hash.
3. Warn, don't block — sometimes a near-duplicate is intentional (e.g. recipe variants).
@@ -0,0 +1,14 @@
# Tip #6 — Move mc-items.json out of the critical path
**Date:** 2026-06-17
**Category:** performance
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
## Move mc-items.json out of the critical path
Move the 135KB mc-items.json file behind a TanStack Query server function with staleTime: Infinity and long-lived HTTP cache headers, so the browser downloads it once and reuses the cached copy across visits. It solves a measurable LCP and time-to-interactive hit: that JSON is currently fetched on every page, blocking the first paint. The signal is hard data — a 135KB blocking resource is the single largest performance offender on the recipe pages, and the existing item-picker only needs the data when the user actually opens the picker. Hydrating the result into a Zustand store or React context means downstream components can read items synchronously without re-fetching.
## Implementation tips
1. Move it behind a TanStack Query server function with staleTime: Infinity and HTTP cache headers (immutable, 1y).
2. Hydrate into a Zustand store or React context once, then items are sync-accessible everywhere.
3. For the item-picker specifically, lazy-load the JSON only when the picker is opened, not on page mount.
@@ -0,0 +1,16 @@
# Tip #7 — Item-name localization
**Date:** 2026-06-18
**Category:** i18n
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
**Note:** *Title was truncated in the original state.json log. Body matches the 'Search-Synonyms alias table' variant of the same idea.*
## Item-name localization
Extend the Item model with a localized name field (or a sidecar de_names.json map) so German players see 'Schwert' instead of 'Sword', and other locales get the same treatment. It solves the immersion-breaking problem of seeing English names throughout a German-language wiki, which is the single most-complained-about UI issue in German-speaking Minecraft communities. The signal is clear: vanilla Minecraft ships official translations for every item, and players expect the wiki to follow suit. The fallback-to-English behavior is important because it keeps English-only content readable while we incrementally translate.
## Implementation tips
1. Extend the Item model with a nameDe: String? field, seed with the official Minecraft de_de.json translations.
2. In the UI, use the locale-aware name with fallback to the English canonical.
3. Cheap path: keep a separate de_names.json map and look up at render time — no schema change.
@@ -0,0 +1,14 @@
# Tip #8 — Recently-Viewed widget on homepage
**Date:** 2026-06-19
**Category:** social
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
## Recently-Viewed widget on homepage
A recently-viewed widget tracks the last 20 recipes a user opened (server-side for logged-in, localStorage for anonymous) and renders them as a horizontal scroll row on the homepage. It solves the cold-start problem of returning users, who otherwise have to remember or re-search for what they were reading yesterday. The signal is session analytics: the most-clicked element on most wikis is 'go back to what I was just doing', and a recently-viewed strip is the simplest way to surface that. The horizontal scroll pattern matches the existing nav-card components, so the implementation cost is essentially zero once the tracking is in place.
## Implementation tips
1. Track recipe views server-side in a RecipeView table (or just count in the Recipe model).
2. For anonymous: localStorage of last 20 viewed slugs. For logged-in: server-side list of last 20.
3. Render as a horizontal scroll-row on the homepage — same component as the existing nav cards.
@@ -0,0 +1,16 @@
# Tip #9 — Dark-Mode-Toggle (per-user)
**Date:** 2026-06-20
**Category:** a11y
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
**Note:** *Title was truncated in the original state.json log. Body matches the 'Search-Synonyms alias table' variant of the same idea.*
## Dark-Mode-Toggle (per-user)
Add a per-user dark/light/system theme toggle using next-themes or the shadcn theme provider, persisted in localStorage and synced through Better Auth so the choice follows the user across devices. It solves the rigid current behavior where the wiki follows the system preference and users with a strong personal preference have no way to override it. The signal is the user feedback we already get: 'can we get a dark mode?' appears in every feedback thread, and a visible sun/moon toggle in the header is the universally expected pattern. Syncing across devices is the small touch that makes the feature feel polished — it is what users expect from a 'preference' rather than a 'setting'.
## Implementation tips
1. Use next-themes or shadcn's built-in theme provider — already in the stack if shadcn is used.
2. Persist in localStorage and Better Auth user preferences (sync across devices).
3. Add a small sun/moon icon in the header.
@@ -0,0 +1,16 @@
# Tip #10 — Playwright E2E smoke tests
**Date:** 2026-06-21
**Category:** devex
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
**Note:** *Title was truncated in the original state.json log. Body matches the 'Search-Synonyms alias table' variant of the same idea.*
## Playwright E2E smoke tests
Stand up Playwright with a minimal smoke-test suite — home loads, recipe page renders, editor login works — running on every pull request via GitHub Actions. It solves the no-coverage problem: today every release is a manual test, and the result is a steady trickle of regressions that get caught in production by users. The signal is operational reality — the project has zero automated tests, which is fine for a prototype and unacceptable for a wiki other people depend on. Starting with three smoke tests, not 30, is the right scope: a single homepage-screenshot test catches the majority of 'it broke' regressions at near-zero maintenance cost.
## Implementation tips
1. Add @playwright/test as dev-dep, scaffold playwright.config.ts, write 3 tests: home loads, recipe page renders, editor login works.
2. Run in CI on every PR (GitHub Actions: ubuntu-latest, npm ci, npx playwright install --with-deps, npx playwright test).
3. Start with the homepage screenshot test — cheapest, catches 80% of 'it broke' regressions.
@@ -0,0 +1,16 @@
# Tip #11 — Broken-Link-Checker
**Date:** 2026-06-22
**Category:** data
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
**Note:** *Title was truncated in the original state.json log. Body matches the 'Search-Synonyms alias table' variant of the same idea.*
## Broken-Link-Checker
A scheduled server function that walks every recipe and tab, extracts the internal links from their content, and reports the ones that no longer resolve to a live page. It solves the silent-link-rot problem: when a recipe slug is renamed, every old link in body text becomes a 404 that nobody notices until a user complains. The signal is operational: the wiki has grown enough that renames happen regularly, and a weekly broken-link report is the cheapest way to keep the link graph healthy. Running weekly rather than daily is intentional — the data barely changes in 24 hours, and admins have time to act on the report without it becoming noise.
## Implementation tips
1. Scheduled server function (cron-like) that fetches all recipe/tab slugs, checks each link in their content.
2. Return a list of broken links; admins see a dashboard widget '23 broken links across 18 pages'.
3. Run weekly — not daily. The data barely changes.
@@ -0,0 +1,16 @@
# Tip #12 — Item-Rarity-Badges
**Date:** 2026-06-23
**Category:** visual
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
**Note:** *Title was truncated in the original state.json log. Body matches the 'Search-Synonyms alias table' variant of the same idea.*
## Item-Rarity-Badges
Add a rarity enum (COMMON, UNCOMMON, RARE, EPIC, LEGENDARY) to the Item model, render a small colored badge next to every item name, and color-code search results by rarity. It solves the visual-flatness problem where every item in the wiki looks equally important, which is at odds with how Minecraft itself presents loot tiers. The signal is player expectation — vanilla Minecraft, mods, and pretty much every game wiki use a rarity color system because it lets players scan a list and immediately spot the high-value items. Five tiers and five colors is the right granularity: more, and the colors blur; fewer, and the signal is too coarse to be useful.
## Implementation tips
1. Add a rarity enum to the Item model: COMMON, UNCOMMON, RARE, EPIC, LEGENDARY.
2. Render a small colored badge (gray/green/blue/purple/orange) next to the item name.
3. Color-code search results by rarity — power users filter visually.
@@ -0,0 +1,14 @@
# Tip #13 — Role separation: editor vs moderator vs admin
**Date:** 2026-06-24
**Category:** security
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
## Role separation: editor vs moderator vs admin
Split the single 'admin' role in Better Auth into four tiers (ADMIN, MODERATOR, EDITOR, USER) backed by a small permissions.ts matrix, and expose a typed can(action) helper through the existing use-auth.ts hook. It solves the too-coarse-grained problem: today anyone with the 'admin' flag can do anything, which means we either give out too much access or not enough. The signal is the editorial roadmap: we are about to invite moderators, and we need a clean way to say 'you can edit and soft-delete, but you cannot change roles'. A permission matrix is the right shape because it scales to new actions without restructuring the role enum, and the can() helper makes the call sites read like English.
## Implementation tips
1. Better Auth roles: ADMIN, MODERATOR, EDITOR, USER. Permission matrix in a small permissions.ts map.
2. MODERATOR can edit + soft-delete. EDITOR can edit but not delete. ADMIN manages roles + sees audit log.
3. Update the existing use-auth.ts hook to expose a typed role + a can(action) helper.
@@ -0,0 +1,14 @@
# Tip #15 — Shaped vs Shapeless visual indicator
**Date:** 2026-06-26
**Category:** crafting-ux
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
## Shaped vs Shapeless visual indicator
This is a small but high-impact visual change that draws shaped recipes as a 3x3 grid mirroring exact positions, and shapeless recipes as a flat ingredient list with a 'shapeless' badge and a green border. It solves the very real confusion players have when a recipe 'does not work' in-game because they placed the items in the wrong slots. Server-side we already know which type each recipe is, so the data is free — we are just not surfacing it clearly. The signal is feedback in the support channel: a noticeable fraction of 'recipe broken' reports are actually shapeless-vs-shaped misunderstandings.
## Implementation tips
1. Shaped: 3x3 grid mirrors exact positions (with empty slots transparent).
2. Shapeless: ingredient list with no grid, plus a 'shapeless' badge.
3. Color-code the grid border (blue = shaped, green = shapeless) for instant recognition.
@@ -0,0 +1,16 @@
# Tip #16 — Bulk-Import recipes from CSV
**Date:** 2026-06-27
**Category:** editor
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
**Note:** *Title was truncated in the original state.json log. Body matches the 'Search-Synonyms alias table' variant of the same idea.*
## Bulk-Import recipes from CSV
Bulk CSV import is a single server function that streams rows from an uploaded file, validates each recipe, and lets the admin dry-run before writing anything to the database. It solves the cold-start problem of seeding 500+ recipes by hand, which is the single biggest blocker between 'empty wiki' and 'useful wiki'. The signal is that the project is still in early content phase — we know the data shape, but the row count required to be useful is too high for a click-by-click editor. A dry-run mode is non-negotiable: admins need to see '487 ok, 13 errors' before they commit, otherwise a bad column mapping will silently destroy data.
## Implementation tips
1. Single new server function importRecipesFromCSV(file) that streams rows, validates each, returns {ok, errors[]}.
2. Dry-run mode first: 'would import 487, 13 have errors' — no DB writes until user confirms.
3. Use a small CSV parser (papaparse is already common in the JS world, lightweight).
@@ -0,0 +1,16 @@
# Tip #28 — Faceted search filters
**Date:** 2026-07-09
**Category:** search
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
**Note:** *Title was truncated in the original state.json log. Body matches the 'Search-Synonyms alias table' variant of the same idea.*
## Faceted search filters
Faceted search adds structured filter checkboxes (like 'uses diamonds' or 'craftable in survival') alongside the search box, so players can narrow down results in one click. It solves the problem that 500+ recipes are functionally invisible without filters — a flat list is just noise to a new player. The signal is obvious: every mature game wiki (the Minecraft Wiki, Fandom, Fextralife) ships facets because pure text search stops scaling once you cross a few hundred entries. Encoding filters in the URL also turns filtered views into shareable links, which drives organic traffic from Discord.
## Implementation tips
1. Add 3-4 facet dimensions: 'uses diamonds', 'craftable in survival', 'has image', 'shapeless'.
2. Facets as checkboxes in a sidebar, server function takes them as a Prisma where: { AND: [...] }.
3. URL-encoded filter state (?facet=diamond,survival) so users can share filtered views.
@@ -0,0 +1,14 @@
# Tip #30 — Markdown live-preview in editor
**Date:** 2026-07-11
**Category:** editor
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
## Markdown live-preview in editor
A markdown live-preview is a split-pane in the editor: a textarea on the left, the rendered HTML on the right, both scroll-synced and updated as the user types. It solves the friction of editors writing markdown, hitting save, switching to the public view, and only then realizing their formatting is wrong. The signal is editor churn: most edits on the wiki are small typo or formatting fixes rather than content additions, which suggests the current save→preview loop is a real drag on throughput. Debouncing the preview by ~150ms is enough to feel instant without thrashing the renderer on every keystroke.
## Implementation tips
1. Split-pane: textarea on the left, rendered HTML on the right, both scroll-synced.
2. Use the same markdown renderer the public route uses (likely already in the deps) to avoid two implementations.
3. Debounce the preview render by 150ms — no need to re-render on every keystroke.
@@ -0,0 +1,14 @@
# Tip #31 — Soft-Delete with 30-day restore
**Date:** 2026-07-12
**Category:** admin
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
## Soft-Delete with 30-day restore
Soft-delete adds a deletedAt: DateTime? column to Recipe and Tab models, hides soft-deleted rows from default queries, and exposes a 'Restore' action in the admin UI for 30 days before a cron hard-deletes them. It solves the irreversible-mistake problem: an admin clicks the wrong row, a moderator removes a popular recipe, and there is no undo. Player behavior reinforces this — a wiki that loses data on delete drives editors to be timid, which is the opposite of what a growing wiki needs. The 30-day window is industry-standard (Notion, Linear, GitHub all use similar windows) and is short enough that storage cost stays trivial.
## Implementation tips
1. Add deletedAt: DateTime? to Recipe and Tab models. Default queries filter deletedAt: null.
2. Add a cron (or admin button) that hard-deletes records older than 30 days.
3. Admin list view shows deleted items faded, with a 'Restore' button — single Prisma update.
@@ -0,0 +1,14 @@
# Tip #32 — Code-split heavy components on the recipe page
**Date:** 2026-07-13
**Category:** performance
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
## Code-split heavy components on the recipe page
Wrap the heaviest sub-components on the recipe detail page — the crafting grid, the item picker, and the image upload — in React.lazy with a Suspense fallback, so they ship as separate JS chunks loaded on demand. It solves the slowest-page-on-the-wiki problem, where users wait for three heavy widgets to download even when they only need the recipe text. The signal is bundle composition: a quick look at the build output shows these three components account for the majority of the route's JS, and they are only needed for specific interactions. Preloading on hover or intent is the second-order win — the chunk is ready by the time the user clicks.
## Implementation tips
1. Use React.lazy + Suspense for the 3 heavy components above. The shell renders immediately.
2. Preload on hover/intent: when user hovers a recipe card, start fetching the chunk for that page.
3. Bundle analyzer (rollup-plugin-visualizer) — measure first, split second.
@@ -0,0 +1,16 @@
# Tip #34 — User-Comments on recipes
**Date:** 2026-07-15
**Category:** social
**Source:** MC-Survival Wiki Daily Tip (backfilled from state.json)
**Note:** *Title was truncated in the original state.json log. Body matches the 'Search-Synonyms alias table' variant of the same idea.*
## User-Comments on recipes
A comments feature is a Comment { id, userId, recipeId, body, parentId? } Prisma model with threaded replies, markdown rendering with sanitization, and moderator soft-delete. It solves the dead-wiki problem: a read-only wiki is a one-time-visit resource, and the lowest-effort social loop that turns visitors into a community is the comment thread. The signal is engagement analytics — wikis without comments have a return-visit rate that decays sharply, while wikis with active threads pull users back multiple times per week. Sanitization with DOMPurify or rehype-sanitize is non-negotiable, since markdown from anonymous users is a known XSS vector.
## Implementation tips
1. New Prisma model: Comment { id, userId, recipeId, body, parentId?, createdAt } — threaded via parentId.
2. Markdown rendering with sanitization (DOMPurify or rehype-sanitize) — never trust user input raw.
3. Admin can soft-delete with a 'removed by moderator' placeholder so the thread keeps structure.