Skip to content

Rebuild as a dependency-free static installer - #85

Open
lost-hope wants to merge 12 commits into
wled:masterfrom
lost-hope:master
Open

Rebuild as a dependency-free static installer#85
lost-hope wants to merge 12 commits into
wled:masterfrom
lost-hope:master

Conversation

@lost-hope

@lost-hope lost-hope commented Jul 28, 2026

Copy link
Copy Markdown
Member

Replaces the static per-release bin/ manifest tree with live GitHub
Releases API fetching (app.js), consolidating script.js/releases.js
into one module.

New Features:

  • Flash size selection (1/2/4/8/16MB) per chip, with unavailable
    sizes hidden automatically.
  • HUB75 Matrix variant with a board/layout picker (ESP32 default and
    forum pinouts, HD-WF2, Adafruit MatrixPortal S3, MOONHUB/LilyGO
    T7-S3, Waveshare RGB-Matrix), each showing its required chip and
    flash size.
  • New pre-patched + re-signed bootloaders and partition tables for
    ESP32-S3 at 4/16/32MB, generated with esptool's own header-patch
    algorithm and verified via esptool image-info.
  • A CORS-proxy health check that disables Install until real
    firmware bytes are confirmed reachable, instead of silently
    flashing an error page as firmware.
  • Dynamic i18n: languages load from lang/*.json + lang/languages.json
    at runtime, so adding a language needs no code changes. Added
    German, Spanish, Portuguese, Dutch and French alongside the
    existing English/Chinese.

Cleanup

Removes installer/ (unused bundled esp-web-tools, superseded by the
CDN build already in index.html), the legacy auto.htm/v2.htm pages,
and the disabled nightly-download workflow.

Changes

Changed version to 10.4.0 as reported by https://github.com/balloob in #84

Summary by CodeRabbit

  • New Features

    • Introduced a refreshed WLED Web Installer with dynamic version/firmware selection and built-in support for variants, flash sizes, board models, and HUB75 layouts.
    • Added CORS-proxy availability checks and improved guidance when version loading or downloads are blocked.
    • Added dynamic localization across English, Chinese, German, Spanish, Portuguese, Dutch, French, and Pirate.
  • Documentation

    • Reworked the README for setup, deployment, localization, and installer file/usage guidance.
  • Chores

    • Added structured bug-report and feature-request issue templates.

Replaces the static per-release bin/ manifest tree with live GitHub
Releases API fetching (app.js), consolidating script.js/releases.js
into one module. Adds:

- Flash size selection (1/2/4/8/16MB) per chip, with unavailable
  sizes hidden automatically.
- HUB75 Matrix variant with a board/layout picker (ESP32 default and
  forum pinouts, HD-WF2, Adafruit MatrixPortal S3, MOONHUB/LilyGO
  T7-S3, Waveshare RGB-Matrix), each showing its required chip and
  flash size.
- New pre-patched + re-signed bootloaders and partition tables for
  ESP32-S3 at 4/16/32MB, generated with esptool's own header-patch
  algorithm and verified via `esptool image-info`.
- A CORS-proxy health check that disables Install until real
  firmware bytes are confirmed reachable, instead of silently
  flashing an error page as firmware.
- Dynamic i18n: languages load from lang/*.json + lang/languages.json
  at runtime, so adding a language needs no code changes. Added
  German, Spanish, Portuguese, Dutch and French alongside the
  existing English/Chinese.

Removes installer/ (unused bundled esp-web-tools, superseded by the
CDN build already in index.html), the legacy auto.htm/v2.htm pages,
and the disabled nightly-download workflow.
Listed openly in the language picker (☠️ Pirate), same pattern as
well-known "pirate mode" easter eggs elsewhere. Full translation of
every string, no code changes required - just lang/pirate.json plus
one line in lang/languages.json.
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

Next review available in: 52 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: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 557cf620-2fd4-4b91-b64e-87c24c50c584

📥 Commits

Reviewing files that changed from the base of the PR and between f809b04 and 4f542a3.

⛔ Files ignored due to path filters (72)
  • bin/Beta/beta_0_15_1-b1/boot_app0.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b1/bootloader_s2.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b1/esp32-c3_bootloader_v2.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b1/esp32_bootloader_v4.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b2/boot_app0.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b2/bootloader_s2.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b2/esp32-c3_bootloader_v2.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b2/esp32_bootloader_v4.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b2/partitions_s2_4m.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b2/partitions_s3_8m.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_2-b1/boot_app0.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_2-b1/bootloader_s2.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_2-b1/bootloader_s3.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_2-b1/esp32-c3_bootloader_v2.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_2-b1/esp32_bootloader_v4.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_2-b1/partitions_c3_4m.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_2-b1/partitions_s2_4m.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_2-b1/partitions_s3_8m.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_3/bootloader_s2.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_3/bootloader_s3.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_3/esp32-c3_bootloader_v2.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_3/esp32_bootloader_v4.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_3/partitions_c3_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_3/partitions_s2_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_3/partitions_s3_8m.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_4/bootloader_s2.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_4/bootloader_s3.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_4/esp32-c3_bootloader_v2.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_4/esp32_bootloader_v4.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_4/partitions_c3_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_4/partitions_s2_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_4/partitions_s3_8m.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_1/boot_app0.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_1/bootloader_s2.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_1/bootloader_s3.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_1/esp32-c3_bootloader_v2.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_1/esp32_bootloader_v4.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_1/partitions_c3_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_1/partitions_s2_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_1/partitions_s3_8m.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_2/boot_app0.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_2/bootloader_s2.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_2/bootloader_s3.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_2/esp32-c3_bootloader_v2.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_2/esp32_bootloader_v4.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_2/partitions_c3_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_2/partitions_s2_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_2/partitions_s3_8m.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_3/boot_app0.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_3/bootloader_s2.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_3/bootloader_s3.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_3/esp32-c3_bootloader_v2.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_3/esp32_bootloader_v4.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_3/partitions_c3_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_3/partitions_s2_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_3/partitions_s3_8m.bin is excluded by !**/*.bin
  • bin/boot/bootloader_s3_16m.bin is excluded by !**/*.bin
  • bin/boot/bootloader_s3_32m.bin is excluded by !**/*.bin
  • bin/boot/bootloader_s3_4m.bin is excluded by !**/*.bin
  • bin/boot/partitions_s3_16m.bin is excluded by !**/*.bin
  • bin/boot/partitions_s3_32m.bin is excluded by !**/*.bin
  • bin/boot/partitions_s3_4m.bin is excluded by !**/*.bin
  • bin/boot/partitions_s3_hdwf2.bin is excluded by !**/*.bin
  • bin/nightly/boot_app0.bin is excluded by !**/*.bin
  • bin/nightly/boot_app0_v2022.bin is excluded by !**/*.bin
  • bin/nightly/bootloader_s2.bin is excluded by !**/*.bin
  • bin/nightly/bootloader_s3.bin is excluded by !**/*.bin
  • bin/nightly/esp32-c3_bootloader_v2.bin is excluded by !**/*.bin
  • bin/nightly/esp32_bootloader_v4.bin is excluded by !**/*.bin
  • bin/nightly/partitions_c3.bin is excluded by !**/*.bin
  • bin/nightly/partitions_s2_4m.bin is excluded by !**/*.bin
  • bin/nightly/partitions_s3_8m.bin is excluded by !**/*.bin
📒 Files selected for processing (69)
  • .github/ISSUE_TEMPLATE/bug_report.yml
  • .github/ISSUE_TEMPLATE/config.yml
  • .github/ISSUE_TEMPLATE/feature_request.yml
  • .github/workflows/nightly.yaml
  • README.md
  • app.js
  • auto.htm
  • bin/Beta/beta_0_15_1-b1/manifest.json
  • bin/Beta/beta_0_15_1-b1/manifest_e.json
  • bin/Beta/beta_0_15_1-b1/manifest_t.json
  • bin/Beta/beta_0_15_1-b2/manifest.json
  • bin/Beta/beta_0_15_1-b2/manifest_e.json
  • bin/Beta/beta_0_15_1-b2/manifest_t.json
  • bin/Beta/beta_0_15_2-b1/manifest.json
  • bin/Beta/beta_0_15_2-b1/manifest_e.json
  • bin/Beta/beta_0_15_2-b1/manifest_t.json
  • bin/Beta/beta_0_15_2-b1/manifest_v4.json
  • bin/Release/release_0_14_3/manifest.json
  • bin/Release/release_0_14_3/manifest_a.json
  • bin/Release/release_0_14_3/manifest_e.json
  • bin/Release/release_0_14_3/manifest_t.json
  • bin/Release/release_0_14_4/manifest.json
  • bin/Release/release_0_14_4/manifest_a.json
  • bin/Release/release_0_14_4/manifest_e.json
  • bin/Release/release_0_14_4/manifest_t.json
  • bin/Release/release_0_15_1/manifest.json
  • bin/Release/release_0_15_1/manifest_e.json
  • bin/Release/release_0_15_1/manifest_t.json
  • bin/Release/release_0_15_1/manifest_v4.json
  • bin/Release/release_0_15_2/manifest.json
  • bin/Release/release_0_15_2/manifest_e.json
  • bin/Release/release_0_15_2/manifest_t.json
  • bin/Release/release_0_15_2/manifest_v4.json
  • bin/Release/release_0_15_3/manifest.json
  • bin/Release/release_0_15_3/manifest_e.json
  • bin/Release/release_0_15_3/manifest_t.json
  • bin/Release/release_0_15_3/manifest_v4.json
  • bin/nightly/manifest.json
  • bin/nightly/manifest_debug.json
  • bin/nightly/manifest_e.json
  • bin/nightly/manifest_t.json
  • checkhtml.sh
  • i18n.js
  • index.htm
  • index.html
  • installer/esp32-76e55e75.js
  • installer/esp32c3-47b374e0.js
  • installer/esp32c6-6da0b175.js
  • installer/esp32s2-0d35c7ed.js
  • installer/esp32s3-69876819.js
  • installer/esp8266-00e25dbe.js
  • installer/index-54fb20b9.js
  • installer/install-button.js
  • installer/install-dialog-19322187.js
  • installer/rom-7e8b4fbe.js
  • installer/styles-fa761598.js
  • lang/de.json
  • lang/en.json
  • lang/es.json
  • lang/fr.json
  • lang/languages.json
  • lang/nl.json
  • lang/pirate.json
  • lang/pt.json
  • lang/zh-CN.json
  • releases.js
  • script.js
  • style.css
  • v2.htm

