Skip to content

feat: draft framework-CSS landing page for review - #504

Closed
jackgranatowski wants to merge 1 commit into
mainfrom
claude/landing-page-redesign
Closed

feat: draft framework-CSS landing page for review#504
jackgranatowski wants to merge 1 commit into
mainfrom
claude/landing-page-redesign

Conversation

@jackgranatowski

Copy link
Copy Markdown
Contributor

Summary

  • Parks a redesigned GitHub Pages homepage in copy-wip/github-pages-index.html for review before promotion to index.md at repo root.
  • The page is styled entirely by slashed.optimal.css, loaded from the jsDelivr dist CDN — the same URL the page's own install instructions tell visitors to use. Layout uses sf-section/sf-container/sf-stack/sf-cluster/sf-bento; macros include sf-prose, sf-surface, sf-text-gradient, sf-divider; scroll-driven sf-entrance animations on feature cards. All page-specific CSS lives in the reserved slashed.overrides layer and composes framework tokens exclusively — no raw colors, sizes, or fonts.
  • Hero wordmark unfolds S/L/A/S/H/E/D into its manifesto word on hover. The interaction is geometry-stable: each word expands to a measured width and the row counter-shifts by exactly half that width, so the hovered letter never drifts onto a neighbor mid-animation. Gated to (any-hover: hover), respects prefers-reduced-motion, has a 120ms sweep-guard delay.
  • Feature grid demos are live framework tokens, not screenshots — the actual --sf-color-primary 50→950 ramp, side-by-side data-theme panels, the real fluid type scale.
  • Install section is a data-theme="dark" band on an otherwise light page, demonstrating section-scoped theming as a live example. Its code blocks pin to theme-safe tokens and wrap instead of horizontally scrolling (a related framework bug where code-token colors don't follow scoped data-theme is filed as Code-block color tokens don't follow section-scoped data-theme #496).
  • copy-wip/ is excluded from the Jekyll build (_config.yml) so the draft isn't published while under review.

Context

Split out of #492, which began as a README/index copy fix and grew into this full redesign plus several review rounds of bugfixes (localStorage guard, hover-drift fix, mobile band hardening, CDN load switch). See #[readme PR] for the README-only half.

Test plan

  • Verified with Playwright: light mode, dark mode, 390px mobile (Pixel 7 emulation), zero console errors
  • Verified the hero hover interaction mechanically — hovering each of the 7 letters and waiting out the full unfold animation confirms the cursor stays on the same letter throughout, for all 7
  • Verified the page requests the exact jsDelivr CDN URL and renders correctly against the real minified bundle
  • Review the copy/design direction
  • On approval, promote to index.md at repo root and delete copy-wip/github-pages-index.html

🤖 Generated with Claude Code


Generated by Claude Code

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@jackgranatowski, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 39 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f2f91578-a270-499a-b9dc-1153bbd0238b

📥 Commits

Reviewing files that changed from the base of the PR and between 2ca0872 and 87e3e0a.

📒 Files selected for processing (1)
  • copy-wip/github-pages-index.html
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/landing-page-redesign

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Draft GitHub Pages landing page styled by SLASHED CDN bundle (kept out of build)

✨ Enhancement 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Add a draft GitHub Pages homepage under copy-wip/ for design/copy review.
• Style the page exclusively with slashed.optimal.min.css from the jsDelivr dist CDN.
• Exclude copy-wip/ from Jekyll output so the draft is not published yet.
Diagram

graph TD
  cfg["_config.yml"] --> jekyll(["Jekyll build"]) --> gh(("GitHub Pages"))
  index["index.md (existing)"] --> jekyll
  draft["copy-wip/github-pages-index.html"] --> exclude{"Excluded from build"}
  cfg --> exclude

  subgraph Legend
    direction LR
    _file["File"] ~~~ _proc(["Build step"]) ~~~ _out(("Published site")) ~~~ _dec{"Build rule"}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Use Jekyll front matter to disable publishing (e.g., `published: false`)
  • ➕ Keeps the draft in the normal site structure without changing global excludes
  • ➕ Easier to preview locally using the same build paths
  • ➖ Depends on Jekyll behavior and conventions; easier to accidentally publish if misconfigured
  • ➖ May still require additional routing/permalink handling to avoid collisions
2. Host a PR preview build (Netlify/Vercel/GitHub Actions artifact) instead of committing `copy-wip/`
  • ➕ Reviewers see the page exactly as deployed, without affecting repo build configuration
  • ➕ Avoids carrying a temporary directory in the main repo
  • ➖ Adds CI/hosting setup and maintenance overhead
  • ➖ Preview environments can diverge from GitHub Pages/Jekyll behavior if not carefully matched

Recommendation: The current approach (parking the draft under copy-wip/ and excluding it from Jekyll) is a safe, low-risk way to iterate on design/copy without accidentally publishing. If the team expects to keep drafts around long-term, consider published: false or a dedicated preview pipeline; otherwise, this is a pragmatic review staging method.

Files changed (2) +601 / -0

Documentation (1) +600 / -0
github-pages-index.htmlAdd draft SLASHED landing page using CDN-hosted framework CSS +600/-0

Add draft SLASHED landing page using CDN-hosted framework CSS

• Introduces a full draft homepage (layout, token-driven styling, and small theme-toggle JS). The page loads 'slashed.optimal.min.css' from jsDelivr and contains page-specific CSS in the 'slashed.overrides' layer, plus interactive hero hover behavior and section-scoped theming examples.

copy-wip/github-pages-index.html

Other (1) +1 / -0
_config.ymlExclude 'copy-wip/' from the Jekyll build +1/-0

Exclude 'copy-wip/' from the Jekyll build

• Adds 'copy-wip' to the Jekyll 'exclude' list so the new draft landing page is not published on GitHub Pages during review.

_config.yml

@qodo-code-review

qodo-code-review Bot commented Jul 3, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 11 rules

Grey Divider


Remediation recommended

1. Unvalidated theme state ✓ Resolved 🐞 Bug ☼ Reliability
Description
The theme-toggle script reads slashed-home-theme from localStorage and applies it directly to
<html data-theme>, so any unexpected stored value prevents the framework’s theme selectors from
matching and can leave the page in an unintended/default theme state with a misleading button label.
This is persistent for returning visitors until they click the toggle (which only then normalizes to
a known state).
Code

copy-wip/github-pages-index.html[R582-591]

+      var btn = document.getElementById('theme-toggle');
+      var states = ['auto', 'dark', 'light'];
+      var current = 'auto';
+      try { current = localStorage.getItem('slashed-home-theme') || 'auto'; } catch (e) {}
+      function apply(state) {
+        if (state === 'auto') document.documentElement.removeAttribute('data-theme');
+        else document.documentElement.setAttribute('data-theme', state);
+        btn.textContent = state[0].toUpperCase() + state.slice(1);
+      }
+      apply(current);
Relevance

⭐⭐⭐ High

Team has accepted validating/normalizing localStorage-derived state to prevent persistent bad values
breaking UI.

PR-#460
PR-#313
PR-#428

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The script applies whatever localStorage returns as data-theme without checking allowed values,
while the framework only recognizes absence of data-theme (auto) and the exact values
light/dark for setting color-scheme and --sf-is-dark. Any other value won’t match those
selectors, so the intended theme activation logic won’t run.

copy-wip/github-pages-index.html[582-596]
core/themes.css[8-17]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The theme toggle persists a value in `localStorage` and re-applies it on load, but it never validates that the stored value is one of the supported states. If the stored value is anything other than `auto|dark|light`, the script sets `data-theme` to an unsupported value.

Because the framework only defines theme behavior for `:root:not([data-theme])` (auto) and `[data-theme="light"|"dark"]`, an unsupported value prevents the intended selectors from applying.

### Issue Context
- This is a user-visible and persistent issue: a stale/invalid localStorage entry can leave the document in an unintended theme state and the toggle UI will display that invalid value.

### Fix Focus Areas
- copy-wip/github-pages-index.html[582-596]

### Suggested fix
- After reading from `localStorage`, normalize:
 - If the value is not in `states`, set it to `'auto'`.
 - In `apply()`, only set `data-theme` for `'dark'`/`'light'`; otherwise remove the attribute.
- (Optional hardening) Bail out early if `btn` is missing to avoid runtime errors if markup changes.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

2. Mutable external CSS dependency 🐞 Bug ☼ Reliability
Description
The draft landing page loads its stylesheet from a jsDelivr URL pinned to the moving dist branch,
so rendering can change or fail independently of the repo revision being reviewed. This is
non-deterministic compared to the repo’s Pages build, which injects locally built bundles into the
site output.
Code

copy-wip/github-pages-index.html[R13-16]

+  <!-- The page is styled by the framework it advertises — served from the
+       jsDelivr CDN off the dist branch (updated on every release). -->
+  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/codeslash-dev/SLASHED@dist/slashed.optimal.min.css">
+
Relevance

⭐ Low

Team previously rejected pinning jsDelivr @dist to immutable refs; they tolerate mutable dist CDN
usage.

PR-#253
PR-#66
PR-#64

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The added HTML explicitly references the @dist CDN URL, while the Pages workflow builds and
injects local badges/*.css outputs and the default layout uses the local
/badges/slashed.optimal.css path. That demonstrates the new draft is dependent on an external,
mutable source unlike the rest of the site.

copy-wip/github-pages-index.html[13-16]
.github/workflows/deploy-configurator.yml[67-94]
_layouts/default.html[6-8]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The draft page styles itself via `https://cdn.jsdelivr.net/...@dist/...`, which is a moving target. That makes review and reproduction non-deterministic (the same commit can render differently later) and introduces an external availability dependency.

### Issue Context
The repo’s Pages pipeline builds bundles into `badges/` and injects them into `_site`, and the default layout references the local `/badges/slashed.optimal.css`.

### Fix Focus Areas
- copy-wip/github-pages-index.html[13-16]

### Suggested fix options
- Prefer deterministic styling for the draft by referencing the locally built Pages asset (`/badges/slashed.optimal.css`) when running in the repo/site context.
- Or, if you want to dogfood the CDN URL, pin to a specific release tag (e.g. `@vX.Y.Z`) for reproducible review snapshots, while still showing the `@dist` install snippet in the code examples.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread copy-wip/github-pages-index.html

Copy link
Copy Markdown
Contributor Author

Re: #2 Mutable external CSS dependency (from the code review comment) — declining this one, keeping the CDN link as-is.

This was an explicit, deliberate choice, not an oversight: the page's own install instructions tell visitors to pull the framework from @dist on jsDelivr, so the page loads its stylesheet the same way to dogfood that exact snippet. Qodo's own cited precedent (PR-#253, PR-#66, PR-#64) confirms the team has already tolerated mutable @dist CDN usage rather than pinning to a release tag.

Pinning to @vX.Y.Z here would make the page's chrome diverge from the code sample right next to it, which is worse for a marketing/landing page whose whole point is "this is what installing SLASHED actually looks like." Since this page is parked in copy-wip/ (excluded from the Jekyll build) and isn't live yet, there's no reproducibility requirement in play either.


Generated by Claude Code

An unexpected stored value (corrupted, or from a future version with
different states) would be applied directly to data-theme, which the
framework's selectors don't recognize, leaving the page in a mismatched
state with a stale button label. Validate against the known states and
fall back to 'auto' otherwise.

Verified with Playwright: seeding localStorage with a garbage value
before load now normalizes to auto (data-theme absent, label "Auto"),
and the toggle still cycles correctly afterward.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019y4H17xqMWoEgvxv3BRM98

Copy link
Copy Markdown
Contributor Author

Closing this out: the only content this PR actually contributed beyond main was the theme-toggle localStorage guard — everything else described here (hero animation, CDN load, token demos, dark install band, Jekyll exclusion) was already merged into main via earlier commits shared by this branch. Split the real diff into #511.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants