content/auto-draft
needs attentionviewing older commit92cce08 · incrementalPR #304reviewed 2026-07-14 02:00 UTC1H · 4M · 3L · 4I- Purpose
- Auto-drafted content branch for the tarifa-gdmth blog post — adds the main MDX article and supporting SVG chart components for Batu's SEO content cluster around GDMTH tariff education.
- Goal
- Publish an SEO-optimized blog post explaining the GDMTH tariff (cómo leer el recibo de CFE, tarifa GDMTH informational cluster) before merge to main.
- Sub-goals
- SG-1: tarifa-gdmth.mdx — full blog post draft (189 lines added)
- SG-2: charts.tsx — SVG chart components (DemandVsConsumptionChart, TouBlocksChart, FpPenaltyChart, SolarBillImpactChart, DemandaFacturableSolarChart)
- SG-3: calendar.yml — add article to content calendar
- SG-4: blog/[slug]/page.tsx — wire up the new MDX slug
- What
- This incremental commit refactors DemandVsConsumptionChart to overlay ToU block background bands (base/intermedia/punta) and mark per-block peak demand explicitly, distinguishing which peak feeds CAPACIDAD vs DISTRIBUCIÓN. Dimensions adjusted (h 360→384, bottom padding 44→74) to accommodate block-name labels below the x-axis.
- Why
- Previous chart showed only the day's absolute peak as a generic 'demanda medida' reference — insufficient for explaining GDMTH's dual demand charges. New version makes the educational split explicit: punta-block peak → capacidad, overall day max → distribución.
- Areas
- apps/web/content/blog+189−0apps/web/src/components/blog+239−20apps/web/src/app/(marketing)/blog+2−2apps/web/content/calendar.yml+1−1
- Blast
- 4 files, +431/−23 lines across apps/web only. No backend, no API, no DB schema. Pure content/chart component work.
Findings · 12
correctness5
Distribución annotation uses intermedia peak, not day's absolute max
apps/web/src/components/blog/charts.tsx
The label 'Dmáx total = X kW → distribución' is placed at `interPk` (peak inside the intermedia block), not at `Math.max(...LOAD_KW)`. For the current LOAD_KW data these are the same value (95 kW at hour 13), but the code doesn't assert or compute the true daily max — it assumes the absolute peak is always in intermedia. If LOAD_KW is ever updated so the daily maximum falls in the punta block, the label would display the intermedia peak (not the true day max) while still claiming 'Dmáx total'. Fix: `const absPk = { kw: Math.max(...LOAD_KW), hour: LOAD_KW.indexOf(Math.max(...LOAD_KW)) }` and use that for the distribución annotation.
interPk annotation text renders very close to SVG top edge
apps/web/src/components/blog/charts.tsx
interPk.kw = 95, maxKw = 115, plotH = 266, pad.top = 44. y(95) ≈ 90.3px. Text baseline at y(95) - 14 ≈ 76px — only ~32px below the SVG top. With a medium-sized font the 'Dmáx total' label may collide visually with the top border of the plot area.
Trailing intermedia band (22–23) covers only one data-index width
apps/web/src/components/blog/charts.tsx
x() maps hour 0–23 with x(23) at the plot right edge. The last intermedia band is {from:22, to:23}, so it covers plotW/23 ≈ 27.8px. The real schedule runs 22:00–24:00 (two hours). TouBlocksChart correctly uses hour/24 scale. Inconsistency is minor for a blog illustration but attentive readers will notice the closing midnight hour isn't shaded.
No label for trailing intermedia band (hours 22–23)
apps/web/src/components/blog/charts.tsx
The 'Intermedia' label at x(12) covers only the main intermedia block. The small cyan band after punta (hours 22–23) is unlabeled, which may confuse readers seeing a second cyan sliver with no identification.
y-axis top is unlabeled (maxKw=115 but gridlines stop at 100)
apps/web/src/components/blog/charts.tsx
Gridlines are drawn at [25,50,75,100] kW. With maxKw=115, the scale ceiling (115 kW) has no gridline or label, leaving the chart's y-axis maximum implicit. Cosmetic only.
domain_accuracy4
TouBlocksChart caption overstates: demanda facturable ≠ only punta block
apps/web/src/components/blog/charts.tsx
TouBlocksChart caption (roughly line 226): 'La demanda facturable de GDMTH se mide en el bloque de punta — por eso reducir consumo en esas horas pega doble.' This is only half-true: cargo por CAPACIDAD uses the punta-block peak, but cargo por DISTRIBUCIÓN uses the absolute monthly maximum (any block). The DemandVsConsumptionChart now correctly distinguishes both charges, making the TouBlocksChart caption contradictory.
Annotation places distribución marker in intermedia band without stating it is block-agnostic
apps/web/src/components/blog/charts.tsx
Placing the 'Dmáx total → distribución' annotation visually inside the intermedia colored band risks readers inferring that distribución is structurally linked to intermedia. The figcaption says '(aquí en intermedia)' but does not explicitly state the charge is block-agnostic. Recommend adding 'independientemente del bloque en que ocurra' or restructuring the annotation to make the distinction clearer.
CAPACIDAD = punta-block peak: correct per GDMTH tariff
apps/web/src/components/blog/charts.tsx
Under CFE's GDMTH tariff, cargo por capacidad applies to the maximum 15-min integrated demand during horas punta in the billing month. The chart correctly depicts puntaPk (62 kW at hour 18) as the CAPACIDAD reference.
Illustrative block schedule is a reasonable GDMTH approximation
apps/web/src/components/blog/charts.tsx
The schedule (base 00-06, intermedia 06-18, punta 18-22, intermedia 22-24) is a plausible weekday GDMTH schedule for the Sistema interconnected region. The DOF disclaimer is present and correct.
security_conventions3
period discriminant and peakOf param should use a union type
apps/web/src/components/blog/charts.tsx
period() returns string; peakOf(p: string) accepts any string. Under TypeScript strict mode, declare `type TouPeriod = 'base' | 'intermedia' | 'punta'` and type both the return of period() and the parameter of peakOf(). No runtime risk today (all callers are hardcoded), but this defeats strict-mode safety.
peakOf kw:-1 sentinel could silently produce out-of-domain y() coordinate
apps/web/src/components/blog/charts.tsx
If period() returns a period with no matching hours, peakOf returns {hour:0, kw:-1}, and y(-1) renders above the chart top. Impossible with current static data but worth guarding against with a null check if peakOf's signature is broadened.
let + mutation in peakOf() — prefer reduce
apps/web/src/components/blog/charts.tsx
peakOf uses let best mutated in forEach. The idiomatic functional form is LOAD_KW.reduce(...) which avoids mutation and aligns with the project's functional-core preference.
History · 14 commits
- c27ea57needs attentionincremental3H · 5M · 4L2026-08-04 17:46
- ff69645needs attentionincremental0H · 6M · 8L2026-07-28 18:21
- 0257d74safeincremental0H · 0M · 0L2026-07-20 23:00
- 0795a9dsafeincremental0H · 0M · 2L2026-07-20 22:42
- 5c57414needs attentionincremental2H · 7M · 10L2026-07-20 22:29
- 5a57a8fneeds attentionincremental0H · 5M · 8L2026-07-20 17:14
- cc9056eneeds attentionfull1H · 3M · 9L2026-07-20 16:40
- 8b79d33needs attentionincremental5H · 7M · 11L2026-07-14 18:10
- f0c337cneeds attentionincremental1H · 1M · 5L2026-07-14 17:15
- 5c9de97needs attentionincremental0H · 5M · 7L2026-07-14 17:02
- 92cce08needs attentionincremental1H · 4M · 3L2026-07-14 02:00current
- b7dd610needs attentionincremental0H · 6M · 7L2026-07-14 01:43
- 8c43554needs attentionfull0H · 2M · 1L2026-07-14 01:15
- 2149391blockedfull8H · 6M · 7L2026-07-10 17:30