Walkthrough

The WLED Web Installer is rebuilt around a dynamic index.html and app.js flow that retrieves release assets, generates manifests, validates proxy access, supports localized UI text, and adds structured repository issue intake and documentation. Legacy installer pages, bundled installer modules, static manifests, and the nightly update workflow are removed.

Changes

WLED installer application

Layer / File(s) Summary
Installer page and controls
index.html, style.css
The new page provides Web Serial installation controls, release and firmware selections, status/error sections, language selection, and styling for the expanded interface.
Release discovery and manifest selection
app.js
Release assets are mapped to chip, variant, flash-size, and HUB75 manifests; version options are cached and populated; selection availability and proxy health determine installation state.
Runtime localization
i18n.js, lang/*
Language metadata and translation files are loaded at runtime, cached, applied with English fallback, and exposed through the language selector.
Repository guidance and issue intake
.github/ISSUE_TEMPLATE/*, README.md
Issue forms, contact links, development/deployment guidance, localization documentation, file descriptions, and license information are added.
Legacy installer and generated assets removal
auto.htm, index.htm, v2.htm, releases.js, script.js, installer/*, bin/*, checkhtml.sh, .github/workflows/nightly.yaml
Superseded installer pages, bundled modules, static manifests, manifest validation, and nightly asset synchronization are removed.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant app_js
  participant GitHub_Releases_API
  participant CORS_Proxy
  participant esp_web_tools
  Browser->>app_js: Initialize installer
  app_js->>GitHub_Releases_API: Fetch releases
  GitHub_Releases_API-->>app_js: Return release assets
  app_js->>CORS_Proxy: Validate firmware access
  CORS_Proxy-->>app_js: Return proxy response
  app_js->>esp_web_tools: Set generated manifest
Loading

Suggested reviewers: netmindz

Poem

A rabbit hops through releases bright,
Builds tiny manifests just right.
Languages bloom in a leafy row,
Proxy checks tell the path to go.
“Install!” it thumps—then off we leap!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: rebuilding the installer as a dependency-free static app.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (4)
index.html (1)

11-14: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Pin esp-web-tools with SRI (integrity/crossorigin).

The script is loaded from unpkg with a pinned version but no integrity hash or crossorigin attribute. This page has direct Web Serial device-flashing capability, so a compromised/tampered CDN asset would run with full page privileges. Since the version is already pinned, adding SRI is low effort.

🔒 Example fix
   <script
     type="module"
     src="https://unpkg.com/esp-web-tools@10.4.0/dist/web/install-button.js?module"
+    integrity="sha384-<hash-for-10.4.0>"
+    crossorigin="anonymous"
   ></script>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@index.html` around lines 11 - 14, Add Subresource Integrity protection to the
external esp-web-tools module script: add the verified hash for the exact pinned
10.4.0 asset and set the required crossorigin attribute. Keep the existing
module type and URL unchanged.
app.js (3)

17-17: 🧹 Nitpick | 🔵 Trivial

Unauthenticated GitHub API calls share a 60 req/hr rate limit per IP.

Every visitor behind the same NAT/corporate egress IP shares GitHub's unauthenticated rate limit; the 5-minute sessionStorage cache is per-browser-session, not shared across users, so a moderately busy shared IP could exhaust the quota and start showing loadError to everyone behind it. Since this is a "no server component" static app, worth considering a lightweight edge cache/proxy in front of the GitHub API call (e.g., a small Cloudflare Worker with its own cache) if this becomes an issue in practice.

Also applies to: 699-723

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app.js` at line 17, Address the GitHub API rate-limit risk in the
release-fetching flow using the existing GITHUB_RELEASES_URL call and related
logic around lines 699-723: route requests through a shared edge-cache/proxy
endpoint, such as a Cloudflare Worker, rather than calling the unauthenticated
GitHub API directly. Preserve the current release data handling and
sessionStorage caching behavior while configuring the proxy to cache responses
for multiple visitors.

533-542: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Dynamically-generated radio labels bypass the i18n system.

fs.label + ' (' + chips.join(', ') + ')' and layout.label + ' (' + layout.chip + ', ' + layout.flashSizeLabel + ')' are written directly as textContent, always in English, regardless of the selected language — unlike the rest of the UI which goes through data-i18n/i18n_apply(). Board/chip names are arguably fine to leave untranslated, but descriptive bits ("default pinout", "forum pinout") won't be localized either.

Also applies to: 558-566

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app.js` around lines 533 - 542, Update the dynamic label rendering in the
FLASH_SIZES loop and the corresponding layout-label block to use the existing
i18n mechanism for descriptive text, including the parenthesized chip/pinout
wording, while preserving board and chip names as values. Ensure the generated
labels are localized according to the selected language rather than assigning
fully composed English strings directly to textContent.

682-682: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add a timeout to the fetch calls.

Neither the GitHub releases fetch nor the proxy health-check fetch has a timeout (AbortController/AbortSignal.timeout). A hung connection leaves the page stuck on "Loading versions..." or "Checking firmware download availability..." indefinitely instead of falling back to the error UI.

♻️ Example fix
-    fetch(GITHUB_RELEASES_URL + '?per_page=30')
+    fetch(GITHUB_RELEASES_URL + '?per_page=30', { signal: AbortSignal.timeout(15000) })

Also applies to: 708-712

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app.js` at line 682, Update both fetch calls in the GitHub releases and proxy
health-check flows, including the call near the HEAD request, to use an
AbortController or AbortSignal.timeout with a finite timeout. Ensure timed-out
requests follow the existing error-handling paths so the UI falls back from
“Loading versions...” or “Checking firmware download availability...” instead of
remaining stuck.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app.js`:
- Around line 653-692: The checkProxyHealth function currently enables Install
based only on HEAD res.ok, without confirming the proxy returns firmware bytes.
Replace or supplement the HEAD request with a ranged GET and validate the
response body contains actual firmware data, or validate reliable Content-Type
and Content-Length headers before enabling installBtn; keep the failure path
through showProxyBlocked.
- Around line 39-47: Update the Classic ESP32 entry in CHIP_CONFIG so its
bootParts layout matches the actual format of esp32_bootloader_v4.bin: if it is
a bare second-stage bootloader, use offset 4096 and include
partitions_esp32_4m.bin at offset 32768; if it is a factory-merged image, keep
it alone at offset 0. Ensure the selected layout does not flash the bootloader
incorrectly or omit the partition table.

In `@index.html`:
- Around line 63-64: Make `#showSerialHelp` keyboard-operable by replacing the
href-less anchor with a button using the existing link styling, or by adding
appropriate focusability and keyboard activation handling alongside its click
behavior in app.js. Ensure Enter and Space reveal `#serialHelp` with the same
behavior as mouse activation.

In `@README.md`:
- Around line 22-24: Update the fenced command block containing `npx serve .` to
specify the `console` or `bash` language on its opening fence, preserving the
command and surrounding README content.

---

Nitpick comments:
In `@app.js`:
- Line 17: Address the GitHub API rate-limit risk in the release-fetching flow
using the existing GITHUB_RELEASES_URL call and related logic around lines
699-723: route requests through a shared edge-cache/proxy endpoint, such as a
Cloudflare Worker, rather than calling the unauthenticated GitHub API directly.
Preserve the current release data handling and sessionStorage caching behavior
while configuring the proxy to cache responses for multiple visitors.
- Around line 533-542: Update the dynamic label rendering in the FLASH_SIZES
loop and the corresponding layout-label block to use the existing i18n mechanism
for descriptive text, including the parenthesized chip/pinout wording, while
preserving board and chip names as values. Ensure the generated labels are
localized according to the selected language rather than assigning fully
composed English strings directly to textContent.
- Line 682: Update both fetch calls in the GitHub releases and proxy
health-check flows, including the call near the HEAD request, to use an
AbortController or AbortSignal.timeout with a finite timeout. Ensure timed-out
requests follow the existing error-handling paths so the UI falls back from
“Loading versions...” or “Checking firmware download availability...” instead of
remaining stuck.

In `@index.html`:
- Around line 11-14: Add Subresource Integrity protection to the external
esp-web-tools module script: add the verified hash for the exact pinned 10.4.0
asset and set the required crossorigin attribute. Keep the existing module type
and URL unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 313d7bf3-cd91-4c5e-98a4-5d44c95cc055

📥 Commits

Reviewing files that changed from the base of the PR and between f809b04 and 6d8516a.

⛔ Files ignored due to path filters (72)
  • bin/Beta/beta_0_15_1-b1/boot_app0.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b1/bootloader_s2.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b1/esp32-c3_bootloader_v2.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b1/esp32_bootloader_v4.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b2/boot_app0.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b2/bootloader_s2.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b2/bootloader_s3.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b2/esp32-c3_bootloader_v2.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b2/esp32_bootloader_v4.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b2/partitions_s2_4m.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_1-b2/partitions_s3_8m.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_2-b1/boot_app0.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_2-b1/bootloader_s2.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_2-b1/esp32-c3_bootloader_v2.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_2-b1/esp32_bootloader_v4.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_2-b1/partitions_c3_4m.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_2-b1/partitions_s2_4m.bin is excluded by !**/*.bin
  • bin/Beta/beta_0_15_2-b1/partitions_s3_8m.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_3/bootloader_s2.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_3/bootloader_s3.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_3/esp32-c3_bootloader_v2.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_3/esp32_bootloader_v4.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_3/partitions_c3_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_3/partitions_s2_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_3/partitions_s3_8m.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_4/bootloader_s2.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_4/bootloader_s3.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_4/esp32-c3_bootloader_v2.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_4/esp32_bootloader_v4.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_4/partitions_c3_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_4/partitions_s2_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_14_4/partitions_s3_8m.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_1/boot_app0.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_1/bootloader_s2.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_1/bootloader_s3.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_1/esp32-c3_bootloader_v2.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_1/esp32_bootloader_v4.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_1/partitions_c3_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_1/partitions_s2_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_1/partitions_s3_8m.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_2/boot_app0.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_2/bootloader_s2.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_2/bootloader_s3.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_2/esp32-c3_bootloader_v2.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_2/esp32_bootloader_v4.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_2/partitions_c3_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_2/partitions_s2_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_2/partitions_s3_8m.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_3/boot_app0.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_3/bootloader_s2.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_3/bootloader_s3.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_3/esp32-c3_bootloader_v2.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_3/esp32_bootloader_v4.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_3/partitions_c3_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_3/partitions_s2_4m.bin is excluded by !**/*.bin
  • bin/Release/release_0_15_3/partitions_s3_8m.bin is excluded by !**/*.bin
  • bin/boot/bootloader_s3_16m.bin is excluded by !**/*.bin
  • bin/boot/bootloader_s3_32m.bin is excluded by !**/*.bin
  • bin/boot/bootloader_s3_4m.bin is excluded by !**/*.bin
  • bin/boot/partitions_s3_16m.bin is excluded by !**/*.bin
  • bin/boot/partitions_s3_32m.bin is excluded by !**/*.bin
  • bin/boot/partitions_s3_4m.bin is excluded by !**/*.bin
  • bin/boot/partitions_s3_hdwf2.bin is excluded by !**/*.bin
  • bin/nightly/boot_app0.bin is excluded by !**/*.bin
  • bin/nightly/boot_app0_v2022.bin is excluded by !**/*.bin
  • bin/nightly/bootloader_s2.bin is excluded by !**/*.bin
  • bin/nightly/bootloader_s3.bin is excluded by !**/*.bin
  • bin/nightly/esp32-c3_bootloader_v2.bin is excluded by !**/*.bin
  • bin/nightly/esp32_bootloader_v4.bin is excluded by !**/*.bin
  • bin/nightly/partitions_c3.bin is excluded by !**/*.bin
  • bin/nightly/partitions_s2_4m.bin is excluded by !**/*.bin
  • bin/nightly/partitions_s3_8m.bin is excluded by !**/*.bin
