Skip to content
This repository was archived by the owner on Mar 26, 2026. It is now read-only.

Rebuild website with Eleventy and interactive hero system#8

Open
JasperNoBoxDev wants to merge 1 commit intomainfrom
feat/eleventy-rebuild
Open

Rebuild website with Eleventy and interactive hero system#8
JasperNoBoxDev wants to merge 1 commit intomainfrom
feat/eleventy-rebuild

Conversation

@JasperNoBoxDev
Copy link
Contributor

@JasperNoBoxDev JasperNoBoxDev commented Feb 22, 2026

Summary

  • Migrated from static HTML/CSS/JS to Eleventy 3.x + Nunjucks templates with shared layouts (base, nav, footer)
  • New hero section with 10 interactive canvas-based variants (Particles, Flow Field, Waves, Constellation, Aurora, Bubbles, Rings, Morph, Grid Warp, Comets) and a live selector panel
  • Design system with CSS tokens, fluid typography (clamp), scroll reveal animations, sticky nav with blur, mobile menu, and pill-shaped CTAs

What changed

  • Removed old static files (index.html, css/, js/)
  • Added Eleventy config, Nunjucks templates for all pages (home, about, contact, privacy, terms)
  • New styles.css with design tokens (coral/purple palette), gradient mesh glows, rotating headline animation
  • New main.js with 10 hero variant renderers, word rotation, scroll reveals, mobile nav, contact form handling
  • All existing content, FormSubmit.co integration, and CNAME preserved

Test plan

  • Run npm install && npm start and verify homepage loads with hero variants
  • Click through all 10 variants in the selector — each should render a distinct animation
  • Test nav: transparent over hero, blurred on scroll, mobile hamburger menu
  • Verify subpages: /about, /contact, /privacy, /terms
  • Test contact form submission
  • Check responsive at 900px and 600px breakpoints
  • Verify CNAME is preserved for GitHub Pages

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Interactive canvas hero with 10 visual effect variants and animated word rotation.
    • Scroll-triggered reveal animations for page elements and content.
    • Improved mobile navigation with enhanced accessibility.
    • Sticky navigation header with intelligent scroll detection.
    • Contact form with visual feedback and success messaging.
    • Dynamic step highlighting in the How We Work section.
  • Documentation

    • Added Privacy Policy and Terms & Conditions pages.

Migrate from static HTML/CSS/JS to Eleventy 3.x with Nunjucks templates,
design tokens, scroll reveals, and 10 interactive hero variants with a
live selector. Preserves all content, contact form, and GitHub Pages setup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Feb 22, 2026

📝 Walkthrough

Walkthrough

Migration from static HTML pages to Eleventy static site generator with Nunjucks templates, introducing reusable layout components (base.njk, nav.njk, footer.njk), converting static pages to templates, and implementing a comprehensive JavaScript framework with 10 interactive canvas-based hero variants plus site-wide enhancements (sticky nav, scroll reveals, form handling). Styling unified into new design system with comprehensive responsive rules.

Changes

