Yellow Wing Roasters — Master Technical Debt & Optimization Roadmap (TODO.md)
This document is the authoritative evaluation and backlog for the Yellow Wing Roasters Jekyll codebase. It consolidates the re-evaluation of:
DRY_OPTIMIZATION_RECOMMENDATIONS.mdAGENTS.md&.agents/rules/coding-principles.md.agents/skills/ywr-coding-guidelines/SKILL.md- Operational tracking from
TODO.txt(Email confirmation automation)
1. Executive Summary & Health Scorecard
Over the recent refactoring cycles, major architectural consolidations were achieved:
- Category Engine Unification: Extracted
_includes/category-section.htmland_layouts/category.html, eliminating duplicate category markup across 6 listing pages and retiring 3 bespoke card includes (custom-cards.html,flight-cards.html,subscription-cards.html) in favor of universal_includes/roast-card.html. - Mascot Standardization: Retired the complex “Lazy Susan” component in favor of standard
mascot_file: peck-your-own-transparent.pngfor Peck Your Own, stripping ~190 lines of specialized SCSS. - Data Centralization: Standardized grind levels in
_data/grind_levels.yml, canonical brewing methods inroasts/index.markdown, badge colors in_data/badge_colors.yml, and store delivery radius in_config.yml. - Inline Style Reduction: Cut inline
style="..."attributes from 791 down to 222.
However, deep re-evaluation reveals critical areas that still require immediate attention:
_data/bag_sizes.ymlis orphaned: Created in config but not yet consumed by templates or scripts, leaving hardcoded'12oz', fabricated size arrays ingift.markdown, and static<option>tags in_custom/bring-your-own-burner.md.- Schema.org Multi-tier Ladders:
_layouts/roast.htmlstill has a 5-level fallback ladder forhighPrice. - Silent Early Returns in Client JS:
order-checkout.js,flights.js,byob-burner.js, andmanage-subscriptions.jsstill contain silentif (!element) return;aborts that hide runtime errors. - Flight Mascot Mismatch in JS:
js/flights.jshardcodesaudubon-cardinal-transparent.pngwhen adding Peck Your Own to cart instead of using the newpeck-your-own-transparent.png. - Duplicate Form Submission Iframes: 4 separate client scripts independently create identical hidden
<iframe>DOM nodes for Google Form submissions. - Email Confirmation Gaps: Gift subscriptions and BYOB submissions do not trigger recipient notification emails.
2. Re-Evaluation of DRY_OPTIMIZATION_RECOMMENDATIONS.md
2.1 Liquid Templates & Layouts
- 2.1 Category Pages Layout Consolidation
- Status: COMPLETE (Commit
85e52a4) - Details: All category pages delegate to
_layouts/category.htmland_includes/category-section.html.
- Status: COMPLETE (Commit
- 2.2 Status-Partitioned Roast Sorting & Collection Engine
- Status: COMPLETE (Commit
85e52a4) - Details: 3-tier partitioning (
active$\rightarrow$incubating$\rightarrow$flown_south) and collection resolution unified in_includes/category-section.html.
- Status: COMPLETE (Commit
- 2.3 Roast Level & Dots Component
- Status: COMPLETE (Commit
0da4f5d& prior) - Details: Centralized in
_includes/roast-dots.html.
- Status: COMPLETE (Commit
- 2.4 Grind Selector Dropdown
- Status: COMPLETE (Commit
b7dc0f1) - Details: Centralized in
_data/grind_levels.ymland_includes/grind-options.html.
- Status: COMPLETE (Commit
- 2.5 Minimal-Vertical Page Hero Layout
- Status: COMPLETE
- Details: Created
_layouts/detail-page.html(inheriting fromdefault.html) that standardizes the.roast-minimal-verticalhero header (divider,mascot_file,title/card_title,subtitle,intro,divider) driven strictly by frontmatter. Migrated_layouts/subscription.html,_flights/the-aviary.md,_flights/peck-your-own.md,_custom/bring-your-own-beans.md,_custom/bring-your-own-burner.md, and_custom/build-your-own-blend.md, eliminating over 110 lines of repetitive boilerplate markup.
- 2.6 Mascot Asset Standardization (Retired Lazy Susan Component)
- Status: COMPLETE (Commit
85e52a4) - Details: Replaced with
peck-your-own-transparent.png. Deleted_includes/lazy-susan.htmland cleaned SCSS.
- Status: COMPLETE (Commit
- 2.7 Checkout & Intake Form Snippets
- Status: KEPT SEPARATE (DECIDED)
- Details: Per user decision, form markup across order checkout and custom roaster intake forms will remain separate and localized to avoid tight coupling and maintain self-contained templates.
2.2 CSS & SASS Consolidations
- 3.1 Eliminating Remaining 222 Inline Styles
- Status: IN PROGRESS (Reduced from 791 to 222)
- Remaining Hotspots:
preview-pricing.html: 32 occurrences_custom/bring-your-own-burner.md: 26 occurrences_custom/build-your-own-blend.md: 25 occurrencesgift.markdown: 23 occurrences_layouts/roast.html: 13 occurrences
- Action: Move inline form container styles (
max-width,margin,display:none) into semantic classes (.u-hidden,.order-form,.price-bar).
- 3.2 Form Label Alignment Conflict
- Status: NOT STARTED
- Problem:
.roast-mv-meta-labelin_sass/_roast-detail.scsssetstext-align: center, forcing labels on checkout and intake forms to override withstyle="text-align: left;"ordisplay: block. - Action: Set default form labels to
text-align: leftin_base.scssand use a modifier.roast-mv-meta-label--centerspecifically for detail page centered headers.
- 3.3 Sass Maps for Category Theming
- Status: COMPLETE (Commit
b7dc0f1) - Details: Refactored category backgrounds in
_sass/_cards.scsswith a Sass$category-colorsmap and@eachloop.
- Status: COMPLETE (Commit
- 3.4 Reusable Button / Pill Mixin
- Status: NOT STARTED
- Problem: Repetitive button shapes, display fonts, uppercase tracking, and hover transitions across
.roasts-quiz-cta,.order-submit,.add-to-order-btn,.roasts-entry-quick-add, and.add-to-blend-button. - Action: Define
@mixin pill-button($bg, $color)in_sass/_variables.scssor_sass/_base.scss.
- 3.5 Backdrop Blur Mixin
- Status: NOT STARTED
- Problem: 10 duplicate declarations of
backdrop-filter: blur(3.5px); -webkit-backdrop-filter: blur(3.5px);in_sass/_roast-detail.scss. - Action: Define
@mixin backdrop-blur($radius: 3.5px)and replace declarations.
2.3 Data Centralization (_data/ & _config.yml)
- 4.1
_data/grind_levels.yml- Status: COMPLETE
- 4.2 Standardize Brewing Methods
- Status: COMPLETE (Commit
0da4f5d) - Details: Canonical brewing methods hardcoded into filter select in
roasts/index.markdown, removing dynamic DOM generation and method maps fromcatalog-filters.js.
- Status: COMPLETE (Commit
- 4.3 Google Forms Centralization Cleanup
- Status: COMPLETE
- Details: Migrated
gift.markdownto consumesite.google_forms.digital_gift.urlandsite.google_forms.digital_gift.entries, and deleted redundant root-leveldigital_gift_form_urlanddigital_gift_entrieskeys from_config.yml.
- 4.4 Connect
_data/bag_sizes.ymlAcross Templates & Scripts- Status: COMPLETE
- Details: Created
_includes/bag-size-options.htmldriven by_data/bag_sizes.yml. Integrated into_custom/bring-your-own-burner.md, exposedwindow.YWR_BAG_SIZESinjs/cart-data.js, and cleanedgift.markdownto derive sizes directly fromr.priceands.sizeswithout fabricated size arrays.
2.4 JavaScript Modularization
- 5.1 Shared Cart Storage & Retrieval
- Status: COMPLETE (Commit
03a7cee) - Details: Unified on
window.ywrGetCart()andwindow.ywrAddToCart(). The old duplicateparts = ck.split('|')parsing has been removed.
- Status: COMPLETE (Commit
- 5.2 Unified Google Form Iframe Submissions
- Status: KEPT SEPARATE (DECIDED)
- Details: Per design decision, hidden iframe generation and submission lifecycles are kept intentionally localized within each form script (
order-checkout.js,form-submit.js,byob-mixer.js,gift-order.js) to maintain self-contained modularity and avoid tight cross-script coupling.
2.5 Defensive Coding & Silent Fallback Elimination
- 6.1 Ghost Property Fallbacks (
prices,status_badge,process)- Status: COMPLETE
- 6.2 Redundant Defaults for Local Frontmatter Constants
- Status: COMPLETE (Peck Your Own / Aviary cleaned)
- 6.3 Hidden Data Bugs Masked by Fallbacks (Mascots)
- Status: COMPLETE (Fixed
double-crested-cormorant)
- Status: COMPLETE (Fixed
- 6.4 Schema.org JSON-LD 5-Level Fallback Ladder
- Status: COMPLETE
- Details: Replaced the 5-level fallback ladder with direct lookups
roast_prices[first_size]androast_prices[last_size], and dynamicofferCount: sizes.size.
- 6.5 Hardcoded JavaScript Duplicate Maps (
dotsMap)- Status: COMPLETE
- Details: Removed hardcoded
levelDotsMapanddotNumberToLeveldictionaries and|| 2fallback fromjs/byob-burner.js. Roast levels and dot counts are now derived directly fromwindow.YWR_ROAST_LEVELSand<option data-dots>.
- 6.6 Visual Type Aliasing Elimination
- Status: COMPLETE (Commit
85e52a4)
- Status: COMPLETE (Commit
- 6.7 Subscription Frequency Fallback Elimination
- Status: COMPLETE
- Details: Eliminated
default_freqsandsub_config.frequencies | default: default_freqsin_layouts/roast.html. Removed phantom variabledefaultFreqfromroast-detail.js. Replaced hardcoded fallback strings ('12oz','Every 2 weeks','Whole Bean') inorder-checkout.jswith direct catalog values (entry.sizes[0],entry.frequencies[0], andwindow.YWR_DEFAULT_GRINDcompiled from_data/grind_levels.yml).
- 6.8 Expose
window.YWR_FLIGHTS_DATA- Status: COMPLETE
- Details: Added
window.YWR_FLIGHTS_DATAtojs/cart-data.jsand updatedjs/flights.jsto read price, price per bag, min bags, and mascots directly from configuration without fallback numbers.
- 6.9 Fast-Fail Runtime Exceptions & Silent Return Elimination
- Status: COMPLETE
- Details: Eliminated silent
if (!element) return;aborts inorder-checkout.js,flights.js,byob-burner.js,gift-order.js, andmanage-subscriptions.js. Added explicitconsole.errorandconsole.warnto empty catch blocks inmanage-subscriptions.jsandorder-checkout.js. Allowed missing DOM dependencies to throw naturalTypeErrorso failures surface immediately in browser DevTools.
- 6.10 Hardcoded Flight Mascot Bug in
js/flights.js- Status: COMPLETE
- Details: Fixed
js/flights.jsto receivemascotfrom frontmatter viainitPYOFlight/YWR_FLIGHTS_DATA, usingpeck-your-own-transparent.pnginstead of the outdated cardinal image.
2.6 Repository Hygiene
- 7.1 Relocate Standalone Preview Files to
_previews/- Status: NOT STARTED
- Files in root:
coming-soon-preview.htmlfooter-icon-preview.htmlmain-icon-preview.htmlpreview-bags.htmlpreview-bags-v2.htmlpreview-pricing.htmlroast-card-color-playground.htmlroast-detail-preview.htmlsocial-preview-generator.html
- Action: Move into
_previews/and update_config.ymlexclude paths.
3. Re-Evaluation Against Coding Principles (AGENTS.md, coding-principles.md, SKILL.md)
Principle 1: Config-Driven Over Hardcoded (Fail Rather Than Guess)
“I’d rather a failure than a default value that doesn’t make sense.”
| File | Line(s) | Violation | Status / Remediation |
|---|---|---|---|
gift.markdown |
415 | default_sub_sizes = "12oz,1lb,2lb,5lb" fabricated string array |
RESOLVED: Sizes derived dynamically from r.price and s.sizes |
_custom/bring-your-own-burner.md |
84–88 | Static <option> tags for 12oz, 1lb, 2lb, 5lb |
RESOLVED: Rendered via _includes/bag-size-options.html driven by _data/bag_sizes.yml |
js/flights.js |
28, 72, 73 | options.price \|\| 38, options.pricePerBag \|\| 10, minBags \|\| 4 |
RESOLVED: Direct reads from frontmatter options without fallback numbers |
js/flights.js |
140 | Hardcoded mascot audubon-cardinal-transparent.png |
RESOLVED: Reads mascot from flight frontmatter |
js/order-checkout.js |
65–66 | params.get('size') \|\| '12oz', params.get('grind') \|\| 'Whole Bean' |
RESOLVED: Reads from catalog entry sizes and window.YWR_DEFAULT_GRIND |
js/roast-detail.js |
21 | var defaultFreq = config.defaultFreq \|\| 'Monthly'; |
RESOLVED: Deleted dead phantom variable and unused parameter |
Principle 2: Simple & Direct Lookups (No Defensive Guessing, No Phantom Variables)
| File | Line(s) | Violation | Status / Remediation |
|---|---|---|---|
gift.markdown |
421 | r_sub.price \| default: r.price |
RESOLVED: Standard roasts only declare price:; reads r.price directly |
gift.markdown |
173–200 | roast.descriptor \| default: roast.subtitle \| default: 'Blend' |
RESOLVED: Direct roast.descriptor read |
_layouts/roast.html |
250 | sub_config.price \| default: roast_prices |
RESOLVED: Reads roast_prices directly |
_layouts/roast.html |
275 | 5-level fallback ladder for highPrice in Schema.org |
RESOLVED: Reads roast_prices[sizes.last] directly |
js/cart-data.js |
63 | site.data.roast_levels[lvl_num] \| default: site.data.roast_levels[lvl_num_str] |
RESOLVED: Direct integer lookup in roast_levels.yml |
Principle 3: Natural Runtime Exceptions (No Manual Guard Boilerplate)
| File | Line(s) | Violation | Status / Remediation |
|---|---|---|---|
js/order-checkout.js |
29 | if (!form \|\| !emptyEl \|\| !itemsEl) return; |
RESOLVED: Removed silent guard; let form.addEventListener throw if missing |
js/flights.js |
79 | if (!addBtn \|\| !countEl) return; |
RESOLVED: Removed silent return; let DOM operations throw TypeError |
js/byob-burner.js |
34 | if (!originSelect) return; |
RESOLVED: Removed silent return |
js/gift-order.js |
183 | if (!customMenu \|\| !customTrigger) return; |
RESOLVED: Removed silent return and defensive ternaries |
js/manage-subscriptions.js |
59 | if (!lookupForm \|\| ... \|\| !resultsSection) return; |
RESOLVED: Removed silent return |
js/manage-subscriptions.js |
44 | Silent catch (e) {} |
RESOLVED: Added console.error('saveMockDb: Failed to save mock subscriptions:', e) |
js/order-checkout.js |
638–639 | Silent catch (e) {} around storage removal |
RESOLVED: Added console.warn if storage removal throws |
Principle 4: Ask Rather Than Fall Back on Missing Data
- Rule: If a field is missing in YAML frontmatter or configs, ask the user or supply the underlying data instead of writing fallback ternaries in templates.
- Recent Example: When
_custom/and_flights/were missingcategory, rather than retaininginclude.category | default: r.category, we addedcategory: customandcategory: flightto the frontmatter files, enabling directr.categorylookups.
4. Email Automation & Operational Gaps (from TODO.txt)
- 4.1 Gift Subscriptions Recipient Notification Email
- Status: COMPLETE
- Details: Implemented Option B dual-submission architecture. Created dedicated Google Form for Gift Subscriptions (
site.google_forms.gift_subscription) with Apps Script trigger inscripts/google-forms/gift-subscriptions/that dispatchespurchaser-confirmation.html(receipt with price to buyer) andrecipient-announcement.html(gift announcement without price to recipient). Updatedjs/gift-order.jsto dual-post to the gift form while submitting recipient delivery details tosite.google_forms.subscription. Both emails are sent intentionally to the recipient; added a direct link to the Subscription Management page insubscription.html, added?email=auto-lookup injs/manage-subscriptions.js, and resolveddoGetfunction name collision acrossCode.gsandManagement.gs.
- 4.2 BYOB (Build Your Own Blend) Customer Confirmation Email
- Problem: BYOB submissions to
site.google_forms.byob_blend.urlare stored in Google Sheets, but there is no Google Apps Script trigger script inscripts/google-forms/to email a recipe confirmation to the customer. - Action: Create
scripts/google-forms/byob/Code.gsandbyob-confirmation-template.htmlto send a branded blend recipe summary toe.namedValues['Email'][0].
- Problem: BYOB submissions to
5. Master Prioritized Implementation Checklist
Phase 1: Critical Architectural & Coding Principle Fixes (Immediate)
- Wire up
_data/bag_sizes.ymltogift.markdownand_custom/bring-your-own-burner.md. - Fix hardcoded mascot
audubon-cardinal-transparent.pnginjs/flights.jsto usepeck-your-own-transparent.png. - Expose
window.YWR_FLIGHTS_DATAinjs/cart-data.jsand remove fallback numbers (38,10,4) fromjs/flights.js. - Remove 5-level Schema.org price ladder in
_layouts/roast.html. - Remove
default_freqsandsub_prices = sub_config.price | default: roast_pricesfallback in_layouts/roast.html. - Clean up
gift.markdownGoogle Form config to usesite.google_forms.digital_giftand delete duplicate lines 10–19 from_config.yml.
Phase 2: JavaScript Hardening & Fast-Fail (Short-Term)
- Replace silent
if (!el) return;aborts inorder-checkout.js,flights.js,byob-burner.js,gift-order.js, andmanage-subscriptions.jswith natural DOM reads and explicit error logging. - Iframe submission lifecycles kept intentionally localized within each script (Kept separate per design decision).
- Replace
levelDotsMapanddotNumberToLevelinjs/byob-burner.jswithwindow.YWR_ROAST_LEVELS.
Phase 3: Layouts & Template DRYing (Medium-Term)
- Create
_layouts/detail-page.htmlto eliminate 7 duplicate.roast-minimal-verticalhero blocks. - Form templates kept separate and localized across checkout & custom roasters (Kept separate per user decision).
Phase 4: CSS Consolidation & Repository Hygiene (Polishing)
- Move inline styles from
bring-your-own-burner.md,build-your-own-blend.md, andgift.markdownto SCSS classes. - Add
@mixin pill-buttonand@mixin backdrop-blurto_sass/. - Move standalone preview HTML files into
_previews/and update_config.ymlexclusion list.
Phase 5: Operational & Email Automation (Features)
- Implement recipient notification in
scripts/google-forms/subscriptions/Code.gs. - Implement BYOB recipe confirmation in
scripts/google-forms/byob/Code.gs.