📒 Files selected for processing (70)
  • .github/ISSUE_TEMPLATE/bug_report.yml
  • .github/ISSUE_TEMPLATE/config.yml
  • .github/ISSUE_TEMPLATE/feature_request.yml
  • .github/workflows/nightly.yaml
  • CNAME
  • README.md
  • app.js
  • auto.htm
  • bin/Beta/beta_0_15_1-b1/manifest.json
  • bin/Beta/beta_0_15_1-b1/manifest_e.json
  • bin/Beta/beta_0_15_1-b1/manifest_t.json
  • bin/Beta/beta_0_15_1-b2/manifest.json
  • bin/Beta/beta_0_15_1-b2/manifest_e.json
  • bin/Beta/beta_0_15_1-b2/manifest_t.json
  • bin/Beta/beta_0_15_2-b1/manifest.json
  • bin/Beta/beta_0_15_2-b1/manifest_e.json
  • bin/Beta/beta_0_15_2-b1/manifest_t.json
  • bin/Beta/beta_0_15_2-b1/manifest_v4.json
  • bin/Release/release_0_14_3/manifest.json
  • bin/Release/release_0_14_3/manifest_a.json
  • bin/Release/release_0_14_3/manifest_e.json
  • bin/Release/release_0_14_3/manifest_t.json
  • bin/Release/release_0_14_4/manifest.json
  • bin/Release/release_0_14_4/manifest_a.json
  • bin/Release/release_0_14_4/manifest_e.json
  • bin/Release/release_0_14_4/manifest_t.json
  • bin/Release/release_0_15_1/manifest.json
  • bin/Release/release_0_15_1/manifest_e.json
  • bin/Release/release_0_15_1/manifest_t.json
  • bin/Release/release_0_15_1/manifest_v4.json
  • bin/Release/release_0_15_2/manifest.json
  • bin/Release/release_0_15_2/manifest_e.json
  • bin/Release/release_0_15_2/manifest_t.json
  • bin/Release/release_0_15_2/manifest_v4.json
  • bin/Release/release_0_15_3/manifest.json
  • bin/Release/release_0_15_3/manifest_e.json
  • bin/Release/release_0_15_3/manifest_t.json
  • bin/Release/release_0_15_3/manifest_v4.json
  • bin/nightly/manifest.json
  • bin/nightly/manifest_debug.json
  • bin/nightly/manifest_e.json
  • bin/nightly/manifest_t.json
  • checkhtml.sh
  • i18n.js
  • index.htm
  • index.html
  • installer/esp32-76e55e75.js
  • installer/esp32c3-47b374e0.js
  • installer/esp32c6-6da0b175.js
  • installer/esp32s2-0d35c7ed.js
  • installer/esp32s3-69876819.js
  • installer/esp8266-00e25dbe.js
  • installer/index-54fb20b9.js
  • installer/install-button.js
  • installer/install-dialog-19322187.js
  • installer/rom-7e8b4fbe.js
  • installer/styles-fa761598.js
  • lang/de.json
  • lang/en.json
  • lang/es.json
  • lang/fr.json
  • lang/languages.json
  • lang/nl.json
  • lang/pirate.json
  • lang/pt.json
  • lang/zh-CN.json
  • releases.js
  • script.js
  • style.css
  • v2.htm