Cohort / File(s) Summary
Eleventy Configuration
.eleventy.js, package.json, .gitignore
New project initialization files. Eleventy config exports module with static passthroughs for styles.css, main.js, assets, and CNAME; specifies input/output directories and Nunjucks template engine. package.json defines project metadata and @11ty/eleventy 3.1.2 dependency with build/serve scripts. .gitignore excludes _site/, node_modules/, .DS_Store.
Layout & Component Templates
_includes/base.njk, _includes/nav.njk, _includes/footer.njk
Reusable template partials. base.njk provides full HTML document structure with Open Graph/Twitter metadata, canonical links, and content injection points. nav.njk renders responsive header with logo, navigation links, and hamburger menu. footer.njk includes branding, link columns (Navigation/Legal), and copyright notice.
Page Templates
index.njk, about.njk, contact.njk, privacy.njk, terms.njk
Nunjucks templates replacing static HTML pages. index.njk introduces hero particle system with 10 interactive variants, services/case studies grids, how-we-work steps, contact form. about.njk, contact.njk, privacy.njk, terms.njk provide static structured content with metadata and semantic markup.
Frontend Script
main.js
Comprehensive 872-line DOMContentLoaded orchestrator implementing sticky navigation, mobile menu toggle with backdrop/Escape handling, active nav link marking, IntersectionObserver-based scroll reveals, step highlighting, contact form submission feedback, and a canvas-based 10-variant hero system (particles, flow field, waves, constellation, aurora, bubbles, rings, morphing blob, grid distortion, comets) with word rotation and reduced-motion detection.
Stylesheet
styles.css
New 1461-line design system establishing design tokens (colors, typography, radii, shadows, transitions), font faces (Aeonik, Arbeit), CSS reset, global typography, layout utilities, component styles (navigation with scrolled state, buttons, hero animations, sections, forms), reveal/stagger animations, responsive grid, and breakpoint adjustments at 900px and 600px with dark/variant theme overrides.
Removed Files
index.html (366 lines), css/styles.css (1112 lines), js/script.js (145 lines), privacy.html (292 lines), terms.html (271 lines)
Replaced by templated equivalents and refactored frontend. Old script.js interactive features (header scroll, mobile menu, anchor smoothing, case-study overlays, step highlighting, form feedback, IntersectionObserver animations) consolidated and enhanced in main.js.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

The review requires assessment of heterogeneous changes across architecture, templating, styling, and interactive logic. main.js presents high-density canvas effect implementations with multiple variants; styles.css introduces a comprehensive design system requiring verification of responsive behavior and token consistency; multiple page templates must be validated for Eleventy structure and metadata; configuration requires confirmation of static passthrough and template engine setup. The scale and diversity of change categories demand substantial reasoning per file type.


🐰 Canvas rabbits dance across the screen,
Ten hero dreams in bytes unseen,
From static HTML to templates so neat,
Eleventy hops make the site complete,
Sticky nav whispers, reveals take flight—
Our warren's refactored, oh what a sight! 🎨✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main changes: migrating to Eleventy and adding the new interactive hero system with multiple canvas variants.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/eleventy-rebuild

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (6)
_includes/nav.njk (1)

5-13: Add ARIA wiring for the mobile menu toggle.
Line 5-13: consider adding aria-controls and aria-expanded so assistive tech can understand menu state. You’ll also need to toggle aria-expanded in openNav()/closeNav().

Suggested markup diff
-    <div class="nav-links">
+    <div class="nav-links" id="primary-navigation">
@@
-    <button class="nav-toggle" aria-label="Toggle menu">
+    <button class="nav-toggle" aria-label="Toggle menu" aria-controls="primary-navigation" aria-expanded="false">

To complement this, update main.js to toggle aria-expanded when opening/closing.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@_includes/nav.njk` around lines 5 - 13, Add ARIA attributes to the mobile
toggle button and update the JS to keep them in sync: give the menu container
(the div.nav-links) a stable id and add aria-controls="that-id" and
aria-expanded="false" to the button.nav-toggle in the template, then update the
openNav() and closeNav() functions in main.js to set
button.setAttribute('aria-expanded', 'true') when opening and 'false' when
closing (and ensure the initial state is false on page load); also ensure any
toggle handler that both opens and closes flips aria-expanded accordingly.
about.njk (1)

31-33: Lazy‑load the mission image to reduce CLS and bandwidth.
Line 32: add loading="lazy" and decoding="async" (and width/height if known) to reduce layout shift.

Suggested diff
-        <img src="/assets/images/noboxdevcontact.png" alt="No Box Dev team working" style="border-radius: var(--radius);">
+        <img src="/assets/images/noboxdevcontact.png" alt="No Box Dev team working" loading="lazy" decoding="async" style="border-radius: var(--radius);">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@about.njk` around lines 31 - 33, The mission image <img> in about.njk
currently lacks lazy loading and async decoding which can increase CLS and
bandwidth; update the <img> element (the line containing the img tag with
src="/assets/images/noboxdevcontact.png") to add loading="lazy" and
decoding="async", and include explicit width and height attributes if you know
the intrinsic dimensions to lock the layout and prevent cumulative layout shift.
styles.css (1)

25-63: Stylelint: Font-family names and keyframe naming conventions.

