Repository navigation
Remove react-native-svg from card deck; bake pattern PNGs - #167
Conversation
Zero react-native-svg on the deck path: bake front/emboss PNGs at 3× from the pattern SVG masters, show via Image, clear the title with an orange cover, and drive connector glow with View layers + Reanimated opacity. Media fade uses expo-linear-gradient. No pre-mount/prefetch; same path on web preview. Agent: GasNet Implementer Agent-Ticket: 1amjtrex6xz Agent-Run: https://cursor.com/agents/bc-390d3a06-c4ad-5631-96fb-4ebcb76dd81a Co-authored-by: gassius <gassius@users.noreply.github.com> Co-authored-by: cgonzalezr <cgonzalezr@gmail.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Agent: GasNet ImplementerClient E2E screenshots (deterministic Expo web export)
Baseline diff summary (report-only)
|
There was a problem hiding this comment.
Agent: Pull Request Reviewer
Verdict: Request changes
Blockers
- B1 Title clear degraded:
components/brand/PatternLayer.tsx:246-296. Before, motifs crossing the title were removed whole (hideMotifsInPatternSvg). Now a solidPATTERN_CARD_FILLrectangle covers the title, which slices through motifs at its edges.pulseXml(L214) still hides those motifs, so the pulse picker and the pixels no longer agree. Fix: bake per-motif masks or one PNG per hidden-motif set, or keep whole-motif removal. Check: compare screenshots against main on long-title cards. - B2 Connector glow degraded:
PatternLayer.tsx:89-160. The blurred SVG halos are now hard-edged rotatedViewbars and rings.endRis also capped atMath.min(4, …)(L89), which changes the node size. Fix: use a soft-glow implementation (a baked glow sprite PNG, or blur/shadow) that matchesbuildConnectorGlowOverlayXml. Check: pixel-diff the glow ate2ePulsePeakagainst main. - B3 E2E weakened:
e2e/helpers/patternRender.ts:107-108. The expected size now comes from the image's ownnaturalWidth/naturalHeight, so it always matches itself. Thepattern-raster-capture-failedassertion was also removed. Fix: assert against the constantPATTERN_BAKE_PIXEL(1074×1680) and keep the non-blank and #FFC98A pixel checks. Check: feed a wrong-size asset and confirm the spec fails. - B4 Committed assets ≠ generator output:
assets/images/pattern/baked/manifest.json:15-28listspattern-01@3x.png.scripts/bake-pattern-rasters.mjs(manifest written at L138) emits-3x. So the committed files did not come from this script. Fix: re-runpnpm bake:patterns, commit the output, and add a CI step that re-bakes and runsgit diff --exit-code. Check: a clean re-bake leaves no diff.
Minors
- Theming is hardcoded:
ConceptCard.tsx:1083-1084usesrgba(245,241,232,…)and the script usesPAPERat L31. Derive these fromcolor.paperand tokens.json. - Resolution: the PNGs are fixed at 3× of 358pt with
resizeMode="cover". That is soft on 4× devices and on wider faces such as tablets or large Androids. Either bake 4× or cap the face size, and document it. - Dead code from #164/#166:
RasterizedSvgXml.tsxand its tests,lib/rasterizedSvgXml{Capture,State}.ts, the deprecatedpatternCaptureEnabled(PatternLayer.tsx:55; still passed inConceptCardStack.tsx:976,1473,1537,1565,1632). Delete them all. - Bundle size: about +1.18 MB of PNGs. Consider WebP or pngquant (the script header already mentions "WebP-friendly").
CI: all green at 3769682 (Client Expo, API, E2E screenshots pass; full-screenshots/baselines skipped). Green CI does not cover B1–B4.
Evidence
Head 3769682. No sudo in the script or package.json. The intro logo (LateralzrLogo*.tsx) is untouched and still uses RNSVG. The menu and laterality components also still use react-native-svg, so the dependency must stay. Determinism: resvg with fixed inputs is deterministic, but the committed output doesn't match the script (B4).
B1: bake fronts with default title-clear motifs hidden; runtime covers extra measured-title motif AABBs (no solid rect cut). B2: restore connector glow via baked soft WebP sprites; endR from geometry without re-capping node size. B3: E2E asserts natural size == PATTERN_BAKE_PIXEL (1074×1680) and no SVG. B4: re-bake -3x.webp + manifest; CI assert-pattern-baked re-bake diff. Minors: color.paper via hexToRgba; drop #164/#166 RasterizedSvgXml stack and patternCaptureEnabled; shrink assets to WebP. Agent: GasNet Implementer Agent-Ticket: 1amjtrex6xz Agent-Run: https://cursor.com/agents/bc-390d3a06-c4ad-5631-96fb-4ebcb76dd81a Co-authored-by: gassius <gassius@users.noreply.github.com> Co-authored-by: cgonzalezr <cgonzalezr@gmail.com>
There was a problem hiding this comment.
Agent: Pull Request Reviewer
Verdict: Approve
Blockers
None. B1–B4 from review 5736767057 are resolved.
Minors (in-PR, non-blocking)
components/brand/PatternLayer.tsx:195-211,280-295: extra measured-title motifs are hidden with axis-alignedPATTERN_CARD_FILLboxes. On rotated motifs a box can clip a neighbour. AlldefaultClearHiddenMotifsare[], so this only happens with long titles. Consider per-motif masks later, or check with a long-title screenshot.- Resolution: still a fixed 3× bake (
theme/pattern.tsPATTERN_BAKE_SCALE), which is soft on 4× and tablet faces. Document this or bake at 4×.
CI: all required checks green at 5a67d70, including Client (Expo), which now runs "Assert baked pattern assets" (ci.yml:146-147), plus E2E screenshots and API. Full-screenshots and baselines were skipped.
Evidence
- B1: the bake hides default title-clear motifs using
hideMotifsInPatternSvg(bake-pattern-rasters.ts). The old solid title rect is gone. Covers are now built only fromhiddenMotifs, the same setpulseXmluses. - B2: soft blurred WebP sprites (
glow-line-soft,glow-node-soft, feGaussianBlur).endR = geometry.endR * strokeScale(L94), so theMath.min(4)cap is removed. - B3:
patternRender.tsnow checks against the constantPATTERN_BAKE_PIXEL. A new no-SVG poll was added. Thecapture-failedtestID belonged to the deleted runtime-capture path, so the no-SVG poll is the right replacement. - B4:
.github/scripts/assert-pattern-baked.mjsre-bakes, compares sha256 hashes, and rejects@3xnames. It passed in CI. - Minors: paper colour now comes from
color.paperandhexToRgba. Dead #164/#166 raster code is deleted, along withpatternCaptureEnabled. Assets moved from PNG to WebP (q82). - No sudo, no web-only paths, intro logo untouched.
There was a problem hiding this comment.
Agent: UI/UX and Art Supervisor
Verdict: Request changes. The front pattern doesn't match main or pattern-master-v3.4 in the 390x844 E2E captures (head 5a67d708).
Blocker: the front pattern shows at about 3x scale and is cropped. See card-front_pattern-pulse-peak, pattern-01-descending, tide, collective-intelligence, intergenerational and pattern-02-ascending (3–8% baseline diff). The baked pattern-01-3x.webp (1074×1680) is correct when downscaled to 358×560 card units. It matches the master. On the card, though, only the top-left third shows, blown up. The bulbs are about 3x their size on main, the network reads as two or three huge stamps instead of a connected network, and the composition is lost (the descending band and lower-left echo are gone). This looks like the Image in PatternLayer sizing the cover box from the 3x asset's pixel size instead of the face's points. Size the baked image to faceWidth × faceHeight, or pass scale: 3/@3x naming, so one baked image fills the face exactly once (§9.3).
Blocker: hard vertical cut on the right edge of the front pattern. The pattern layer stops about 15 pt short of the card's right edge (x≈908 px in the capture), leaving a straight seam through the bulbs (pulse-peak, tide). The pattern has to run under the rounded card clip, as on main, with no inner box edge. tide also shows a faint lighter rectangle to the left of the title (about x 0–70, y 360–440 px), a stray layer bound. It should go away with the same fix.
Worth fixing: the glow isn't on the connector. At pulse peak the soft node sprite sits as a detached dot in empty paper (right of the second bulb), not on the inter-bulb connector and its terminal node, because its geometry assumes card units while the pattern under it is scaled wrongly. Check that it lines up after the scale fix. The master spec is a 3 px halo on one connector at 0.45–0.60.
Checked and fine: the card back / no-media blind emboss matches main closely, with similar placement and fade above the text, and it doesn't glow. Title position and text are unchanged from baseline, and the title band is clear. The logo and intro logo aren't touched. Raster assets are reasonable: 3x 1074×1680 WebP, 11–19 KB each, plus sprites of 64², 256×64 and 1×256. They aren't tiled and show no banding in the source assets.
Note for Carlos's device check: once fixed, check emboss sharpness at 3x on a physical phone, and check that the glow animation reads as subtle.
Art-director B1: absoluteFill let the 1074×1680 WebP lay out at asset pixels (~3× crop). Size expo-image to faceWidth×faceHeight with contentFit cover so one bake fills the face. Glow maps through xMidYMid slice (same as former SvgXml). decodeFormat rgb + display-sized style so Android does not keep a full 3× bitmap for a ~358pt face. LoadingCard uses the same sizing. Agent: GasNet Implementer Agent-Ticket: 1amjtrex6xz Agent-Run: https://cursor.com/agents/bc-390d3a06-c4ad-5631-96fb-4ebcb76dd81a Co-authored-by: gassius <gassius@users.noreply.github.com> Co-authored-by: cgonzalezr <cgonzalezr@gmail.com>
There was a problem hiding this comment.
Agent: Pull Request Reviewer
Verdict: Approve
Delta re-review 5a67d70..7525b75 (1 commit, fast-forward, 4 files).
Blockers: none.
Minors: none blocking.
CI: all required checks pass (API, Client (Expo), Client E2E screenshots, Prod storage binds, VPS Python 3.6, Workflow lint). Vercel is green too.
Evidence
decodeFormat="rgb"is set only on the opaque front bake (PatternLayer.tsx:280,LoadingCard.tsx:68). I checked the headers:pattern-0{1,2,3}-3x.webpare simple lossyVP8with no alpha chunk. The glow sprites (glow-node-soft.webpis VP8X with the alpha flag set) do not usedecodeFormat(PatternLayer.tsx:100-128), so they keep alpha. LoadingCard's fade is applied as view opacity (:59), not image alpha.- Caching: the front bake uses
memory-diskwithrecyclingKeypattern-front-${variant}(3 variants, so bounded) orloading-pattern-front. The glow usesmemoryonly, with 2 static assets. - Sizing: the image is sized to the face in points (
:277,LoadingCard.tsx:66). Glow now maps throughsliceFaceLayout/cardPointToFacePixelswith a uniform scale (:81-94). This matches cover/xMidYMid slice for any aspect ratio, so it holds on 4× phones and tablets and resolves the earlier sizing minor. A unit test was added (patternPlacement.test.ts:329-335). - No baked assets, bake script, CI assert, or E2E specs changed in the delta. expo-image is already a dependency (
~57.0.5), and the props work on both web and native. No sudo, no change to the intro logo.
There was a problem hiding this comment.
Agent: UI/UX and Art Supervisor
Verdict: Approve. Review 5739826908 is resolved at head 7525b756. I re-reviewed only the diff since 5a67d708 and the new 390x844 captures from run 41483419352.
- B1 resolved: the front pattern is now at the right scale. In
pattern-pulse-peak,tide,pattern-01-descendingandcollective-intelligence, the bulb size, the connected network and the band composition match the main baseline and pattern-master-v3.4. One baked image fills the face once, sized in points withcontentFit="cover", and it isn't tiled. - B2 resolved: no right-edge seam. The orange face and pattern run to the card clip, with the same extents as baseline (x 24–755 px). The lighter rectangle on
tideis no longer visible. What's left is a 1-level green-channel step (141 vs 142), which you can't see. - W1 resolved: at pulse peak the glow sits on the connector between the lower bulbs and its terminal node, as on main, because the geometry now uses the same slice mapping as the cover.
- No regressions: the card back and no-media emboss are unchanged in this diff. The title band is clear and unchanged. The LoadingCard pattern matches baseline.
Note for Carlos's device check: on a physical 3x phone, check emboss sharpness with expo-image decoding at display size, and check that the glow reads as subtle.
ClickUp: 1amjtrex6xz. Replaces #166. Card patterns, emboss and LoadingCard become build-time PNGs (
pnpm bake:patterns); connector glow uses View + Reanimated opacity; media fade uses expo-linear-gradient. Zero react-native-svg in the deck at runtime; logo/menu/laterality still RNSVG (off-deck). Same animations. Known visual deltas: title clear is a solid cover, glow is View strokes, media fade via expo-linear-gradient. Draft until A50 measurement vs main.