💤 Files with no reviewable changes (51)
  • CNAME
  • bin/Release/release_0_15_1/manifest_t.json
  • bin/Release/release_0_14_4/manifest_e.json
  • bin/Beta/beta_0_15_1-b1/manifest_t.json
  • bin/Beta/beta_0_15_2-b1/manifest.json
  • bin/Release/release_0_14_3/manifest_e.json
  • bin/Beta/beta_0_15_2-b1/manifest_v4.json
  • bin/Release/release_0_15_2/manifest_e.json
  • bin/Release/release_0_14_4/manifest_a.json
  • bin/Beta/beta_0_15_1-b1/manifest_e.json
  • installer/rom-7e8b4fbe.js
  • bin/nightly/manifest_debug.json
  • bin/Release/release_0_15_2/manifest_v4.json
  • bin/Release/release_0_14_3/manifest_t.json
  • bin/nightly/manifest.json
  • bin/Beta/beta_0_15_1-b2/manifest_e.json
  • installer/esp32c6-6da0b175.js
  • bin/Release/release_0_15_3/manifest_e.json
  • bin/Release/release_0_15_1/manifest_v4.json
  • bin/Beta/beta_0_15_1-b2/manifest_t.json
  • bin/Release/release_0_15_3/manifest_v4.json
  • bin/Release/release_0_14_3/manifest.json
  • bin/Beta/beta_0_15_2-b1/manifest_t.json
  • bin/Release/release_0_14_3/manifest_a.json
  • bin/Release/release_0_15_3/manifest.json
  • bin/Release/release_0_15_2/manifest_t.json
  • bin/Beta/beta_0_15_1-b2/manifest.json
  • bin/Release/release_0_14_4/manifest_t.json
  • bin/Release/release_0_15_3/manifest_t.json
  • bin/Release/release_0_14_4/manifest.json
  • .github/workflows/nightly.yaml
  • installer/esp32s2-0d35c7ed.js
  • bin/nightly/manifest_t.json
  • v2.htm
  • bin/Release/release_0_15_1/manifest.json
  • installer/index-54fb20b9.js
  • releases.js
  • bin/Release/release_0_15_1/manifest_e.json
  • bin/nightly/manifest_e.json
  • script.js
  • installer/esp32s3-69876819.js
  • installer/install-button.js
  • bin/Beta/beta_0_15_1-b1/manifest.json
  • installer/esp32c3-47b374e0.js
  • installer/esp32-76e55e75.js
  • auto.htm
  • checkhtml.sh
  • bin/Release/release_0_15_2/manifest.json
  • installer/esp8266-00e25dbe.js
  • index.htm
  • bin/Beta/beta_0_15_2-b1/manifest_e.json