Static analysis flags stylistic issues that can be optionally addressed:

  1. Font-family quotes: Stylelint prefers unquoted font names in @font-face declarations (e.g., font-family: Aeonik instead of font-family: 'Aeonik').

  2. Keyframe names: Stylelint expects kebab-case (e.g., page-in, glow-drift-1) instead of camelCase (pageIn, glowDrift1).

Both are valid CSS and function correctly. Address if aligning with project linting rules.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@styles.css` around lines 25 - 63, Remove the quotes from the font-family
declarations in the `@font-face` rules (change 'Aeonik' and 'Arbeit' to unquoted
Aeonik and Arbeit in the declarations for Aeonik and Arbeit) and, separately,
rename any keyframe identifiers to kebab-case to match linting (e.g., change
pageIn → page-in, glowDrift1 → glow-drift-1) and update any references to those
keyframes in your CSS/animations to use the new kebab-case names.
_includes/base.njk (1)

19-21: Missing twitter:image meta tag.

Twitter Cards require twitter:image for large image previews. Currently relying on Open Graph fallback, which may not work reliably for all Twitter clients. Also note that the default og:image is an SVG logo, which Twitter may not render properly.

🔧 Suggested fix
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:title" content="{{ ogTitle or title }}">
  <meta name="twitter:description" content="{{ ogDescription or description }}">
+ <meta name="twitter:image" content="{{ ogImage or 'https://noboxdev.com/assets/images/og-default.png' }}">

Consider using a PNG/JPG image (1200×630px recommended) for better social media preview compatibility.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@_includes/base.njk` around lines 19 - 21, Add an explicit twitter:image meta
tag to the template so Twitter Cards get a raster image instead of relying on OG
fallback; update _includes/base.njk to include <meta name="twitter:image"
content="{{ twitterImage or ogImage or image }}"> (or similar variable used for
og:image) and ensure the default image points to a PNG/JPG (recommended
1200×630) rather than the SVG logo.
contact.njk (1)

38-41: Inconsistent form validation: message field lacks required attribute.

The message textarea here is not required, but the same field in index.njk (Line 279) has required. Consider making this consistent across both contact forms.

🔧 Suggested fix
          <div class="form-group">
            <label for="message">Tell us about your project</label>
-           <textarea id="message" name="message" rows="5" placeholder="Describe your project, goals, and timeline..."></textarea>
+           <textarea id="message" name="message" rows="5" placeholder="Describe your project, goals, and timeline..." required></textarea>
          </div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contact.njk` around lines 38 - 41, The message textarea in the contact form
(element with id="message" and name="message") is missing the required
attribute; update the <textarea id="message" name="message" rows="5"
placeholder="Describe your project, goals, and timeline..."></textarea> to
include required (e.g. ... placeholder="..." required></textarea>) so validation
matches the other form that uses the same id/name.
index.njk (1)

111-116: Placeholder links with href="#" may cause accessibility and UX issues.

The case study links go to # but are visually covered by "Coming soon" overlays. Screen readers will still announce these as actionable links, and clicking scrolls to top unexpectedly. Consider one of these alternatives:

🔧 Option A: Remove the link and style the overlay as the primary element
          <div class="case-study-link-wrapper">
-           <a href="#" class="case-study-link">View Case Study <span>&rarr;</span></a>
-           <div class="coming-soon-overlay">
-             <span class="coming-soon-btn">Coming soon</span>
-           </div>
+           <span class="coming-soon-btn">Coming soon</span>
          </div>
🔧 Option B: Add aria-disabled to indicate non-functional state
-           <a href="#" class="case-study-link">View Case Study <span>&rarr;</span></a>
+           <a href="#" class="case-study-link" aria-disabled="true" tabindex="-1">View Case Study <span>&rarr;</span></a>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@index.njk` around lines 111 - 116, Replace the placeholder anchor to avoid an
actionable link: remove href="#" from the element with class "case-study-link"
and either (A) convert the <a class="case-study-link"> into a non-interactive
element (e.g., <span> or <div>) and style it as before so the
"coming-soon-overlay" and "coming-soon-btn" remain visible, or (B) if keeping an
anchor, add aria-disabled="true" and tabindex="-1" and prevent default click
behavior so screen readers and keyboard users know it is inactive; update the
DOM around the "case-study-link-wrapper" to reflect the chosen approach and
ensure no click/scroll-to-top occurs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@contact.njk`:
- Line 20: The form with id "contact-form" currently posts to a suspicious test
address via its action attribute ("meme@noboxdev.com"); update the action to the
intended recipient (e.g., change the email in the action URL to
hello@noboxdev.com) or confirm and replace it with the correct production
address so the contact form posts to the same displayed contact email.

In `@index.njk`:
- Line 259: The form with id "contact-form" currently uses the placeholder
recipient meme@noboxdev.com in its action URL; update the action value on the
<form id="contact-form"> (or make it configurable) to the correct recipient
address or to a template/config variable (e.g., CONTACT_EMAIL) instead of the
hardcoded meme@noboxdev.com so it no longer duplicates the placeholder used in
contact.njk.

In `@main.js`:
- Around line 86-94: The current submit handler on form (the listener added to
form via form.addEventListener('submit', ...)) triggers native navigation so the
setTimeout success UI (formOk, btn) is never shown; update the handler to accept
the event parameter, call e.preventDefault(), disable the submit button (btn)
and then perform an async submit (e.g., fetch) to the formsubmit endpoint, and
on success hide the form and add class 'show' to formOk; alternatively, if you
want to keep native submission, remove the inline success UI code (the
setTimeout block) so unreachable code is not present.

In `@package.json`:
- Around line 6-9: The package.json scripts are missing a "start" entry
referenced by the PR test plan; add a "start" script in the scripts object
(alongside "build" and "serve") that runs the Eleventy dev server (e.g., set
"start" to the same command as "serve" such as "npx `@11ty/eleventy` --serve") so
npm start works as expected.

In `@styles.css`:
- Around line 96-102: The global rule on the selector "button, input, textarea,
select" removes default focus outlines, harming keyboard accessibility; either
remove "outline: none" from that rule or restrict that reset and add explicit
visible focus styles for all interactive controls (e.g., ensure selectors like
".form-group input:focus", ".form-group textarea:focus", "button:focus",
"select:focus" define clear outlines/box-shadows) so every interactive element
has a keyboard-visible focus state.

---

Nitpick comments:
In `@_includes/base.njk`:
- Around line 19-21: Add an explicit twitter:image meta tag to the template so
Twitter Cards get a raster image instead of relying on OG fallback; update
_includes/base.njk to include <meta name="twitter:image" content="{{
twitterImage or ogImage or image }}"> (or similar variable used for og:image)
and ensure the default image points to a PNG/JPG (recommended 1200×630) rather
than the SVG logo.

In `@_includes/nav.njk`:
- Around line 5-13: Add ARIA attributes to the mobile toggle button and update
the JS to keep them in sync: give the menu container (the div.nav-links) a
stable id and add aria-controls="that-id" and aria-expanded="false" to the
button.nav-toggle in the template, then update the openNav() and closeNav()
functions in main.js to set button.setAttribute('aria-expanded', 'true') when
opening and 'false' when closing (and ensure the initial state is false on page
load); also ensure any toggle handler that both opens and closes flips
aria-expanded accordingly.

In `@about.njk`:
- Around line 31-33: The mission image <img> in about.njk currently lacks lazy
loading and async decoding which can increase CLS and bandwidth; update the
<img> element (the line containing the img tag with
src="/assets/images/noboxdevcontact.png") to add loading="lazy" and
decoding="async", and include explicit width and height attributes if you know
the intrinsic dimensions to lock the layout and prevent cumulative layout shift.

In `@contact.njk`:
- Around line 38-41: The message textarea in the contact form (element with
id="message" and name="message") is missing the required attribute; update the
<textarea id="message" name="message" rows="5" placeholder="Describe your
project, goals, and timeline..."></textarea> to include required (e.g. ...
placeholder="..." required></textarea>) so validation matches the other form
that uses the same id/name.

In `@index.njk`:
- Around line 111-116: Replace the placeholder anchor to avoid an actionable
link: remove href="#" from the element with class "case-study-link" and either
(A) convert the <a class="case-study-link"> into a non-interactive element
(e.g., <span> or <div>) and style it as before so the "coming-soon-overlay" and
"coming-soon-btn" remain visible, or (B) if keeping an anchor, add
aria-disabled="true" and tabindex="-1" and prevent default click behavior so
screen readers and keyboard users know it is inactive; update the DOM around the
"case-study-link-wrapper" to reflect the chosen approach and ensure no
click/scroll-to-top occurs.

In `@styles.css`:
- Around line 25-63: Remove the quotes from the font-family declarations in the
`@font-face` rules (change 'Aeonik' and 'Arbeit' to unquoted Aeonik and Arbeit in
the declarations for Aeonik and Arbeit) and, separately, rename any keyframe
identifiers to kebab-case to match linting (e.g., change pageIn → page-in,
glowDrift1 → glow-drift-1) and update any references to those keyframes in your
CSS/animations to use the new kebab-case names.


<div class="contact-grid reveal">
<div>
<form id="contact-form" action="https://formsubmit.co/meme@noboxdev.com" method="POST">
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Suspicious form action email address.

The form action uses meme@noboxdev.com which appears to be a test/placeholder email. This differs from the displayed contact email hello@noboxdev.com on Line 56. Verify this is the intended recipient address before deploying.

🔧 Suggested fix
-        <form id="contact-form" action="https://formsubmit.co/meme@noboxdev.com" method="POST">
+        <form id="contact-form" action="https://formsubmit.co/hello@noboxdev.com" method="POST">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<form id="contact-form" action="https://formsubmit.co/meme@noboxdev.com" method="POST">
<form id="contact-form" action="https://formsubmit.co/hello@noboxdev.com" method="POST">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contact.njk` at line 20, The form with id "contact-form" currently posts to a
suspicious test address via its action attribute ("meme@noboxdev.com"); update
the action to the intended recipient (e.g., change the email in the action URL
to hello@noboxdev.com) or confirm and replace it with the correct production
address so the contact form posts to the same displayed contact email.