📜 Review details
🧰 Additional context used
🪛 ast-grep (0.45.0)
app.js

[error] 646-646: React's useState should not be directly called
Context: setManifest()
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(usestate-direct-usage)

🪛 markdownlint-cli2 (0.23.1)
README.md

[warning] 22-22: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (17)
.github/ISSUE_TEMPLATE/bug_report.yml (1)

1-97: LGTM!

.github/ISSUE_TEMPLATE/config.yml (1)

1-8: LGTM!

.github/ISSUE_TEMPLATE/feature_request.yml (1)

1-30: LGTM!

README.md (1)

1-21: LGTM!

Also applies to: 25-57

index.html (1)

1-10: LGTM!

Also applies to: 15-62, 65-161

style.css (1)

49-51: LGTM!

Also applies to: 81-87, 112-143, 195-200

app.js (1)

1-38: LGTM!

Also applies to: 48-652, 693-707, 713-747

i18n.js (1)

2-96: LGTM!

lang/pirate.json (1)

1-40: LGTM!

lang/pt.json (1)

1-40: LGTM!

lang/zh-CN.json (1)

1-40: LGTM!

lang/de.json (1)

1-40: LGTM!

lang/en.json (1)

1-40: LGTM!

lang/es.json (1)

1-40: LGTM!

lang/fr.json (1)

1-40: LGTM!

lang/languages.json (1)

1-10: LGTM!

lang/nl.json (1)

1-40: LGTM!

Comment thread app.js
Comment thread app.js
Comment thread index.html Outdated
Comment thread README.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@style.css`:
- Around line 170-173: In the `#showSerialHelp` style rule, remove the duplicate
padding: 0 declaration and retain a single padding declaration.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 777c77af-fa39-4af7-81b3-c5c8d74b68c2

📥 Commits

Reviewing files that changed from the base of the PR and between 6d8516a and c6f88f7.

📒 Files selected for processing (4)
  • README.md
  • app.js
  • index.html
  • style.css
🚧 Files skipped from review as they are similar to previous changes (3)
  • README.md
  • index.html
  • app.js
📜 Review details
🧰 Additional context used
🪛 Stylelint (17.14.1)
style.css

[error] 170-170: Duplicate property "padding" (declaration-block-no-duplicate-properties)

(declaration-block-no-duplicate-properties)

Comment thread style.css Outdated
@lost-hope

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@lost-hope
lost-hope requested a review from netmindz July 29, 2026 11:34
@lost-hope lost-hope self-assigned this Jul 29, 2026
@lost-hope

Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.


Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 52 minutes.

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.

Web installer seems to upload wrong binary for S3 with QSPI psram or no psram

1 participant