</div>

<div>
<form id="contact-form" action="https://formsubmit.co/meme@noboxdev.com" method="POST">
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Same placeholder email as contact.njk.

This form also uses meme@noboxdev.com. See comment on contact.njk Line 20.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@index.njk` at line 259, The form with id "contact-form" currently uses the
placeholder recipient meme@noboxdev.com in its action URL; update the action
value on the <form id="contact-form"> (or make it configurable) to the correct
recipient address or to a template/config variable (e.g., CONTACT_EMAIL) instead
of the hardcoded meme@noboxdev.com so it no longer duplicates the placeholder
used in contact.njk.

Comment on lines +86 to +94
const form = document.querySelector('#contact-form');
const formOk = document.querySelector('.form-success');
if (form) {
form.addEventListener('submit', () => {
const btn = form.querySelector('button[type="submit"]');
btn.textContent = 'Sending...';
btn.disabled = true;
if (formOk) setTimeout(() => { form.style.display = 'none'; formOk.classList.add('show'); }, 1000);
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find the contact form markup
rg -n -C3 'id="contact-form"' -S

Repository: No-Box-Dev/website

Length of output: 996


Remove unreachable inline success UI or prevent form submission and handle async.

Lines 89–94: The form submits natively to formsubmit.co with a _next redirect, so the page navigates away before the setTimeout callback renders the success message. Either call e.preventDefault() and submit asynchronously via fetch, or remove the inline success state since the user is redirected server-side anyway.

Async-submit approach if staying on page
-  form.addEventListener('submit', () => {
+  form.addEventListener('submit', async (e) => {
+    e.preventDefault();
     const btn = form.querySelector('button[type="submit"]');
     btn.textContent = 'Sending...';
     btn.disabled = true;
-    if (formOk) setTimeout(() => { form.style.display = 'none'; formOk.classList.add('show'); }, 1000);
+    try {
+      await fetch(form.action, {
+        method: form.method || 'POST',
+        body: new FormData(form),
+        headers: { 'Accept': 'application/json' },
+      });
+      if (formOk) { form.style.display = 'none'; formOk.classList.add('show'); }
+    } finally {
+      btn.disabled = false;
+    }
   });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const form = document.querySelector('#contact-form');
const formOk = document.querySelector('.form-success');
if (form) {
form.addEventListener('submit', () => {
const btn = form.querySelector('button[type="submit"]');
btn.textContent = 'Sending...';
btn.disabled = true;
if (formOk) setTimeout(() => { form.style.display = 'none'; formOk.classList.add('show'); }, 1000);
});
const form = document.querySelector('#contact-form');
const formOk = document.querySelector('.form-success');
if (form) {
form.addEventListener('submit', async (e) => {
e.preventDefault();
const btn = form.querySelector('button[type="submit"]');
btn.textContent = 'Sending...';
btn.disabled = true;
try {
await fetch(form.action, {
method: form.method || 'POST',
body: new FormData(form),
headers: { 'Accept': 'application/json' },
});
if (formOk) { form.style.display = 'none'; formOk.classList.add('show'); }
} finally {
btn.disabled = false;
}
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@main.js` around lines 86 - 94, The current submit handler on form (the
listener added to form via form.addEventListener('submit', ...)) triggers native
navigation so the setTimeout success UI (formOk, btn) is never shown; update the
handler to accept the event parameter, call e.preventDefault(), disable the
submit button (btn) and then perform an async submit (e.g., fetch) to the
formsubmit endpoint, and on success hide the form and add class 'show' to
formOk; alternatively, if you want to keep native submission, remove the inline
success UI code (the setTimeout block) so unreachable code is not present.

Comment on lines +6 to +9
"scripts": {
"build": "npx @11ty/eleventy",
"serve": "npx @11ty/eleventy --serve"
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add a start script to match the documented test plan.
Line 6-9: the PR test plan says npm start, but there’s no start script, so it will error.

Suggested diff
   "scripts": {
     "build": "npx `@11ty/eleventy`",
-    "serve": "npx `@11ty/eleventy` --serve"
+    "serve": "npx `@11ty/eleventy` --serve",
+    "start": "npm run serve"
   },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"scripts": {
"build": "npx @11ty/eleventy",
"serve": "npx @11ty/eleventy --serve"
},
"scripts": {
"build": "npx `@11ty/eleventy`",
"serve": "npx `@11ty/eleventy` --serve",
"start": "npm run serve"
},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` around lines 6 - 9, The package.json scripts are missing a
"start" entry referenced by the PR test plan; add a "start" script in the
scripts object (alongside "build" and "serve") that runs the Eleventy dev server
(e.g., set "start" to the same command as "serve" such as "npx `@11ty/eleventy`
--serve") so npm start works as expected.

Comment on lines +96 to +102
button, input, textarea, select {
font: inherit;
color: inherit;
border: none;
background: none;
outline: none;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Removing outline: none degrades keyboard accessibility.

Setting outline: none on form elements removes the default focus indicator. While custom focus styles are defined for .form-group input:focus etc. (Lines 964-969), this reset applies globally and may affect interactive elements without custom focus styles. Consider removing this or ensuring all interactive elements have visible focus states.

🔧 Suggested fix: Remove outline: none or add visible focus fallback
 button, input, textarea, select {
   font: inherit;
   color: inherit;
   border: none;
   background: none;
-  outline: none;
 }
+
+/* Provide visible focus for all interactive elements */
+:focus-visible {
+  outline: 2px solid var(--coral);
+  outline-offset: 2px;
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
button, input, textarea, select {
font: inherit;
color: inherit;
border: none;
background: none;
outline: none;
}
button, input, textarea, select {
font: inherit;
color: inherit;
border: none;
background: none;
}
/* Provide visible focus for all interactive elements */
:focus-visible {
outline: 2px solid var(--coral);
outline-offset: 2px;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@styles.css` around lines 96 - 102, The global rule on the selector "button,
input, textarea, select" removes default focus outlines, harming keyboard
accessibility; either remove "outline: none" from that rule or restrict that
reset and add explicit visible focus styles for all interactive controls (e.g.,
ensure selectors like ".form-group input:focus", ".form-group textarea:focus",
"button:focus", "select:focus" define clear outlines/box-shadows) so every
interactive element has a keyboard-visible focus state.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant