Files
FreeCrawl-SEO-Tool/CHANGELOG.md
T
2026-10-18 00:47:06 +03:00

114 KiB
Raw Blame History

Changelog

[1.1.0] — 2026-10-18

Added

  • Adaptive speed (off by default) slows the crawl automatically on 429 / 503 / Retry-After responses and recovers once the server answers cleanly again.
  • Bot-protection detection marks pages blocked by Cloudflare, AWS WAF, Vercel, Sucuri or DataDome as "Blocked" instead of reporting them as broken links or 4xx errors.
  • A site-level soft-404 probe warns when missing pages return 200, and a Soft 404 issue flags "not found" pages served with a 2xx status.
  • New benchmark-driven checks (hreflang outside head, HTTP/2, page size, dead external domains, CORS and more) bring the catalogue to 181 checks (thanks @alvinycheung).
  • The status bar shows every post-crawl phase, such as measuring images or running checks, with live counts.
  • srcset and picture image variants are listed without being fetched unless the new Spider setting or the CLI --image-variants flag turns them on.
  • Images and other resources now show their Inlinks in URL Details.
  • CLI: --adaptive-speed and --image-variants flags, Yandex Metrica commands (metrica-counters, metrica-fetch) and support for desktop-saved projects.

Changed

  • Stored page bodies are zstd-compressed with a per-project dictionary, shrinking working project files several times over on template-heavy sites.
  • The Linux AppImage now starts on Ubuntu 24.04+ by disabling Chromium's sandbox only where the kernel denies unprivileged user namespaces; the .deb and .rpm keep the sandbox.
  • README and the update dialog explain the macOS 15 Sequoia Gatekeeper flow (Open Anyway); the CLI now requires Node 22.13 or newer.
  • README refreshed with the current feature set, counts and a new live-crawl demo GIF.

Fixed

  • Lazy-loaded images, tracking pixels, aria-labelled links, duplicate alt text and title/meta lengths measured in code points no longer produce false alarms.
  • External links are re-checked with GET and a browser User-Agent before being reported broken.
  • Sentence counting no longer stalls on long unpunctuated pages (thanks @alvinycheung).
  • Cookie checks show "Off" instead of 0 when all cookies are rejected, crawls mark the project as unsaved, and keyboard hints show the Command key on macOS.

[1.0.1] — 2026-10-13

Added

  • Yandex Metrica integration with unsampled pageviews, visits, users and search visits per crawled URL (thanks @danzerzine).
  • Metrica data has its own tab with filters and exports, appears in URL Details and the orphan report, and is available over MCP.

Fixed

  • Clicking a row in the Broken Links, GA4, Search Console, PageSpeed, CrUX, AI and SEO Authority tabs now opens it in URL Details.
  • Anchor text and target=_blank checks now catch links to pages the menu already links to, instead of reporting 0.
  • MCP query and report tools now return Search Console and GA4 data instead of empty results.
  • An expired Google sign-in now explains the one-time fix for the 7-day token limit instead of asking you to reconnect weekly.
  • Smaller translation fixes in the setup guides.

[1.0.0] — 2026-09-21

Added

  • FreeCrawl 1.0.0 is the full release; updates will keep coming based on user feedback.
  • The interface is available in 11 languages, from Turkish and Spanish to Chinese, Korean and Hindi, and follows your system language on first launch.
  • Light theme, switchable from View → Theme or Settings → Theme, with every table, badge and banner tuned for contrast.
  • Canvas-rendered URL table that keeps scrolling smooth and live updates flicker-free on crawls of 25K+ URLs.
  • PDF report export with a brandable header (name, logo, accent colour) and a recommendations section.
  • Screaming Frog-compatible SEO Audit export so existing audit templates and Looker sources work without remapping.
  • Scheduled crawls can export bulk, audit, HTML and PDF reports automatically and notify a webhook when they finish.
  • Custom Extraction rules get their own table columns, plus ready-made templates for price, stock, author, dates, ratings and SKU.
  • Optional crawl setting to follow JavaScript redirects (meta refresh and inline location changes).
  • Canonical chains are followed from redirect targets, with a new "Redirect → Canonical Chain" issue.
  • New checks: Content Wider Than Screen, Mobile / Desktop Mismatch, and structured-data findings that jump to the offending JSON-LD block.
  • Settings → Issues lets you disable any of the 172 checks per project, and Settings → System shows live memory use and environment details.
  • Auto-save the open project every N crawled URLs (Settings → Storage).
  • New E-commerce, News and Accessibility-focus crawl presets.
  • "Pages Over Max Links per Page" report, and Top Words can now include body text.

Changed

  • Release files are named by platform and CPU (Windows-Setup, Windows-Portable, macOS-Apple-Silicon, macOS-Intel, Linux) so the right download is obvious.
  • Check for Updates now recognises an Apple Silicon Mac running the Intel build under Rosetta and offers the native build.
  • Bulk Export gained the remaining datasets: redirect and canonical chains, hreflang, orphans, AMP, structured data, issue severities and link-level CSVs.

Fixed

  • Stop now responds immediately on large crawls instead of waiting for the post-crawl analysis to finish.
  • Saving a large project no longer freezes the window; the title shows "Saving…" while it runs in the background.
  • Sidebar issue counts and table queries no longer stall the app on 60K+ URL crawls.
  • The table no longer goes black while scrolling during a live crawl.
  • The duplicate URL check now respects the "normalise before comparing" setting.

[0.9.9] — 2026-09-09

Added

  • In-app AI Assistant tab — chat over your crawl data with OpenAI, Claude, or Ollama, and connect external MCP servers to add their tools.
  • Crawl setting to skip URLs with query strings, plus a parameter whitelist, so faceted navigation no longer eats the whole URL budget.
  • SPA route discovery for JavaScript rendering — hash routes and History-API navigations are now crawled as their own pages.

Changed

  • The Settings dialog and every table column tooltip are now fully translated into Turkish.
  • The Log Analyzer URL Hits tab gained a response-code filter, with hover explanations for each threat category and the threat score.

Fixed

  • X-Robots-Tag directives are now scoped to the correct bot, so a rule meant for one crawler no longer leaks onto the others.
  • robots.txt parsing is capped at 512 KiB to stay fast and within spec on oversized files.

[0.9.8] — 2026-08-27

Added

  • New "Suspicious Requests" tab in the Log Analyzer flags SQL-injection, XSS, and scanner probes in your access logs with the sender IP and the decoded payload.
  • Export (CSV/Excel) buttons on every integration tab, and all integration tables added to the "Export Crawl Data" dialog.
  • Optional adaptive crawl speed that automatically slows down when a site returns 429 / Retry-After and speeds back up once it recovers.
  • Richer debug.txt diagnostics so a remote user's issue can be pinpointed from a single file.

Changed

  • Removed the Privacy settings page — FreeCrawl keeps no telemetry, so the opt-in served no purpose.

Fixed

  • Fixed the detail panel showing no Inlinks/Outlinks for a selected URL.
  • Fixed crawl freezes and sidebar filters hanging on large sites, caused by slow issue queries.
  • Fixed the crawl appearing stuck during the post-crawl image probe by pacing it and reporting progress.
  • Fixed the Copy button in the Logs window.
  • Fixed the Log Analyzer showing old sample data after a fresh crawl.
  • Fixed the red "—" status badge shown for URLs blocked by robots.txt.
  • Various performance, stability, and UI refinements.

[0.9.7] — 2026-08-23

Added

  • Images tab now lists each image per page it appears on, with a Page column, so Missing/Empty Alt is accurate for every page.
  • Opt-in "Allow invalid HTTPS certificate" for browser form-login — off by default so credentials aren't typed into an unverified page.

Changed

  • Crawl credentials (auth, proxy, custom headers) are now encrypted at rest and stripped from shared settings exports.
  • Exports now honour the active search and advanced filter, so the file matches exactly what the table shows.
  • robots.txt is now evaluated per origin, so cross-protocol and subdomain URLs are checked correctly.
  • URLs blocked by robots.txt are now recorded, so the "Blocked by robots.txt" count is no longer always zero.

Fixed

  • Fixed the Overview panel staying blank in RAM-only storage mode.
  • Fixed several crashes, freezes, and out-of-memory cases on large crawls, exports, and log imports.
  • Fixed quitting with unsaved changes (Ctrl/Cmd+Q) wiping the crawl.
  • Fixed tabs falsely reporting "no broken links / no images" and detail panels stuck on "Loading…" when a query failed.
  • Fixed relative links and canonicals resolving wrongly when a page declares a <base> tag.
  • Fixed robots.txt user-agent matching, X-Robots-Tag per-bot rules, and noindex, follow pages not being crawled through.
  • Fixed sitemap comparisons, favicon/thin-content flags on redirects, and the non-ASCII and uppercase URL checks.
  • Fixed Missing/Empty Alt being judged site-wide instead of per page, and external links reporting a redirect's final status.
  • Fixed crawl-control buttons and destructive actions failing silently instead of reporting the error.
  • Hardened against credential leaks in logs and exports, CSV formula injection, path traversal, and untrusted-content navigation.
  • Various stability, correctness, and UI refinements.

[0.9.6] — 2026-08-20

Added

  • Four new canonical checks — Conflicting Canonicals, Canonical → Cross-Domain, Noindex + Canonical Conflict, and Redirect → Noindex.
  • A Crawl Trap filter that flags faceted-navigation, session-ID, calendar, and repeating-path URLs which quietly drain crawl budget.
  • Optional URL normalisation settings to sort query parameters and collapse duplicate slashes, removing a common source of false duplicates.

Fixed

  • The Log Analyzer now reads gzipped .gz access logs, which previously imported as zero lines.
  • Relative canonicals such as href="/page" are now resolved before comparison, so self-referencing pages are no longer reported as canonicalised away.
  • Gzipped sitemaps are now read instead of skipped, and oversized or mislabelled sitemaps are reported as warnings.
  • URLs that differ only by percent-escape casing (%2f versus %2F) no longer appear as two separate rows.
  • Crawls no longer run away on link loops like /shop/shop/shop/, and any skipped URLs are reported when the crawl finishes.
  • Long post-crawl passes on large projects no longer hit a locked database or abort crawl teardown.

[0.9.5] — 2026-08-15

Added

  • Ready-to-use GitHub Actions and GitLab CI templates that run a crawl as a build gate, with a setup guide.

Changed

  • "Delete Domain Data" now completes much faster on large single-domain projects.

Fixed

  • Opening a project crawled from the command line, or saved by an older build, now restores the start URL in the toolbar instead of coming up blank.
  • The table's search, sort, and advanced filter now stay set when you leave a tab and return, instead of resetting to empty.
  • The Overview sidebar no longer reports Response Codes and Security percentages above 100%.

[0.9.4] — 2026-08-13

Added

  • Several automated agents can now share one crawler safely, each working in its own isolated session with a crawl queue.
  • The Advanced table filter can now match on the values captured by your custom extraction rules.

Changed

  • Custom extraction values now read as plain text in the results table instead of raw JSON, matching the extraction preview.
  • Sitemap and List crawls now stay within the supplied URL set instead of also following on-page links and fetching every asset.

Fixed

  • Redirect and error pages are no longer reported as missing title, meta description, H1, and other on-page elements they can never have.
  • Search Console data now attaches to a crawled page even when the two URLs differ only by a trailing slash or letter case.
  • Opening a saved project by double-clicking it now restores the start URL and mode in the toolbar instead of coming up blank.
  • The results table no longer briefly draws two rows over each other while a crawl is running.
  • Consistent toolbar strip across every detail-panel sub-tab, plus various interface refinements.

[0.9.3] — 2026-08-08

Added

  • Connect several Google Search Console and Analytics accounts, and pick which one each project reports on from the tab toolbar.
  • Every integration now has its own settings page, so one long shared page no longer buries the option you are looking for.
  • Search Console gains a date range, device / search type / country / query filters, and twelve ready-made URL filter presets.
  • A "Crawl New URLs Discovered In Google Search Console" option that pulls in pages Search Console knows about but your crawl never reached.
  • Import several server log files at once, both in the app and from the command line.

Changed

  • Integrations is now a collapsible heading in the settings sidebar rather than a page of its own.

Fixed

  • Resuming an interrupted Sitemap or List crawl now genuinely carries on instead of re-fetching every page it had already done.
  • Resuming a crawl no longer risks clearing the project when the sitemap changed while the app was closed.
  • The toolbar now shows the mode and start URL of a resumed crawl, and of a project you open, instead of resetting to an empty Spider.
  • Screenshots are now captured in unsaved projects too — the Screenshot tab used to stay empty unless you had saved the project first.
  • Saving a project now takes its screenshots along, so they still appear after Save As and when the project is reopened.
  • Robots directives are now read from every robots meta tag on a page, including ones written in uppercase.
  • Google sign-in now explains a blocked consent screen and how to fix it, instead of failing with a generic timeout after five minutes.
  • A timed-out database read no longer piles more work onto the busy worker, which could leave every table in the window waiting.
  • Various improvements and refinements.

[0.9.2] — 2026-07-29

Added

  • A Crawl and Store switch for every link type — images, CSS, JavaScript, media, canonicals, pagination, hreflang, AMP, iframes — so you control exactly what is fetched and what is reported.
  • Right-click any table selection to copy cells, rows, or columns to the clipboard.
  • A Mobile Alternate column that surfaces separate-URL (m-dot) mobile pages, including the classic setup with no canonical pointing back.
  • A change marker on rows that differ from the previous crawl, so a re-crawl shows at a glance what moved.
  • An optional "Respect robots.txt Crawl-delay" setting for teams whose policy requires it.

Changed

  • robots.txt Crawl-delay is now ignored by default, matching Google and Screaming Frog — sites that publish it no longer turn a 40-second crawl into hours.
  • Pages are now crawled ahead of images, CSS, and JavaScript, so the table fills with real pages from the first seconds instead of assets.
  • Assets can no longer consume a whole Max URLs budget, so a capped crawl returns pages rather than one page and its images.
  • A robots.txt Crawl-delay is now reported in the log whether it is honoured or ignored, so a slow crawl is never unexplained.

Fixed

  • Fixed Clear taking around 17 seconds on a large project; it now finishes in under a second.

[0.9.1] — 2026-07-23

Added

  • Offline spell checking for languages LanguageTool can't cover — Turkish ships with a bundled dictionary, so its pages get real findings instead of a warning.
  • Each project now saves as a single compressed file, so moving or emailing one means one file instead of three.
  • Any sub-table in the URL Details panel (Inlinks, Outlinks, Images, Resources) can now be exported on its own to CSV or Excel.
  • JavaScript rendering now provisions its own Chromium automatically — bundled in the installer, or downloaded in the background when the bundle can't run on your machine.
  • Turkish tooltips for the on-screen ⓘ help text across table columns and settings.

Changed

  • Spelling & grammar now detects each page's language locally before checking, so Turkish and other pages are no longer graded against the wrong language and flagged word-by-word.
  • Pages in a language LanguageTool has no dictionary for are now marked "unsupported" instead of being scored against a substitute language.
  • The "Add API Key" and Spelling "Options" buttons now open Settings directly on the right panel and highlight the field to fill in.
  • Applying a crawl preset now shows a clear confirmation so it's obvious the settings changed.

[0.9.0] — 2026-07-21

Added

  • The link visualiser now opens in WebGL 3D — a force-directed crawl tree and link graph you can orbit and fly through, matching how large sites are usually explored.
  • Crawl Tree and Directory Tree stay 2D and gained click-to-collapse branches, so a 100K-URL site can be folded down to the part you care about.
  • Hovering any node now shows a summary card with title, response code, indexability, H1, depth, inlinks, outlinks, and word count instead of just the URL.
  • Long crawls on macOS now hold a power assertion so App Nap can't throttle them while the window is in the background.
  • Crawl concurrency now scales down automatically as macOS reports rising thermal pressure, so fanless Macs degrade gracefully instead of stalling.

Changed

  • macOS keyboard shortcuts now match Windows — Cmd+C and the rest of the edit shortcuts work everywhere in the app.
  • Encrypted project save and open now stream, so protecting a multi-gigabyte project no longer depends on it fitting in memory.
  • Exports that must build the whole file in memory now check available headroom first and suggest a streaming format instead of failing late.
  • The Top Anchor Texts panel is now a ranked list with usage bars, replacing the hard-to-read word cloud.

Fixed

  • Fixed a crash that could end a long crawl on macOS during the post-crawl phase by running out of memory.
  • Fixed sidebar filter counts that didn't match the rows you got when clicking them, across Response Codes, Security, and Indexability.
  • Fixed word count including JavaScript and CSS from the page, which inflated it many times over and broke the thin-content, empty-page, and readability checks.
  • Fixed boilerplate detection reporting every sampled page as fully templated regardless of the site.
  • Various visualisation and performance refinements.

[0.8.9] — 2026-07-20

Added

  • New Sitemap crawl mode plus an optional sitemap seed for spider crawls — crawl exactly what a sitemap lists, or feed one in for faster discovery and orphan detection.
  • A Desktop/Mobile toggle in the toolbar that crawls a site's mobile version (mobile User-Agent + viewport), useful when the mobile page renders differently.
  • New "Duplicate Alt Text" image check that flags distinct images sharing the same alt text.

Changed

  • The crawl mode selector (Spider / List / Sitemap) now sits in the toolbar beside the URL bar, with an inline editor for the List URL set.
  • The app now always opens in Spider mode with an empty URL bar.
  • Various small UI improvements across the Search Console and Images tabs.

Fixed

  • The "Empty Alt" image issue now counts images (not pages) and its click-through filter works, so the sidebar number matches what you see.

[0.8.8] — 2026-07-18

Added

  • New Video and News XML sitemap variants — build a Google News sitemap or a video sitemap for the crawled site.
  • The Generate Sitemap menu is now a submenu exposing every variant (Standard, Images, Hreflang, News, Video).
  • New mobile-usability checks that flag pages with text or tap targets too small to use comfortably on phones (JavaScript rendering only).
  • A system tray icon with quick show/hide, stop-crawl, and quit actions.

[0.8.7] — 2026-07-14

Added

  • Multi-window support — open several projects at once, each in its own window with an independent crawl, logs, settings, and enrichment runs.
  • Projects manager dialog to browse, search, tag, and archive recent projects, and start new ones from a template.
  • Project templates (E-commerce, Blog, News, Corporate, SaaS) that pre-fill sensible exclude rules and crawl budgets.
  • Each project file now remembers its own crawl configuration.

Changed

  • Various improvements and enhancements.

[0.8.5] — 2026-07-06

Added

  • Chrome UX Report tab — real-user Core Web Vitals (p75 LCP, INP, CLS, FCP, TTFB) per page for phone and desktop.
  • Spelling and grammar checking via LanguageTool, with a custom dictionary, picky rule level, and in-context highlighting of every finding.
  • A "Spelling/Grammar Issues" sidebar filter that lists pages with at least one finding.
  • Five new MCP tools so agents can run and read CrUX and spelling checks.

Changed

  • Various improvements and enhancements.

[0.8.2] — 2026-07-06

Added

  • Internal PageRank "Link Score" (0–100) per page — a sortable column, a detail-panel row, and a "By Link Score" graph colour mode showing where internal link equity concentrates.
  • RAM-only storage mode — run a crawl entirely in memory for maximum speed, writing to disk only when you Save As (Settings → Storage).

Changed

  • Cross-source orphan pages (sitemap + Search Console + Analytics) now rank by traffic and are available as an MCP report tool.
  • Various performance and reliability improvements.

[0.8.1] — 2026-07-02

Added

  • Full Turkish and English localization across right-click menus, native dialogs, and settings panels.

Changed

  • The requests-per-second limit and robots.txt crawl-delay are now honoured during crawls.
  • Various performance, reliability, and UI polish improvements.

Fixed

  • Crawls now keep your configured proxy instead of silently dropping it after the first page.
  • Links with encoded characters are now fetched as the correct URL instead of a broken duplicate.
  • Legacy-encoded pages (e.g. older Turkish sites) no longer render as garbled text.
  • Country-code domains like .com.tr no longer let broad-scope crawls escape onto unrelated sites.
  • Image usage counts no longer inflate when the same pages are re-crawled.
  • External integrations no longer time out after running a crawl in the same session.
  • Large in-page link and report tables no longer freeze the interface.

[0.8.0] — 2026-06-29

Added

  • Three new site-graph layouts — Force-Directed Tree, Radial Tree, and Directory Tree — for clearer structural views of the crawl.
  • Crawl Path Report — click any page in the graph to trace its shortest discovery path from the homepage.
  • A "By LCP" graph colour overlay that flags pages whose largest above-the-fold element is an image, a prime optimisation target.
  • Browser-driven login mode that drives a real Chromium through JS-heavy SPA login forms, then reuses the session for the crawl.
  • XPath parent, ancestor, and sibling axes in custom extraction, for pulling values plain CSS selectors can't reach.
  • A new MCP get_crawl_path tool so AI agents can fetch any page's crawl path.

Changed

  • HTTP Digest auth now caches each host's challenge and authenticates proactively, avoiding a 401 round-trip on every URL.

Fixed

  • Importing custom-extraction rules no longer silently drops XPath and JSONPath rules.

[0.7.3] — 2026-06-26

Added

  • Log File Analyzer — a standalone window that parses Apache / Nginx / IIS / custom access logs into bot hits per URL, crawl budget, response-code distribution, and a daily trend.
  • Crawl × log join that surfaces URLs search-engine bots hit but the crawl never reached, with one click to seed them into a running crawl.
  • Bot detection across 40+ crawlers (Googlebot, Bingbot, YandexBot, GPTBot, …) with optional reverse-DNS verification to catch spoofed user-agents.
  • A per-bot filter on the URL Hits table to see exactly which pages any one bot crawled.
  • One-click export of every Log Analyzer table to a single CSV or a multi-sheet Excel workbook.
  • A headless analyze-logs CLI command to ingest access logs without opening the app.
  • New MCP tools to run a bulk export and to save / open (encrypted) project snapshots from an AI agent.

[0.7.2] — 2026-06-23

Added

  • The Internal tab now lists images, CSS, JavaScript, and fonts — each with its own status code, type, and size — not just HTML pages.
  • New "Check Images / CSS / JavaScript" toggles let you include or exclude page resources from the crawl, mirroring Screaming Frog.
  • Broken external resources (third-party scripts, stylesheets, images) and external HTML pages are now probed and classified, so dead third-party assets surface in Broken Links.

[0.7.1] — 2026-06-21

Added

  • SOCKS5 / SOCKS4 proxy support (including the DNS-at-proxy socks5h / socks4a variants), so crawls can route through Tor or an SSH tunnel — not just HTTP proxies.
  • HTTP Digest authentication alongside Basic and Bearer, for crawling staging sites and APIs protected by Digest auth.
  • Form-based multi-step login that establishes an authenticated session (with CSRF capture) before the crawl so member-only pages are reachable.
  • XPath custom-extraction rules for pulling values off the page with XPath 1.0 location paths and predicates.
  • JSONPath custom-extraction rules for pulling values straight out of JSON API responses, with live preview.
  • PDF metadata extraction that reads each crawled PDF's title, author, page count, creation date, and producer into the detail panel.
  • Issue severity tiers (Critical / Warning / Info) with a "split bulk export by severity" option that writes one rollup file or sheet per tier.
  • Start, watch, and cancel batch PageSpeed / AI / SEO-authority runs from connected AI agents over the MCP server.
  • List and fetch Google Search Console and Analytics 4 data directly from connected AI agents over the MCP server.

Fixed

  • Batch PageSpeed audits no longer fail under concurrency — fixed the timeout that killed every audit but the first when running many URLs.
  • PageSpeed audits now honor corporate HTTP/HTTPS proxy settings, so they work behind a proxy just like the crawler.
  • A proxy change between crawls in the same session now takes effect instead of the first crawl's proxy sticking for the whole session.

[0.7.0] — 2026-06-18

Added

  • Performance budget — set per-page response-time / page-size / LCP / CLS ceilings and flag every page that exceeds them under a new issue filter.
  • Structured-data validation now warns on missing Google-recommended properties (not just required ones) and covers 17 schema types including LocalBusiness, JobPosting, Review, and Course.

[0.6.9] — 2026-06-14

Added

  • Social image aspect-ratio validation — flags OG / Twitter images too small or wrongly shaped to render as a proper share card.
  • Core Web Vitals INP, TTI, and Max Potential FID in PageSpeed audits, with INP shown alongside LCP and CLS as a Core Web Vital.
  • Accessibility audit (opt-in, JS render) — flags low colour-contrast text (WCAG AA) and stylesheets that suppress the keyboard focus outline.

Fixed

  • macOS: added Edit and Window menus so copy / paste and ⌘M work, and cleared a ⌘R shortcut conflict between Reload and Reports.

[0.6.8] — 2026-06-04

Added

  • Canonical Conflict (Near-Duplicate) issue filter — flags pages clustered as near-duplicates whose declared canonical URLs disagree, a classic CMS localisation / pagination drift bug.
  • Query String Variant Grouping report — surfaces base URLs that share many tracker / session-id / faceted-nav variants so you can spot crawl bloat from un-stripped query parameters.
  • Sitemap Priority Mismatch report — high-priority sitemap URLs whose actual crawl outcome contradicts the declared importance (4xx, noindex, canonicalised, redirect, blocked, never reached).
  • Content area selector — Settings → Duplicates accepts a CSS selector that pins the duplicate fingerprint to a specific page region, overriding the heuristic.
  • Template / Boilerplate Detection — post-crawl sampling pass identifies repeated chrome (nav, footer, sidebar) across pages and flags pages whose unique 5-word shingles are over 50% boilerplate.

[0.6.7] — 2026-06-01

Added

  • MCP server action tools — 29 new actions covering every export format, sitemap generate / validate, robots tester, project compare, schedule, respider, remove, settings, URL rewrite + extraction previews, and graph snapshot.
  • MCP integration triggers — gsc_fetch, ga4_fetch, gsc_list_sites, ga4_list_properties, and google_auth_status let agents pull Search Console and Analytics data on demand.
  • In-app Integration Setup Guide modal — every integration card now opens a localised step-by-step walkthrough with deep links to the relevant Google Cloud Console pages and troubleshooting for the most common OAuth and API errors.

Changed

  • README Highlights rewritten as flowing paragraphs that reflect what the current release can actually do — shorter, less wall-of-bullets.

[0.6.6] — 2026-06-01

Added

  • Cluster view on the Duplicates tab — surfaces every near-duplicate cluster with grouped headers and inline members.
  • Column pin (sticky left) — pin frequently-referenced columns so they stay visible during horizontal scroll.
  • Column reorder via drag-drop — grab the grip handle on a header to rearrange columns within their pin region.
  • AMP smoke validation — pages declaring themselves AMP now flag missing boilerplate, runtime, canonical, and forbidden tags.
  • Extraction Preview button in Settings → Custom Extraction — test selectors / regex against a real URL before committing to a crawl.
  • Custom Extraction rule import / export — versioned JSON envelope, shareable as a file or via source control.
  • MCP server read parity — 33 new tools covering every detail sub-tab, integration row, report, and specialised query.
  • MCP clear_crawl tool — same primitive as the desktop "Clear" button so an agent can force a fresh BFS.

Fixed

  • Re-running a same-seed crawl via MCP no longer no-ops once the prior crawl already completed.
  • Advanced filter clauses now reset on tab change so a filter set on one tab doesn't silently apply to every other tab.
  • Column picker popover no longer hides behind the bottom detail panel — rendered through a portal at document.body.

[0.6.5] — 2026-05-28

Added

  • JavaScript rendering via headless Chromium (Playwright) — post-JS DOM capture for SPAs and hydration-only sites, used for link extraction + extraction rules.
  • View Rendered HTML detail sub-tab — compare raw HTTP response against post-JS DOM with side-by-side search and per-render timing badge.
  • Screenshot capture during JS render — full-page, above-the-fold, and 375×667 mobile-viewport PNGs stored next to the project file with a dedicated detail panel sub-tab.
  • LCP candidate detection — identifies the largest above-the-fold element after JS render and stores its CSS selector, dimensions, and resource URL.
  • Mobile Usability audit — re-renders each page on a mobile viewport and checks viewport meta, horizontal overflow, font size, and tap-target spacing.
  • Settings → Rendering panel — viewport, wait conditions, resource blocking, Chromium channel, pre-render JS snippet, screenshot mode, and advanced audit toggles.
  • "Export Crawl Data…" dialog — single menu entry replacing the three "Export Current View as …" items, with Excel .xlsx / CSV-UTF-8 / JSON / XML formats and a hierarchical tree picker that lays out top tables and their structural sub-categories under nested folders.
  • Per-tab quick-filter dropdown — Overview sub-categories accessible directly from each tab's toolbar without leaving the view.
  • List ↔ Tree view toggle — switch between flat virtualized table and URL-path hierarchy with collapsible folders.
  • Visualization moved to its own native window — accessible from the new "Visualization" top-level menu (Ctrl+G), free to park on a second monitor.
  • Full Settings dialog Turkish translation coverage — sidebar sections, dialog chrome, and every field label across the 24 panels.
  • Optional offline-ready installers — release builds now ship Playwright Chromium inside the installer so JavaScript rendering works on first launch with no extra download.

Changed

  • Overview sidebar clicks now auto-switch to the matching top-level tab (e.g. Response Codes → Client Error 4xx jumps to the Response Codes tab) for every structural group and 30+ issue filters.
  • File menu "About FreeCrawl SEO" now opens https://freecrawl.net/ in the default browser instead of doing nothing.
  • Browser pool startup checks the Playwright binary up-front and, if missing, surfaces a single download prompt instead of spamming a warning per URL.

Fixed

  • Mobile screenshot now actually renders on a 375×667 mobile viewport instead of producing a desktop above-the-fold duplicate.
  • Pre-render JS snippet no longer accumulates across pooled pages — it is registered once at the browser context level so long crawls run the snippet exactly once per navigation.
  • Stop button now cancels in-flight Playwright navigations immediately instead of waiting for the request timeout to elapse.
  • Browser pool no longer crashes the crawler when closed while page acquires are queued — waiters are rejected with a clean error.
  • Screenshot file IPC reader hardened against path-traversal attempts; only PNGs inside the active project's sidecar folder are returned.
  • Body snapshot truncation respects UTF-8 boundaries so the View Source / View Rendered tail no longer ends in a replacement character.
  • Render artefacts (rendered HTML, screenshots, LCP, mobile-usability) are now persisted inline before the URL is considered complete, eliminating a race window with the Clear button.
  • CSV / XLSX exports now neutralise cells beginning with =, +, -, @, TAB, or CR to prevent formula-injection attacks via crawled page content.
  • Tree view distinguishes root URLs that differ only by query string or fragment.
  • "Export Crawl Data" single-file mode now rewrites the chosen output path's extension to match the selected format.
  • Quick-filter dropdown shows a placeholder when the active category isn't in the predefined list instead of silently mislabelling itself as the first option.

[0.6.0] — 2026-05-25

Added

  • Google Search Console integration — pull clicks / impressions / CTR / position per crawled page and overlay them on the URL list.
  • Google Search Console URL Inspection — fetch coverage verdict, last-crawl time, and canonical decisions for batches of pages.
  • Google Analytics 4 integration — join GA4 sessions / users / engagement / avg session duration onto each crawled URL.
  • AI tab — run OpenAI, Anthropic, or local Ollama prompts per URL with shared variables ({url}/{title}/{description}/{h1}/{body}).
  • SEO Authority tab — unified Ahrefs / Majestic / Moz / Semrush per-URL metrics behind a single provider dropdown.
  • Google Sheets export — File menu writes the active category to a fresh Sheet and copies the link to clipboard.
  • BigQuery export — service-account streaming insert into a timestamped table inside the freecrawl_seo dataset.
  • Analytics sub-tab in the detail panel — combined GSC + GA4 + URL Inspection card view for the selected URL.
  • Reports → "Orphan Pages (Cross-Source)" — surfaces URLs that PSI / GSC / GA4 / sitemap know about but the crawl never reached.
  • Encrypted project snapshots — File menu now saves and opens AES-256-GCM-encrypted .seoproject.enc snapshots protected by a password.
  • Images tab — Export button writes every image row to CSV honouring the active missing-alt filter and search box.
  • CLI: ready-made GitHub Actions and GitLab CI templates that crawl a target on schedule and fail the pipeline on broken-URL thresholds.

Changed

  • PageSpeed Insights now requires a free API key — Google's keyless shared quota is 0/day so the tab gates the Run button and shows an "Add API Key…" call-to-action when no key is configured.
  • PageSpeed failure handling surfaces the exact Google error inline (QUOTA / RATE / TIMEOUT / NET tag plus a hover-tooltip), and the batch log lists the top distinct errors instead of just a failed count.
  • Memory limit setting now actively pauses and auto-resumes the crawler when RSS crosses the configured threshold instead of being a display-only value.

Fixed

  • Ahrefs integration — the v3 combined /site-explorer/overview endpoint was removed by Ahrefs, replaced with a parallel fan-out across the four per-metric endpoints with partial-success tolerance.
  • Semrush integration — type=url_overview was renamed to type=url_rank and the now-mandatory export_columns parameter is supplied.
  • Various crawler, UI, and integration stability fixes.

[0.5.6] — 2026-05-22

Added

  • Google PageSpeed Insights integration — a new PageSpeed tab runs on-demand Lighthouse audits (mobile + desktop) for the crawled pages you select.
  • Broken Links tab now also shows a "unique broken URLs" count — a stable figure that doesn't swing with how many pages a crawl reached.

Fixed

  • Re-crawling a URL no longer duplicates its link and image rows, which had been inflating broken-link and image counts.
  • macOS — closing the main window no longer prevents reopening it from the dock.
  • The Logs window no longer drags down the main window's frame rate while it is open.
  • Bulk actions (delete / re-spider / copy) on very large URL selections no longer fail.
  • Scheduled crawls no longer fire twice in a row when a crawl outlasts its interval.
  • "Check for Updates" now downloads the installer instead of the portable build.
  • Various crawler and UI stability fixes.

[0.5.5] — 2026-05-19

Added

  • Integrations panel (Settings → Integrations) — securely store API keys and OAuth credentials for OpenAI, Anthropic, Ollama, PageSpeed, Ahrefs, Moz, Semrush, Majestic, and Google services.
  • Rendering Mode setting — Text Only or Old AJAX Crawling Scheme (_escaped_fragment_); JavaScript rendering is reserved for V2.
  • Quick User-Agent preset switcher (Settings → Requests) — one click between Googlebot, Chrome, and Bingbot profiles.
  • Broken Links tab now has an Export button — writes every broken link to CSV, honouring the active internal/external filter.
  • Broken Links tab now supports cell selection, drag-select, Ctrl+C copy, and a right-click menu (copy cells, copy/open source & target URLs).

Changed

  • Near-duplicate detection now fingerprints the main content area only — site-wide nav/header/footer no longer makes distinct pages look like duplicates.

[0.5.2] — 2026-05-19

Fixed

  • Linux .deb / .rpm installer build — added author.email maintainer metadata, pinned the linux artifact filename (so the scoped package name no longer breaks the deb output path), and forced a space-free package name for rpm.

[0.5.1] — 2026-05-19

Fixed

  • Linux installer build — added the homepage / repository metadata that electron-builder's fpm target needs to package .deb and .rpm artifacts.

Changed

  • README updated with multi-language UI, scheduled crawl, file association, portable .exe, Linux .rpm, and the macOS / Linux .sh launcher.

[0.5.0] — 2026-05-19

Added

  • Multi-language UI (English + Turkish) — instant swap from Settings → Language, covers menus, sidebar, every tab, every dialog, and the detail panel.
  • Settings → Storage panel — pick a default folder for new .seoproject files; falls back to the OS Documents folder when unset.
  • Settings → Privacy panel — opt-in toggle for anonymous telemetry (off by default; no endpoint wired up yet, consent is persisted for future builds).
  • Linux .rpm installer target alongside AppImage / deb.
  • Windows portable .exe target alongside the NSIS installer — runs without installation.
  • .seoproject file association — double-clicking a project file from the OS opens it in FreeCrawl (Windows / macOS / Linux).
  • Custom CSS override — drop a custom-theme.css in the user-data folder to tweak colours, spacing, or typography without rebuilding the app.

[0.4.1] — 2026-05-15

Added

  • In-app scheduled crawl — File → Scheduled Crawl… arms an hourly/daily/weekly/custom recurring crawl per project, fires while FreeCrawl stays open.
  • Two new reports — Indexability Distribution and Content-Type Distribution histograms (Reports total 21 → 23).
  • Linux/macOS launcher script (.sh) mirrors the existing Windows .bat launcher with Node/npm checks, dependency install prompt, and production start.

[0.4.0] — 2026-05-15

Added

  • Visualization and SERP top-level tabs — the link graph and Google-style snippet preview moved out of a modal/sub-panel into permanent tabs.
  • Column show/hide menu in every URL table — toolbar button, header right-click to hide, and per-tab persistence.
  • Bulk Export added ~37 named CSVs across redirect, canonical, pagination, hreflang, duplicate, security, image, structured-data, AMP, and SERP families.

Fixed

  • MCP bridge silently failed to start because the address was read before the socket bound — Claude Code can now reliably drive desktop crawls again.

[0.3.7] — 2026-05-13

Added

  • MCP crawl control — Claude Code and any MCP client can now start, pause, resume, and stop crawls in the running desktop app and poll live progress, in addition to the existing read-only data queries.

[0.3.6] — 2026-05-12

Added

  • Top Words report — frequency table over the title + meta description + H1 corpus, with English/Turkish stopword filtering.
  • Status-code diagnosis banner in the HTTP Headers panel — decodes Cloudflare 52x/530 and standard 4xx/5xx codes with header-derived signals (cf-ray, Retry-After, CDN/server detection) and crawl-context fixes.
  • Request headers view in the HTTP Headers panel — toggle between captured response headers and the request headers reconstructed from the active crawl config.

Changed

  • Crawler settings relabelled to their Screaming Frog equivalents and the duplicated throughput inputs consolidated into the Speed section for clarity.
  • Settings dialog gained a "Reset to Defaults" button.

[0.3.5] — 2026-05-10

Added

  • Skipped Heading Level and Too Many Requests issue filters — surface accessibility outline gaps and pages with >100 subresources.
  • Security and Duplicates top-level tabs — security-header audit and near-duplicate cluster review in dedicated views.
  • Specialised columns on Pagination, Hreflang, AMP, Structured Data, Meta Refresh, Custom Extraction/Search, and Links tabs — each surfaces its domain data instead of generic placeholders.
  • Live memory monitor in the status bar — RSS, system free, per-URL cost, and capacity projection update every 2 seconds.
  • Robots.txt syntax validation — the Robots Tester custom-policy editor lints typos, orphan rules, sitemap URLs, crawl-delay, and deprecated noindex inline.

Changed

  • Boolean flag cells render as "Y" / "—" instead of "true" / "false" for a more compact table.

Fixed

  • Duplicate "Check for Updates" popup — concurrent silent and manual checks now share a re-entrancy guard so only one dialog appears.

[0.3.4] — 2026-05-09

Added

  • Accessibility issue filters — Main Landmark Missing, Skip Link Missing, and Invalid ARIA Role surface WCAG gaps.
  • Critical performance tier — Render-Blocking Head >20 and Page Size >3MB highlight LCP regressions beyond the warning thresholds.
  • Pagination Canonical Conflict filter — flags pages declaring both rel=next/prev and a non-self canonical.
  • Structured-data validation — Duplicate @id, Malformed @type, and Missing Required Property catch JSON-LD bugs that hurt rich-result eligibility.
  • Seven new top-level filter tabs — Pagination, Hreflang, AMP, Structured Data, Meta Refresh, Custom Extraction, Custom Search.
  • View Source match navigation — Enter / Shift+Enter cycle through hits, ↑/↓ buttons, and the active match auto-scrolls into view.

Changed

  • Clear button is ~4-5× faster (~2 s → ~400 ms) by wrapping the reset in a single SQLite transaction and truncating the WAL afterwards.
  • Various improvements and refinements.

Fixed

  • Bot-blocked pages with no URL extension now stay visible in the Internal tab instead of disappearing into the Other content kind.

[0.3.3] — 2026-05-04

Added

  • Web App Manifest parsing — pages’ PWA theme_color, short_name, display, scope, and number of icons can now be inspected.
  • TLS certificate chain view — CA hops from leaf to root are listed in the URL Details panel.
  • “Duplicate URL normalize” toggle — under Settings → Duplicates, you can choose between byte-exact vs. normalized comparison.
  • A Security Policy (SECURITY.md) has been added to the repository.

Changed

  • Various improvements and enhancements.

[0.3.2] — 2026-05-04

Added

  • In-app installer download in the "Update Available" dialog — when GitHub Releases lists a matching artifact for the current platform/arch (Windows .exe, macOS Intel .dmg, macOS ARM64 -arm64.dmg), the dialog now offers a "Download Installer" button alongside "Open Release Page". Saves to the user's Downloads folder via session.defaultSession.downloadURL with taskbar/dock progress, then reveals the file with shell.showItemInFolder. Linux falls back to the release page (no single canonical artifact). Code-signing-free path — the user installs manually after Gatekeeper / SmartScreen prompt.
  • Markdown release notes rendered as plain text — stripMarkdownToPlain collapses code fences, bold / italic, headings, links ([text](url) → text (url)), images, bullets, and strikethrough. Preview window expanded from 600 to 1500 chars.
  • "Don't show this version again" checkbox in the Update Available dialog — persists in the existing skipDiag:update-${tag} prefs namespace, so Help → "Reset Diagnostic Warnings" already clears it. Silent startup auto-check (8 s after launch) respects dismissals; manual menu invocation always shows.
  • srcset + <picture> support for images — html-parser now captures every candidate URL from <img srcset> and <picture> > <source srcset> (WHATWG-compatible split), feeding them into the same broken-image / large-image probe pipeline so retina + breakpoint variants no longer slip through. Per-page images_responsive (count of <img> slots that carry srcset or sit inside a <picture> parent) and picture_count columns (migration v49). New issue filter Low Responsive Image Adoption under Sidebar → Issues → Images, mirroring the lazy-loading rule's ≥5-image / <50%-adoption threshold. Detail Panel surfaces "Responsive Images" ratio + "<picture> Elements" count rows.
  • Malformed URL detection — isUrlMalformed helper in url-utils.ts flags URLs that browsers tolerate but search engines / log analysers diverge on: multiple ? or #, ASCII control chars (<0x20 / 0x7F), unescaped reserved chars (<>"{}|^), and double-encoding sequences (%2520etc.). The crawler sets a per-URLurl_malformed` 0/1 flag at every upsert path (HTML, redirect, non-HTML, size-cap, network-fail, seed-stub). New Malformed URL issue filter under Sidebar → Issues → URL.
  • OpenGraph extras — og:type (lowercased), og:url (verbatim raw, useful for canonical comparison), og:site_name (entity-decoded), and og:locale are now stored as separate columns and shown in the URL Details panel.
  • Android / PWA icon detection — first <link rel="icon" sizes> whose declared dimension is ≥192px (or sizes="any" for vectors) is captured as android_icon — the right adoption signal for home-screen / PWA launchers, distinct from the smaller favicon. Surfaced in the URL Details panel as "Android / PWA Icon".
  • Database migrations v49 + v50 — bundled column additions: images_responsive, picture_count (v49); url_malformed, og_type, og_url, og_site_name, og_locale, android_icon (v50).

Changed

  • Update Available dialog is now a 3-button dialog (Download Installer / Open Release Page / Later) on platforms with a matching installer asset, falling back to the 2-button form (Open Release Page / Later) elsewhere. Silent startup check skips network errors, up-to-date results, and dismissed versions so it isn't intrusive.

[0.3.1] — 2026-05-04

Fixed

  • Queue error: database is locked / External probe error: database is locked during crawl — root cause was two SQLite writer connections (main-thread ProjectDb + writer-worker ProjectDb) contending for the same file's writer lock. With busy_timeout=10s set on both, the periodic recomputeUrlsIssuesYielding pass (every 30 s, 70+ short transactions with setImmediate yields) could starve the main thread out of the lock window and surface as a visible error. Fixed by routing the crawler's high-frequency main-thread sync writes (upsertUrl for redirect / non-HTML / size-cap / network-fail rows, updateExternalProbe, setUrlHeaders, setSitemapUrls, checkpointQueue) through the same writer-worker pool that already serves writeFetchedUrl. Now the DB sees a single writer connection during a crawl — SQLite's lock contention is gone and serialisation happens at the worker's JS-level FIFO instead. New dbCall<T>(method, args) opt callback on Crawler (default = sync this.db[method](...args), so CLI / tests are unchanged); desktop main injects a dbCallViaPool dispatcher with main-thread fallback.

[0.3.0] — 2026-05-04

Added

  • Manual update check — Help → "Check for Updates…" menu item. Fetches the latest GitHub Releases tag (api.github.com/repos/kemalai/FreeCrawl-SEO-Tool/releases/latest, 10 s timeout) and compares it against app.getVersion() with a hand-rolled compareSemver (no semver dependency). Three native dialogs: up-to-date / update available with first-600-char release-notes preview + "Open Release Page" button / network error fallback with "Open Releases Page" link. Pure on-demand — no background polling, no telemetry. electron-updater-based auto-install deferred to V2 (requires macOS notarisation + Windows code-signing first).

[0.2.9] — 2026-05-04

Added

  • Readability scoring (Flesch Reading Ease, Flesch–Kincaid Grade, Gunning Fog Index) — computed inline during HTML parse from the same body-text token stream that drives wordCount. Dictionary-free vowel-group syllable heuristic (Hemingway / textstat / Yoast convention). Returns null scores when the page has <50 words or 0 sentences so navigation-only landing pages don't show a meaningless 0.0 grade. New issue filters: Hard to Read (Flesch <30) and Gunning Fog >17 under Sidebar → Issues → Content. Detail panel surfaces Sentence Count, Flesch with band ("very difficult" → "very easy"), F-K Grade, Fog Index, and Complex Words.
  • CORS header audit — captures Access-Control-Allow-Origin / -Credentials / -Methods / -Headers per URL (1 KB cap on -Headers). Two new issue filters: CORS Wildcard + Credentials (CRITICAL — * paired with credentials true; XSS-leveraged credential exfiltration vector) and CORS Wildcard Origin (informational — * without credentials). Detail panel renders all four headers; credentials value as human-readable true/false/missing.
  • HTTP (not HTTPS) issue filter — flags internal pages still served over plain HTTP. Excludes localhost, 127.0.0.1, and *.local hosts so local-dev crawls don't trip the filter.
  • Active vs passive mixed content split — separate counts and issue filters for Mixed Content Active (Blocked) (script/iframe/object/embed/stylesheet over HTTP — browsers silently drop these) and Mixed Content Passive (Warning) (img/video/audio/source over HTTP — rendered with "Not Secure" UI). Legacy mixed_content_count kept as the total for back-compat. <object data> is now picked up alongside the rest of the audit list.
  • URL rewriting suite — three additions to the normalizer:
    • Query parameter whitelist (keepQueryParams) — when non-empty, every query parameter not on the list is dropped (case-insensitive name match), replacing the default tracking-only strip behaviour.
    • Regex URL rewrites (urlRegexRewrites: [{pattern, replacement, flags?}]) — compiled once in the crawler, applied in order to the fully-normalised URL string and re-parsed (invalid output drops the link). Used during link-follow, canonical, and redirect-target normalisation.
    • Live preview in Settings → URL Rewriting — runs the unsaved configuration through normalizeUrl in main and surfaces the result + any regex compile errors before saving.
  • Custom Search regex mode — each line in customSearchTerms is dispatched on shape: /pattern/flags runs as a regex (allowed flags imsuy, g is always forced) via text.match(), anything else stays on the legacy lowercase-substring path. Invalid patterns are recorded as -1 and surfaced as "invalid regex" in the Detail panel so typos are visible. No DB migration — the JSON shape is unchanged.
  • Per-URL Duplicates sub-tab in the Detail panel — urlClusterMembers(urlId) returns every other URL in the same near-duplicate cluster sorted by SimHash hamming distance ascending (closest matches first). Table shows Hamming / URL / Status / Indexability / Words / Inlinks / Title; URLs open in the system browser. Singleton URLs see a guidance message pointing to Crawl Analysis and the Hamming-threshold setting.
  • Least-Linked URLs (Bottom 25) report — counterpart to the existing Most-Linked report. Excludes inlinks = 0 rows so it surfaces weakly-linked indexable pages, not orphans (orphan signal lives in dedicated filters). topUrlsBy gains a direction: 'asc' | 'desc' argument; TopUrlsInput.direction plumbed through the IPC.
  • DB migration v46 — flesch_reading_ease, flesch_kincaid_grade, gunning_fog_index, sentence_count, complex_word_count columns.
  • DB migration v47 — cors_allow_origin, cors_allow_credentials (-1 missing / 0 false / 1 true), cors_allow_methods, cors_allow_headers columns.
  • DB migration v48 — mixed_content_active, mixed_content_passive columns alongside the legacy mixed_content_count.
  • New IPC channels — url:rewrite-preview and urls:cluster-members.
  • README highlights table updated — Analysis tile gains CORS audit, mixed-content split, readability, custom search regex; Desktop UI tile gains 13-sub-tab count, Duplicates view, URL rewriting; Export tile gains 20-report count, Export Dialog with XLSX, MCP server. Status note updated.

Changed

  • normalizeUrl signature — UrlRewriteOptions now accepts keepQueryParams and pre-compiled regexRewrites. The crawler compiles regex rules once in its constructor (compileUrlRegexRewrites) and bad patterns are reported via the error event up-front so per-link normalisation cost stays constant.
  • Custom-search haystack lazy — the lowercase pass for literal terms is computed only if at least one literal term exists, so a regex-only term list no longer pays for it.

[0.2.8] — 2026-05-03

Added

  • In-table Export button + dialog — every URL tab now has an "Export" button in the toolbar (replaces the inline URL counter; counter moved to the bottom status bar). Modal lets the user pick: which tables to include (defaults to the tab the button was clicked from, "Active" badge), which columns (per-tab union, all-checked by default, with All / None toggles), the format (CSV or Excel .xlsx), and "Selected rows only" when there's a row selection. CSV with multiple tables → folder picker, one file per table; xlsx → single workbook with one sheet per table. Disabled when the table is empty.
  • Streaming-XLSX writer in @freecrawl/core (tabular-export.ts) — hand-rolled multi-sheet workbook writer using node:zlib DEFLATE + manual ZIP central directory. Inline-string sheets, sanitised sheet names, numeric/boolean cells typed correctly. Zero new dependencies.
  • ErrorBoundary component wrapping the export dialog so a render error in the dialog tree no longer black-screens the renderer (the dialog ate the entire React root before; now you get a small inline notice + Dismiss button + a console stack).
  • MCP server (apps/mcp-server/) — new workspace exposing the active .seoproject over the Model Context Protocol (stdio JSON-RPC 2.0). Read-only ProjectDb connection coexists with the desktop app's writer (SQLite WAL, concurrent readers). Hand-rolled — no @modelcontextprotocol/sdk dependency. 8 tools: get_summary, get_overview_counts, top_issues, query_urls (category + search + sort + paginate, projectable fields), get_url_detail (id or URL, inlinks + outlinks + images), list_projects, set_project, current_project. Cross-platform userData resolver matches Electron's path semantics; FREECRAWL_PROJECT env var overrides. Claude Desktop / Claude Code / generic-client install snippets in the README.
  • getUrlIdByUrl(url) public method on ProjectDb — used by the MCP server to resolve a URL string to its row id.

Changed

  • URL counter pill removed from the URL-table toolbar — the live count moved into the bottom status bar (URLs: N (M loaded)) so the toolbar can host the new Export button without losing the information.
  • Export dialog mounts only when open — dialog hooks no longer run on every parent re-render of the URLs tab, eliminating a state-churn loop that was triggered by selectedIds array references changing on each crawler progress tick.
  • README install section gains an "MCP server" details block with build instructions, Claude Desktop config snippet, Claude Code CLI command, sample prompts, and FREECRAWL_PROJECT env override usage.

[0.2.7] — 2026-05-02

Added

  • Multi-row aggregation in detail sub-tabs — selecting multiple URLs in the main table (Row column, Shift/Ctrl-click, drag, or cell-multi-select) now aggregates Inlinks, Outlinks, Images, and Resources across the full selection. Up to 50 URLs aggregated in parallel; primary-URL banner shown for per-page tabs (URL Details / Headers / Cookies / Source / SERP).
  • Right-click + Ctrl/Cmd+C in detail sub-tab tables — Inlinks/Outlinks tables now ship a context menu (Copy N Cells, Copy URL / Copy N URLs for URL cells, Open in Browser) and a document-level keyboard listener. Selection is row-then-column TSV so cells paste cleanly into Excel / Sheets.
  • Auto-drain pending link stubs at first-crawl end — links discovered but never crawled (depth-race, queue cap, filter race) are picked up before the first crawl finishes; pressing Start a second time on the same project no longer surfaces "+1000 new URLs". Up to 20 drain passes with excludeNofollow honoured so nofollow targets aren't silently followed.
  • Freeze-watchdog worker thread + debug.txt — independent worker_threads.Worker polls a SharedArrayBuffer every 250 ms and writes stall events to <userData>/debug.txt. Tracks main process, db-reader worker, and renderer (via existing lag IPC); each stall logged with start gap, duration, end op, and live counters. The watchdog itself never blocks because it only reads atomically.
  • HTML parser worker pool (4–8 threads, sized to cpus() − 2, clamped [2, 8]) — cheerio parsing + link extraction now runs on dedicated worker threads per fetchAndProcess call. The 12–26 s "fetch" stalls observed on large category / store-listing pages drop to <100 ms because the main thread no longer holds the JS event loop during parse.
  • DB writer worker thread — every per-URL hot-path write (upsertUrl + headers + body snapshot + links + images) is shipped as a single writeFetchedUrl payload to a worker-thread SQLite connection. Main thread stops blocking on .run() for the duration of writes. Atomic visibility — readers can never see a URL row without its links.
  • Atomic writeFetchedUrl batch method in ProjectDb — replaces the legacy two-step "upsertUrl then runInTransaction" sequence with a single transaction. Halves the IPC round-trips per URL and one fsync instead of two.

Changed

  • Production launcher in the start .bat — npm run dev (electron-vite cold-start, ~25 s) replaced with npm --workspace apps/desktop run start against the production bundle (1–2 s). Auto-builds the desktop app on first launch and when out/ is missing.
  • Cooperative recomputeUrlsIssuesYielding — the post-crawl materialise-issues phase now yields between each of the 70+ INSERT…SELECT definitions, dropping the 22-26 s main-thread block to a stream of <500 ms transactions with the UI staying responsive throughout.
  • Periodic in-crawl issue recompute uses the yielding variant too — the 30 s sidebar-counter tick no longer freezes the renderer mid-crawl. In-flight ticks dropped if a previous one is still running.
  • PRAGMA busy_timeout = 10000 on the writer connection (5 s on read-only) — the new writer worker coexists cleanly with the main-process writer when both happen to want the SQLite lock at the same moment, instead of throwing SQLITE_BUSY: database is locked (seen when starting a new crawl while the previous one was mid-materialise).
  • rAF-throttled progress dispatch in the renderer — setProgress now coalesces multiple progress events arriving within a single animation frame into one React update. TopBar / StatsBar / OverviewSidebar moved to scalar Zustand selectors so a counter that didn't change skips the full re-render.
  • buildTree + TreeNode memoised in OverviewSidebar — 150-node tree no longer rebuilds + reconciles on every progress event.
  • getPendingInternalLinks({ excludeNofollow }) — drain loop and hydrateFromDb now both filter out URLs reachable only via rel="nofollow" links when followNofollow is false, matching the live link-follow path.
  • Crawler.stop() clears the queue-checkpoint and issue-recompute timers immediately — Clear no longer races against a 30 s timer that re-populates crawl_queue after the wipe.
  • ProjectDb.reset() now wipes crawl_queue + the IPC crashRecoveryDiscard handler explicitly clears the on-disk queue when the user dismisses the recovery prompt — fixes a "Pending URLs: N" prompt that kept reappearing across launches even after Clear.
  • Reader pool heavy-method timeout raised to 60 s for getOverviewCounts (default 30 s for everything else) — eliminates reader-timeout > 15000ms warnings during materialise-issues phase contention.

Fixed

  • Multi-row aggregation also reads cell selection — picking 4 URLs via cell-clicks (Selected Cells: 4) now aggregates correctly; previously only Row-column picks (Selected Rows) were mirrored.
  • First-launch 25 s freeze — Vite dev cold-start replaced with prebuilt bundle (see Changed).
  • Click-induced 3-4 s "Yanıt Vermiyor" stalls during crawls — eliminated by the parser pool + writer worker + render-pressure reductions; debug.txt should now show no [STALL:MAIN] events on a typical 5 k-URL crawl.
  • Recovery-prompt false positives after Clear — see Changed.
  • Sitemap discovery skipped: database is locked when starting a crawl while the previous one is in post-crawl materialise — fixed by busy_timeout PRAGMA.
  • reader-timeout: queryUrls > 15000ms during post-crawl recompute — default reader timeout raised, materialise phase now yields cooperatively.

[0.2.6] — 2026-04-29

Added

  • Read-only worker thread pool — every read-heavy IPC handler (urlsQuery, overviewGet, imagesQuery, urlDetailGet, brokenLinksQuery, summaryGet, all 14 reports*) now runs on a dedicated node:worker_threads Worker that holds its own read-only SQLite connection against the same WAL file. Crawler writes on the main thread no longer contend with UI SELECTs. Auto-restart up to 3× per minute on worker crash; transparent fallback to the main-thread DB if the worker is unhealthy.
  • Materialised issue counters (urls_issues table, migration v42) — heavy O(n²) issue counters (Dead External Domain, Duplicate URL post-norm, Canonical Chain Multi-hop) are now materialised once per crawl by recomputeUrlsIssues and read via a single GROUP BY instead of correlated subqueries on every sidebar tick. Periodic recompute every 30 s during crawl + final pass on done.
  • Live performance meter in the status bar — FPS, JS heap (MB), and main-thread input lag (ms) update at 10 Hz with colour-coded thresholds. Lag is also piped back to the crawler so it can self-throttle.
  • Adaptive crawler concurrency — when renderer input lag exceeds 200 ms, Crawler.reportRendererLag() shrinks maxConcurrency by 1 (floor 1); when lag drops below 30 ms it grows back toward the user-configured ceiling. 2-second cooldown prevents oscillation. Runs autonomously — low-end machines stay responsive without the user having to tune any setting.
  • 3-tier resilient DNS resolver (kept from 0.2.4) extended with hot-swappable hooks for crawl-scoped diagnostics in the Logs panel.
  • 2 new HTML signals + 5 new issue filters — js_only_links_count (JS-Only Navigation), text_code_ratio (Low Text/Code Ratio <10%), Render-Blocking Head >20 (critical tier), OG/Twitter Image >5MB (HEAD-probe based). Migrations v40, v41.
  • 3 new Reports — URL Length Histogram, Word Count per Directory, Sitemap Orphans (Top 1000). Reports menu now lists 19 reports.
  • macOS .dmg in every release — workflow matrix [windows-latest, macos-latest] produces both .exe (x64) and .dmg (Apple Silicon arm64 + Intel x64) on every tag push.

Changed

  • DB write coalescing — per-URL fan-out (URL row + headers + body snapshot + 50–500 links + 5–50 images) is now wrapped in a single runInTransaction block. Each BEGIN…COMMIT is one fsync; previously a single page produced 5–10 fsyncs. On low-end SSDs with antivirus realtime-scan this halves per-page latency.
  • Cooperative setImmediate yield in the crawler hot loop — fetchAndProcess yields to the Node event loop before each URL so renderer IPC, lag heartbeats, and progress listeners interleave with crawler work instead of waiting for batches.
  • IPC handler setImmediate wrapper — read-heavy handlers yield once before running their SQL; combined with the worker pool this keeps click → response under one frame even on a saturated main thread.
  • Crawl-aware UI polling — Overview Sidebar / Broken Links / Images tab polling intervals are 3 s during a running crawl, 30 s when idle. Sidebar additionally refetches on every 50-URL crawl-progress bucket (push-style invalidation).
  • requestIdleCallback wrapping for sidebar + lazy-row loaders so SQL only fires when the renderer's main thread has idle slack.
  • Progress event throttling — crawler caps progress emit to 5 Hz (200 ms) with trailing emit, dropping IPC volume from ~200 msg/s to 5 msg/s during high-throughput crawls.
  • Statement cache — the 130+ SELECT COUNT(*) WHERE … clauses in getOverviewCounts are now compiled once per process and re-executed; SQLite parser cost amortised across ticks.
  • Logs window — fixed cannot start a transaction within a transaction error caused by nested BEGIN inside the per-URL coalesce block (setUrlHeaders / insertLinks / insertImages now respect the outer transaction).
  • Reader pool node:sqlite compatibility — fixed TypeError: The "options" argument must be an object on Node 24 by switching the writer connection to single-arg form and only passing { readOnly: true } for the worker.

Fixed

  • UI kasma during 2k+ URL crawls — combination of write coalescing, worker thread reads, statement cache, materialised counters, and cooperative yield brings sidebar tick from ~150 ms → <5 ms and renderer Lag from 200 ms → <30 ms (p99) on commodity hardware.
  • Sidebar issue counters showing 0 for Dead External Domain / Duplicate URL post-norm / Canonical Chain Multi-hop — replaced placeholder zeros with materialised counts.

[0.2.5] — 2026-04-29

Added

  • macOS .dmg installer in every release — release workflow is now a [windows-latest, macos-latest] matrix; one tag push fans out into both jobs and uploads .exe (NSIS, x64) and .dmg (Apple Silicon arm64 + Intel x64) to the same GitHub release. macOS DMG is currently unsigned — first launch shows a Gatekeeper warning, the user right-clicks → Open once and the app runs normally.
  • 2 new Reports — URL Length Histogram (6 buckets: ≤75 / 76–115 / 116–200 / 201–500 / 501–2048 / >2048; thresholds match SERP-snippet comfort zones) and Word Count per Directory (avg word count + page count grouped at depth 1–4; spots thin-content site sections). Reports menu now lists 18 reports.
  • 1 new Report — Sitemap Orphans (Top 1000) lists each URL declared in <urlset> but never reached by the crawl, alongside <lastmod> and source sitemap so the user can decide stale-vs-genuinely-orphaned. Reports menu now lists 19 reports.
  • 7 new issue filters — Internal Link → Redirect (page links to an internal 3xx target — wastes crawl budget), H1 = Title (lazy CMS copy-paste), Description = H1 (same lazy pattern, different copy direction), Dead External Domain (page links to an external domain whose crawled pages are ≥80% broken across ≥3 attempts), Duplicate URL (post-norm) (URL collides with another after lowercase + query-strip + trailing-slash strip), Canonical Chain (Multi-hop) (Page A canonical → B, B canonical → C — two-level EXISTS subquery catches deeper chains too), Slow-Loading Image (>200 KB image on a page that hasn't applied lazy-loading to every image — LCP killer on mobile).

Changed

  • CI release pipeline — single build job replaced by a strategy matrix; both Windows and macOS runners install deps, build shared packages, run their platform's electron-builder target, upload artifacts, and append to the same release via softprops/action-gh-release. Public-repo runners are free across all OSes so this carries no cost.

[0.2.4] — 2026-04-28

Added

  • Automatic 3-tier DNS bypass — crawls now keep working on machines with broken system DNS, with zero user action required. New resilient resolver cascades through (1) Node OS lookup → (2) direct UDP to public DNS servers (1.1.1.1, 1.0.0.1, 8.8.8.8, 9.9.9.9) → (3) DNS-over-HTTPS to Cloudflare / Google over port 443. Tier 3 connects to IP literals with SNI override + custom checkServerIdentity, so it works even when port 53 is fully blocked (Pi-hole, AdGuard, restrictive firewall, broken VPN). Solves the EDESTRUCTION queryA / ECONNREFUSED queryA failures that previously stopped crawls at 1 URL on misconfigured Windows / macOS / Linux machines. After 3 OS-DNS failures within 60 s, Tier 1 is auto-skipped globally so a sustained outage doesn't pay the per-host failure tax.
  • DNS bypass visibility in Logs — when the cascade falls back to Tier 2 or Tier 3, a single warn entry is emitted per crawl ("DNS bypass active: system resolver unavailable, falling back to public DNS …"). Subsequent per-host lookups stay at debug level so the log panel doesn't flood.

Changed

  • Logs window performance — major optimisation pass: virtualised list (only ~20 visible rows mounted), 250 ms render coalescing in renderer + 100 ms batch coalescing in main process, 200-entry ring buffer (full history persisted to disk), useDeferredValue for filter / level changes, memoised rows with strict comparator, CSS contain: strict on the scroller, drag/resize busy-flag pauses live updates, backgroundThrottling: false so logs flow even when window is hidden, parent-window decoupling so the Logs window no longer competes with the main window for DWM compositor time.
  • Disk-persistent logging — every log entry is now also written to <userData>/logs/freecrawl-<ISO>.log (rotated at 25 MB, 10 files retained). Help → "Open Logs Folder" reveals the directory. Logs survive crashes and exceed the 200-entry in-memory tail.
  • Single-instance lock — only one FreeCrawl can run per machine; launching a second instance refocuses the existing window. Eliminates Chromium GPU cache Erişim engellendi (0x5) / Gpu Cache Creation failed: -2 errors caused by two processes racing for the same cache directory on startup.
  • Diagnostic popup messaging rewritten — DNS popups no longer recommend "restart Windows DNS Client" (the new resolver does that for you). They now only fire when ALL THREE DNS layers failed, which means the real diagnosis is "no internet" or "antivirus blocking everything", not a fixable DNS quirk.
  • Polling intervals reduced — Overview sidebar 1500 ms → 3000 ms (with in-flight coalescing), Broken Links / Images tabs 1500 ms → 3000 ms, lazy URL rows live-refresh 250 ms → 750 ms. Cuts background IPC volume by ~60 % during crawls.

Fixed

  • fetch failed -> EDESTRUCTION queryA / ECONNREFUSED queryA errors — the underlying cause (Windows DNS Client mid-query crash, port-53 blocked by VPN/firewall, antivirus DNS hijacking) is now bypassed automatically by the resilient resolver instead of failing the crawl.
  • Logs window kept freezing the entire app after a crawl finished — post-crawl SQL passes (inlinks recompute, redirect chains, hreflang reciprocity, duplicates, image probes, TLS probes) now yield to the Node event loop between phases via setImmediate, so the IPC channel stays live and the renderer doesn't stall.
  • Logs window stuttered during drag/resize — busy-flag from main process pauses renderer state updates during window manipulation; React startTransition lets the compositor preempt log applications.
  • formatFetchError DNS messages — updated to reference the automatic 3-tier fallback ("automatic DNS-over-HTTPS fallback active") instead of asking the user to manually restart services.

[0.2.3] — 2026-04-28

Added

  • Diagnostic popup dialogs — when a crawl fails for an environment-specific reason (DNS port refused, DNS resolver crashed / EDESTRUCTION, TLS certificate inspection by antivirus / proxy, unreachable seed URL), a native modal opens with a clear explanation, step-by-step fix (services.msc → DNS Client restart, switch to 1.1.1.1, set NODE_EXTRA_CA_CERTS, …), an "Open Logs" button, and a "Don't show this again" checkbox that persists per-category. Site-specific failures (404 / WAF / timeout) stay in the log panel only.
  • Help → Reset Diagnostic Warnings — re-enables every "Don't show again" checkbox the user previously dismissed; reports how many warnings were re-enabled.

Fixed

  • DNS-layer failures misattributed to HTTP errors — formatFetchError now recognises Node DNS error patterns (queryA / queryAAAA / queryMx / …) and surfaces DNS-specific hints. ECONNREFUSED queryA is no longer misread as "host refused connection" — it correctly identifies the local DNS resolver / VPN / Pi-hole / firewall as the culprit and recommends switching DNS to 1.1.1.1 / 8.8.8.8.
  • EDESTRUCTION errors had no diagnostic hint — now mapped to "Windows DNS resolver crashed mid-query — restart the DNS Client service".

[0.2.2] — 2026-04-28

Added

  • 50+ new SEO issue checks — analytics coverage (GA4 missing / multiple / legacy UA / pixel-without-policy), large images (>200 KB), SSL/TLS cert (expired / expiring ≤30 d / weak signature / old protocol), HSTS quality (no preload / short max-age / no includeSubDomains), anchor text (too long / generic), form accessibility (unlabeled inputs), lazy-loading missing on images, broken <img src>, target="_blank" without rel="noopener", empty pages, OG/Twitter/canonical absolute-URL checks, description equals title, single-word title, external-links-too-many (>100), zero outlinks.
  • 6 new sub-tabs in URL Details panel — Outline (heading hierarchy), Images, Resources, Extracted Data, Cookies, Structured Data — alongside existing Details / Inlinks / Outlinks / SERP / Headers / Source.
  • SSL/TLS certificate audit — post-crawl TLS handshake probe per HTTPS host stores cert validity / issuer / subject / signature algorithm / protocol in host_certs; powers 4 SSL issue filters and a TLS panel in the Details view.
  • Image weight probe — post-crawl HEAD pass on internal images persists byte_size; powers the "Large Image" issue and the new Image-Weight-Per-Page report.
  • 7 new Reports — Analytics Coverage, Link Positions, Image Weight Per Page, Inlinks Histogram, Word-Count Histogram, Server Headers, plus existing entries — Reports dialog now lists 16 reports.
  • Document outline — heading hierarchy (up to 200 entries) captured per page, surfaced in the new Outline sub-tab.
  • Server header capture — Server response header stored per URL; powers the Server Headers report and a row in the URL Details panel.
  • Drag & drop list import — drop a .txt / .csv / .list file onto the app to populate List mode and start a crawl in one motion.
  • Custom robots.txt in tester — Robots.txt Tester dialog accepts a pasted or file-loaded custom robots.txt body so you can verify rules before deploying them.
  • CLI --config and --json flags — layered config (defaults → file → flags) for CI; --json emits a machine-readable summary to stdout.
  • Detailed network diagnostics in Logs panel — every crawl now logs runtime info (Node / Electron / undici versions, OS), proxy state (config / env / none), CA bundle, TLS-validation flag, retry attempts, abort reasons, and 4xx / 5xx response interpretations (403 → bot/WAF, 429 → rate limit, 503 → server error). Failed fetches now surface in the Logs window with full root-cause chain — no more silent fails.

Changed

  • formatFetchError hint coverage — extended to UND_ERR_HEADERS_TIMEOUT (WAF / Cloudflare challenge), UND_ERR_BODY_TIMEOUT, ECONNRESET / EPIPE (antivirus / firewall TLS inspection), EPROTO / TLSV1_ALERT / WRONG_VERSION_NUMBER (TLS handshake), NGHTTP2_ / GOAWAY (HTTP/2 protocol error), AbortError. Each carries an actionable hint embedded in the log line.
  • README Features section condensed — long bulleted feature lists collapsed into a 10-line high-signal summary.

Fixed

  • Crawler hung in "Running" forever after an unreachable seed URL — start() now emits a done event and clears running when resolveStartUrl returns null, with an explicit error message in the Logs panel.
  • Silent fetch failures — failed URL fetches were stored to the DB but never logged; users saw Crawl done: total=1 failed=1 with no clue why. The fetch catch path now emits an error (seed URL) or warn (any other URL) entry with the full diagnostic chain.

[0.2.1] — 2026-04-27

Added

  • 30+ new issue checks — H1 Empty, H1 Too Long (>70), Multiple <title> Tags, Title Pixel Width Truncated (>600 px Arial 18), Title Placeholder ("Untitled" / "Default" / "Page N"), Meta Description Pixel Width Truncated (>990 px), Fragment in URL, Spaces in URL, Long Query String (>100 chars), Folder Depth >4, Image Empty Alt, Empty Anchor Text, Apple Touch Icon Missing, Web Manifest Missing, RSS/Atom Feed Missing, Insecure Form Action (HTTPS → HTTP), Missing SRI (3rd-party subresource), TTFB Slow (>600 ms), TTFB Very Slow (>1.8 s), Cookies Missing Secure / HttpOnly / SameSite, HTTP/2 Not Advertised, Render-Blocking Head Resources (>5), Keep-Alive Disabled.
  • View Source detail tab — every HTML page's raw body is captured during crawl into a sibling url_sources table (capped at bodySnapshotMaxBytes, default 1 MB; storeBodySnapshots config knob to disable). The new sub-tab in the URL Details panel renders the source with case-insensitive search + match highlighting (≤5K hits cap), a Wrap toggle, and Copy / Download buttons. Truncated badge surfaces when the body was clipped.
  • TTFB measurement — request-to-headers timing captured per successful attempt (retry overhead excluded) and stored as ttfb_ms. Powers the two new TTFB issue filters and a new "TTFB (ms)" row in the URL Details panel.
  • Cookie security analysis — Set-Cookie response headers are split RFC-6265-correctly (Expires-date safe), security flags counted per page (cookies_count, cookies_insecure, cookies_no_httponly, cookies_no_samesite). Cookie values are never stored; only the per-flag counts. Three issue filters surface them.
  • HTTP/2 detection — best-effort heuristic via Alt-Svc header (h2= / h3= advertised → HTTP/2 / HTTP/3 capable). Stored as http_protocol; "HTTP/2 Not Advertised" issue surfaces origins still on HTTP/1.1.
  • Render-blocking + keep-alive detection — html-parser counts <head> <script src> (no async/defer/type=module) + <link rel=stylesheet> (excl. media=print) → render_blocking_count. Crawler captures Connection: close → keep_alive flag.
  • Microdata + RDFa structured-data — [itemscope] and [typeof]/[vocab]/[property] counted alongside JSON-LD; the "No Structured Data" issue now triggers only when ALL three formats are absent (no more false positives on Microdata-first sites).
  • Apple Touch Icon, Web Manifest, RSS/Atom feed detection — <link rel="apple-touch-icon"> (incl. legacy -precomposed), <link rel="manifest">, <link rel="alternate" type="application/rss+xml|atom+xml"> URLs absolute-resolved and surfaced in the URL Details panel + sidebar issue filters.
  • Pixel-width estimation for title + meta description — per-character Arial 18 px width table approximates Google SERP truncation (600 / 990 px thresholds); replaces the previous client-side approximation that drove the URL Details panel.
  • Bulk Export menu — File → Bulk Export… opens a folder picker, then writes ~22 curated CSVs (Internal HTML / All, External All, 2xx / 3xx / 4xx / 5xx, Indexable / Non-Indexable, Title / Meta / H1 / Canonical Issues, Pagination Broken, Mixed Content, Insecure Form Action, Hreflang Reciprocity, Sitemap Crawled-Not-Listed, Image Missing Alt, Near-Duplicate). 0-row files auto-deleted; concludes with "Open Folder" prompt.
  • Sitemap Validator dialog — Help → Sitemap Validator… fetches a sitemap URL, walks nested sitemap-index entries up to depth 3 / 100K URLs, shows tried/parsed/error counts + <lastmod> samples + protocol findings. Tolerant input (bare hosts auto-prefixed with https://).
  • 6 new Reports — Slowest URLs, Most-Linked URLs, Most-Outlinking URLs, Biggest Pages, Deepest URLs, External Domain Health (per-host success/error rollup with avg response time + error-rate %). Brings total to 10 reports in the Reports dialog.
  • Recent Projects — File → Open Project… (Ctrl+O) and File → Open Recent submenu (last 10 projects, persisted; bad entries auto-pruned; "Clear Recent" command). Save Project As… now also pins the saved file as the active project.
  • Settings preset profiles — Settings → Presets: one-click Fast / Thorough / Mobile-only Googlebot / Desktop-only Googlebot / Aggressive. Apply only writes affected fields; URL list, custom rules, filters, and extraction rules are preserved.
  • Settings Import / Export — Settings → Presets → Export… / Import… buttons. JSON envelope {format, version, exportedAt, config}. Bare CrawlConfig fragments accepted; unknown fields warn-and-skip.
  • CLI subcommands — freecrawl validate-sitemap <url>, freecrawl audit-robots <url>, freecrawl compare <before.seoproject> <after.seoproject>. Each returns a CI-friendly exit code (0 / 1 / 2).
  • Settings → Speed dedicated panel — pulls Max Concurrency / Max URL/s / Per-Worker Delay / Retry knobs out of the generic Crawler section. Live "Effective ceiling" banner + worst-case retry-delay math. Throughput tips at the bottom.
  • Visualization tuning popover — gear icon next to Reload opens 5 sliders (node size, repulsion, edge length, cluster spacing, edge opacity). Persists to prefs across sessions; live preview; Reset + Re-run-layout buttons.

Changed

  • Force-Directed visualization defaults rebuilt — node radius 6–24 px (down from 8–48), tuned cose layout (1M repulsion, 400 px ideal-edge, 0 gravity, 5000-px boundingBox) so hub-spoke topologies fan out instead of collapsing into a tight ball. Default node count 150 (was 500).
  • Visualization labels hidden by default — new "Labels" mode (Hover Only / Top 20 / All). Hover highlights the node + its closed neighbourhood; non-neighbours fade to 25% opacity. Click selects (persists until empty-canvas click); double-click on a node opens its URL.
  • Visualization label rendering — switched from cytoscape's built-in (zoom-scaled, illegible at low zoom) to a fixed-size HTML overlay positioned via node.renderedPosition(). Stays at 12 px regardless of zoom level / display DPI.
  • Robots.txt Tester accepts bare hosts — gamesatis.com, www.example.com/foo, //host/path are auto-prefixed with https://. Same normalisation in the CLI's audit-robots.
  • CSV exporter accepts a category filter — exportUrlsToCsv(db, path, { category }) walks iterateUrlsByCategory directly, replacing the old "all rows" behaviour for selection-less exports. Underpins Bulk Export.
  • OverviewSidebar sections expanded to ~100 issue filters — new groups: Cookies (Missing Secure / HttpOnly / SameSite), PWA / Discovery (Apple Touch / Manifest / Feed). Existing groups (Title, H1, URL, Performance, Security Headers, Images, Links, Structured Data) gained 1–4 entries each.
  • Settings dialog grew to 14 sections — added Presets and Speed sections; preset application + JSON import/export inside Presets.
  • Body snapshots auto-stored during crawl — every HTML page's raw response now goes into url_sources so View Source works without re-fetching. Disable via storeBodySnapshots: false to save disk on snapshot-free runs.

Fixed

  • Clear button stuck disabled after crawl completion / Open Recent — Clear is now enabled whenever any of progress.discovered, progress.crawled, summary.total, or overview.summary.totalInternalUrls / totalExternalUrls is non-zero. Previously it only checked the live progress counters, which were reset to 0 in the final emitProgress.
  • SyntaxError: Unexpected token '??' on Electron startup — http-client.ts mixed || and ?? without parentheses (illegal per ES2020). Refactored to compute the env-proxy chain into a helper variable first.
  • Robots.txt Tester rejected hostnames without scheme — bare hosts now auto-resolve to https://<host>/robots.txt.

Removed

  • Developer Tools menu item + keyboard shortcuts — View → Developer Tools entry removed. F12 / Ctrl+Shift+I / Ctrl+Alt+I / Ctrl+Shift+J / Ctrl+Shift+C swallowed via before-input-event. Belt-and-braces devtools-opened hook closes them if anything else opens them programmatically. Applied to both main + Logs windows.

[0.2.0] — 2026-04-26

Added

  • Near-duplicate / exact duplicate content detection — every crawled page's body text is fingerprinted with a 64-bit Charikar SimHash over 3-shingles. Post-crawl, a band-based LSH (4 × 16-bit) + Union-Find clustering pass groups pages within a configurable Hamming threshold (Settings → Duplicates; default 3 ≈ 95% similarity, "Only cluster indexable pages" toggle). Surfaces as the Near-Duplicate Content issue plus Cluster ID / Cluster Size columns on the Content tab. Duplicate Content (exact) issue layered on top via FNV-1a content-hash collisions.
  • Hreflang full analysis — recomputeHreflangAnalysis validates BCP-47 / x-default codes, computes self-reference, reciprocity (against the in-crawl hreflang graph), and target health. Four new Hreflang issues: Invalid Code, Self-Ref Missing, Reciprocity Missing, Target Issues (non-200 / noindex / canonical-away targets).
  • Sitemap multi-file split + gzip + image / hreflang variants — exporter auto-shards >50K-URL outputs into <base>-N.xml parts under a <sitemapindex> wrapper; gzip: true writes .xml.gz; variant: 'image' emits <image:image> blocks (Google Images, max 1000/page); variant: 'hreflang' emits <xhtml:link rel="alternate" hreflang> siblings inside each <url>. Built-in validateSitemap checks URL count / file size / RFC 3339 lastmod.
  • Sitemap diff filters — Crawled-Not-In-Sitemap (orphan candidate from sitemap perspective), Redirect in Sitemap (3xx specifically, distinct from non-200), plus a sitemapNotCrawled count for entries the crawl never reached.
  • HTML standalone audit report — File menu → "Export HTML Report…": single-file print-ready report with KPI cards (URLs / Indexable / Avg Response / Total Bytes), severity-ranked Issues table covering 56 issue types, and Top-25 Slowest / Deepest / Outlink-Heavy URL tables. No external assets — emailable / archivable as-is.
  • Webhook on crawl completion — Settings → Webhook: any URL receives a single POST with crawl summary JSON when the run finishes. 10 s timeout, fire-and-forget so a misconfigured Slack/Zapier endpoint can't break crawl teardown. Status + latency surface as info events.
  • Custom Extraction (CSS + Regex) — Settings → Custom Extraction: up to 10 user-defined rules per project. CSS rules (cheerio-driven, reuses the loaded DOM) support text / attribute / inner_html / outer_html / count outputs; regex rules (JS RegExp /g with infinite-loop guard) support whole-match / capture-group-1 / count. Multi-match modes: first / last / all (JSON array) / concat (| joined) / count. Per-rule failures are isolated. Results stored in a single JSON column, surfaced in the URL Details panel as Extract: <name> rows and included in CSV / JSON exports.
  • Compare with Project (Compare/Diff Mode) — File menu → "Compare With Project…" opens a .seoproject and produces a 9-category diff: Added (URLs in B not A), Removed (URLs in A not B), and field-level changes for Status / Title / Meta / H1 / Canonical / Indexability / Response Time (Δ ≥500 ms threshold). Modal shows per-category counts in the sidebar + colour-coded before/after diff table; samples capped at 5K per category for memory.
  • Site architecture visualization (Ctrl+G) — View → Visualization opens an interactive Cytoscape graph of the internal link structure. Top-N nodes by inlinks (200 / 500 / 1K / 2K / 5K cap), edges between them. Four layouts: Force-Directed (cose), Tree (BFS), Circle, Concentric. Three colour modes: By Status (2xx green / 3xx amber / 4xx orange / 5xx red), By Depth (bluescale), By Indexability. Log-scaled node sizing by inlinks. Hover tooltip surfaces full URL.
  • Anchor-text word cloud — sidebar of the Visualization dialog ranks the top 120 internal-link anchors by frequency with log-scaled font sizing across the cloud.
  • HTTP Basic + Bearer authentication — Settings → Authentication. Adds Authorization: Basic <base64> or Authorization: Bearer <token> to every request. User-supplied custom-header Authorization still wins for advanced overrides.
  • Per-project proxy URL override — Settings → Network. Takes precedence over HTTPS_PROXY / HTTP_PROXY env vars when non-empty; same syntax (http://user:pass@host:port).
  • File-extension exclude filter — Settings → Network → "Exclude extensions". Comma-separated list (pdf, jpg, png, woff2, …); URLs whose path ends in any of these are dropped at enqueue time. Start URL exempt; query strings ignored.
  • Configurable max redirect hops — Settings → Network → "Max redirect hops" (default 10). Each 3xx is still recorded as its own URL row, but the chain stops being followed beyond N hops.
  • Manual URL injection during crawl — TopBar Add URL button (only visible while running). Clears the seen-flag for re-crawl semantics; respects robots / include-exclude / queue cap.
  • Save Project As… (Ctrl+Shift+S) — File menu → atomic SQLite VACUUM INTO snapshot of the live crawl into a .seoproject file. WAL-consistent unlike a plain file copy.
  • OS notifications — Electron Notification toasts when a crawl completes while the main window isn't focused. Gracefully degrades on Linux distros without a notification daemon.

Changed

  • Settings dialog grew to 12 sections — added Custom Extraction, Authentication, Network, Duplicates, Webhook entries to the existing Mode / Crawler / Requests / Include-Exclude / Custom Search / URL Rewriting / Hardware. Sidebar search filter covers all of them.
  • OverviewSidebar issue count rose from ~60 to ~70 — adds a new Content group (Thin Content / Near-Duplicate / Duplicate Content) plus the four new Hreflang and two new Sitemap issues.
  • Sitemap exporter API expanded — exportSitemap(db, path, opts) now accepts variant / gzip / splitAtUrlCount and returns { files: string[], urlsWritten, truncated, sharded } so callers can surface every part file.

[0.1.10] — 2026-04-26

Changed

  • README rewritten to match current capability surface (v0.1.9) — feature list synced with the post-0.1.4 reality: 1M-URL target, ~60 issue categories (was 12), full Settings dialog inventory, Hardware throttling section, recent-URLs dropdown, sitemap auto-discovery, list mode, custom search, URL rewriting, JSON export, robots.txt tester, reports dialog, in-app logs, [i] info tooltips on every settings field and table column header, live-streaming UX (~1 s first row, 250 ms refresh), pause/resume, retry/backoff, HTTPS_PROXY support, Happy Eyeballs, mixed-content scan, security-header audit, JSON-LD / OpenGraph / Twitter Card / hreflang / pagination extraction, redirect-chain resolution.
  • Added freecrawl.net website link — surfaced in the README header and a new Links section.

[0.1.9] — 2026-04-26

Added

  • [i] info tooltips on every Settings field — every input/select/checkbox in the Settings dialog now has a hoverable info icon next to its label. Tooltip surfaces a one-line description plus a concrete "Example" value so the user understands what each setting does without leaving the dialog. Covers all 26 fields across Mode, Crawler, Requests, Include/Exclude, Custom Search, URL Rewriting, and Hardware sections.
  • [i] info tooltips on every table column header — every column on the Internal/External/Response Codes/URL/Page Titles/Meta Description/H1/H2/Content/Canonicals/Directives/Links views (35 columns total) shows an info icon on hover with a description + example value. Same treatment applied to the Images and Broken Links views. Uses a new shared InfoTip component so settings and tables share styling.

Changed

  • First row appears in ~1 s instead of ~3-4 s after Start — sitemap discovery (fetchSitemaps) is now fire-and-forget, no longer blocking the start URL from being enqueued. loadRobots (robots.txt fetch) is also fire-and-forget — the robots check is fail-open until the file loads (typically <500 ms, well before the first fetched page emits its outlinks). Both promises are awaited at end-of-crawl so post-crawl recomputeInlinks and sitemap-derived issue filters see the full data set.
  • resolveStartUrl rewritten as a single auto-follow fetch — gamesatis.com previously took ~2-3 s (HEAD probe + manual redirect: 'manual' hop-by-hop GET chain over 1-2 redirects). Replaced with a single fetch(..., { redirect: 'follow' }) call that lets undici drive the redirect chain at the network layer; typical resolution drops to ~300-800 ms. Probe timeout lowered from 5 s to 3 s.
  • Live URL-table refresh cadence dropped from 1500 ms to 250 ms — at 20 RPS the user previously saw ~30 rows arrive in a single 1.5 s lump (felt like the program had stalled). Now ~5 rows arrive every 250 ms, giving a continuous "streaming" feel. Added a leading tick (fires immediately on mount, no 1.5 s dead-window after Start) and an inFlight guard that coalesces overlapping ticks at the new cadence.

Fixed

  • Stop → Start "pır pır" / flicker eliminated — when Stop was pressed during a crawl, the in-flight sitemap fetch (5+ s on a 20k-URL sitemap) and the queued done event from the just-stopped crawler kept firing into the next crawl's UI, producing rapid Running ↔ Done state flips. Fixed by (1) tracking the sitemap fetch's AbortController on the crawler instance and aborting it from stop(), (2) gating all done emits behind if (!this.stopped) in spider/list/early-exit paths, and (3) gating the main process IPC forwards by activeCrawler === crawler so a zombie crawler's late progress / done / error / info events never reach the renderer.

[0.1.8] — 2026-04-26

Added

  • Canonical completeness — 4 new issues: Canonical Missing (HTML 2xx with no canonical declared anywhere), Self-Referencing Canonical filter, Canonicalised (canonical points elsewhere), HTTP vs HTML Mismatch (the document's <link rel="canonical"> and the response's Link: …; rel="canonical" header disagree). New canonical_http column captures the HTTP-header canonical (RFC 8288 angle-bracket-aware parsing).
  • Meta Refresh detection — meta_refresh + meta_refresh_url columns extract <meta http-equiv="refresh" content="…">. New issue Document → Meta Refresh Used flags any HTML page using meta-refresh (Google recommends 301 instead).
  • Charset detection — charset column populated from <meta charset>, then legacy <meta http-equiv="Content-Type">, then HTTP Content-Type header charset= parameter. New issue Document → Charset Missing for HTML 2xx with no declared charset anywhere.
  • Settings dialog redesign — left-sidebar category nav (Mode, Crawler, Requests, Include/Exclude, Custom Search, URL Rewriting, Hardware) with searchable filter; breadcrumb header; per-category right-pane content. Wider modal (920×80vh).
  • Settings entry in File menu (Ctrl+,) — opens the Settings dialog from the menu bar in addition to the gear button.
  • Recent URLs dropdown — focusing the URL input shows the last 5 crawled URLs as a dropdown (persisted across launches). The URL bar always starts empty on launch.
  • Hardware section in Settings — Memory soft limit (MB) auto-pauses the queue when the crawler's RSS exceeds the cap and resumes at 80% of it; Max in-memory queue size drops new discoveries beyond the cap (back-pressure on fan-out bursts); Process priority (Normal / Below Normal / Idle) sets the OS scheduler hint so the machine stays usable during heavy crawls.
  • Crawler info event channel — non-error status messages (e.g. successful sitemap parse summaries, memory monitor pause/resume, priority-set acks) are now emitted as info events and logged at info level, no longer polluting the error log.

Changed

  • Default maxUrls raised from 100k to 1,000,000 — supports large-site audits out of the box. Existing users keep their saved value (defaults merge under saved preferences).
  • recomputeInlinks rewritten as one-pass aggregate — switched from a correlated (SELECT COUNT…) subquery (N×M lookups, minutes at 1M URLs) to a temp-table GROUP BY links.to_url followed by an indexed JOIN; finishes in seconds at the same scale.
  • recomputeRedirectChains memory fix — now snapshots only rows where redirect_target IS NOT NULL instead of the full urls table (~100 MB saved at 1M URLs).
  • Sitemap entry cap follows maxUrls — the sitemap fetcher's hard 50k limit is now Math.max(50_000, config.maxUrls), so 1M-URL crawls can ingest the full sitemap.
  • Crawler dedup sets released after crawl ends — seen and externalSeen are cleared once the queue is drained, releasing ~80–120 MB of string heap on big crawls.
  • URL bar starts empty on launch — previous start URL is no longer auto-restored; the recent-URLs dropdown surfaces history instead.

[0.1.7] — 2026-04-25

Added

  • Multiple Canonicals detection — canonical_count column tracks the number of <link rel="canonical"> tags on the page (previously only the first was captured). New issue Canonicals → Multiple Canonicals flags pages with more than one canonical (Google may pick any of them, defeating the canonical's purpose).
  • Canonical → Non-200 detection — new issue Canonicals → Canonical → Non-200 flags pages whose canonical URL was crawled and returned 4xx/5xx (uses an EXISTS join against the canonical's stored status code).

[0.1.6] — 2026-04-25

Added

  • Settings dialog (gear icon in TopBar) — every plumbed-through CrawlConfig field is now editable from the UI: max depth/URLs/concurrency/RPS, request timeout, crawl delay, retry attempts/initial backoff, follow-redirects, respect-robots, crawl-external, store-nofollow, discover-sitemaps, User-Agent, Accept-Language, custom HTTP headers, include/exclude regex patterns, custom search terms, URL rewriting (strip-www / force-https / lowercase-path / trailing-slash policy), List mode + URL list. Persisted to preferences.json, restored on next launch.
  • Sitemap auto-discovery + parser — at crawl start, robots.txt Sitemap: directives + /sitemap.xml + /sitemap_index.xml fallbacks are fetched, nested <sitemapindex> walked BFS (cap 50K entries, depth 3), entries persisted to a new sitemap_urls table. Two new issue filters: Non-Indexable in Sitemap, Non-200 in Sitemap. Toggle: discoverSitemaps (default on).
  • List mode — CrawlConfig.mode = 'list' fetches every URL in urlList exactly once with no link follow / robots / sitemap discovery. CLI --list <file> (one URL per line, # comments). Settings dialog has a Mode dropdown + URL list textarea.
  • Custom Search — case-insensitive literal substring counts in body text, configured via Settings or customSearchTerms config. Per-page hits stored as JSON in custom_search_hits; one Detail-panel row per term.
  • URL Rewriting — 4 opt-in toggles applied at every normalizeUrl call site (so the seen-set, redirects, link extraction, sitemap entries all dedupe consistently): Strip www, Force HTTPS, Lowercase path, Trailing slash policy (leave / strip / add — add is file-extension aware).
  • JSON export — streaming exporter dumps every captured field (security headers, structured data, hreflang JSON, pagination, custom search hits, redirect chain, …) for ~65 columns vs. CSV's 23. CLI --out *.json auto-detects format. Menu: File → Export Current View as JSON… (Ctrl+Shift+E).
  • Robots.txt Tester dialog — Help → Robots.txt Tester… opens a popup; enter a URL + UA, see fetched robots.txt status, allow/disallow verdict, declared sitemaps, crawl-delay, and the raw body (8 KB cap).
  • Reports dialog — new top-level Reports menu (Ctrl+R) opens a dropdown-driven analytics dialog: Pages per Directory (depth selector 1–4), Status Code Histogram (2xx/3xx/4xx/5xx/NET badges), Depth Histogram (BFS click-depth distribution), Response Time Histogram (6 buckets <100ms → >10s + No response row, OK/WARN/SLOW/ERR badges).
  • Heading hierarchy — h3_count / h4_count / h5_count / h6_count columns + new Skipped Heading Level issue (flags pages where a tier is missing — e.g. H1 → H3 without H2). Detail panel shows non-zero counts.
  • Full security header capture — Content-Security-Policy, Referrer-Policy, Permissions-Policy rounded out the response-header set (joining HSTS, X-Frame-Options, X-Content-Type-Options, Content-Encoding). New CSP Missing issue filter.

Changed

  • normalizeUrl signature gained an optional UrlRewriteOptions parameter. Existing call sites are unaffected (defaults are no-op); the crawler snapshots config rewrites once in the constructor and threads them through parseHtml so every URL the page declares is normalized identically.

[0.1.5] — 2026-04-25

Added

  • HTTP Headers tab in URL Details — every response header (lowercased, dedup'd, 4 KB cap) is now persisted to the headers table and rendered as a sortable name/value table for the selected URL.
  • JSON-LD structured data extraction — every <script type="application/ld+json"> block is parsed; @type values from arbitrary nesting (top-level, arrays, @graph containers, string-or-array @type) are collected into a sorted unique list. Block count + invalid-block count tracked separately. Two new issues: JSON-LD Missing, Invalid JSON-LD.
  • Pagination + hreflang extraction — <link rel="next"> / <link rel="prev"> and all <link rel="alternate" hreflang> entries are stored; hreflangs as JSON. Two new issues: Broken Next/Prev Target (joins to urls to find 4xx/5xx redirect targets), x-default Missing.
  • Mixed Content + AMP + Favicon detection — HTTPS pages are scanned for http:// subresources (img / script / iframe / video / audio / source / embed / stylesheet — anchors deliberately ignored). <link rel="amphtml"> and <link rel="icon"> (with legacy shortcut icon fallback) captured per URL. New issues: Mixed Content, Favicon Missing.
  • Security headers audit — Strict-Transport-Security, X-Frame-Options, X-Content-Type-Options, Content-Encoding captured from response headers. Three new issues: HSTS Missing (HTTPS pages only), X-Frame-Options Missing, X-Content-Type-Options Missing. Plus Compression Missing issue under Performance.
  • Twitter Card extraction — twitter:card / twitter:title / twitter:description / twitter:image (Twitter spec uses name= not property=). New issue Twitter Card Missing when both card+image are absent.
  • OpenGraph + viewport + lang extraction — og:title / og:description / og:image, meta[name=viewport], html[lang] per URL. Three new issues: OpenGraph Tags Missing (all three absent), Viewport Meta Missing, Lang Attribute Missing.
  • Meta extras — meta[name=keywords], meta[name=author], meta[name=generator], meta[name=theme-color] captured + shown in URL Details.
  • Redirect chain resolution — post-crawl recomputeRedirectChains() walks every redirect with cycle detection (visited-set + 50-hop hard cap), filling redirect_chain_length / redirect_final_url / redirect_loop. Two new issues: Redirect Loop, Long Chain (>3 hops).
  • URL structure analytics — 4 new URL-shape issues (Contains Uppercase, Contains Underscore, Multiple Slashes, Non-ASCII Characters) plus Many Query Params (>5), Self-Redirect, and Too Long (>2048 chars). folder_depth and query_param_count columns computed at upsert time.
  • Configurable crawler — customHeaders, includePatterns, excludePatterns (regex) added to CrawlConfig. Default headers merge case-insensitively with user overrides; include filter is opt-in (empty = all pass), exclude is always applied; start URL is exempt. CLI flags --header "K: V", --include <regex>, --exclude <regex>.

Changed

  • README.md — added a Prerequisites section detailing Node.js 22+ requirement, optional tooling, corporate-proxy / antivirus TLS guidance (HTTPS_PROXY, NODE_EXTRA_CA_CERTS), and disk/memory budget. Prebuilt installer users explicitly exempted from these requirements.

[0.1.4] — 2026-04-24

Added

  • Pause / Resume crawl controls in the top bar — in-flight requests finish naturally; queued work halts until Resume. Status bar shows an amber "Paused" indicator.
  • Retry with exponential backoff — transient failures (network errors, 408, 425, 429, 5xx) are retried up to retryAttempts times with doubling delay. Defaults: 2 retries, 500 ms initial backoff.
  • Crawl delay (crawlDelayMs) — optional per-worker politeness delay applied after each request, on top of the global RPS cap.
  • In-app Logs window — Help → Show Logs… (Ctrl+L) opens a live popup that streams every console message, warning, uncaught exception, and crawler event from app startup onward. 5 000-entry ring buffer, filter by level, search, Copy, Clear.
  • Fetch error diagnostics — the generic "fetch failed" message now walks err.cause and surfaces the real underlying reason (e.g. ENOTFOUND, UND_ERR_CONNECT_TIMEOUT, UNABLE_TO_GET_ISSUER_CERT_LOCALLY, ECONNREFUSED) with a contextual hint about corporate proxy / antivirus / DNS.
  • HTTPS_PROXY / HTTP_PROXY environment variable support via undici ProxyAgent — users behind corporate proxies no longer get silent ECONNREFUSED.
  • Happy Eyeballs (RFC 8305) — autoSelectFamily races IPv4/IPv6 so dual-stack hosts with a broken AAAA record don't stall the crawl.
  • SEO metadata extraction — every crawled HTML page now stores lang (html[lang]), viewport (meta[name=viewport]), and OpenGraph og:title / og:description / og:image. Shown in the URL Details panel.
  • 7 new SEO issue filters under the Overview sidebar's Issues group:
    • H1 > Multiple (h1_count > 1)
    • Response > Very Slow (>3 s)
    • Page > Large (>1 MB)
    • URL > Too Long (>2048 chars)
    • Accessibility > Lang Attribute Missing
    • Mobile > Viewport Meta Missing
    • Social > OpenGraph Tags Missing (all of og:title / og:description / og:image absent)

Changed

  • Nofollow links no longer stored by default (Screaming-Frog style "Respect Nofollow"). Links with rel="nofollow" are treated as hints for search engines only — they don't appear in the links table, don't count toward urls.outlinks, and external nofollow targets aren't HEAD-probed. Opt back in via storeNofollowLinks: true.
  • urls.outlinks now reflects the stored (followed) link count so the detail panel's Outlinks list stays consistent with the header count.

Fixed

  • node:sqlite ExperimentalWarning no longer appears as ERROR in the Logs window — classified as benign and suppressed (CLAUDE.md already acknowledged it as expected for this stack). The 'warning' event listener also disables Node's default stderr printer for us, so any future warnings flow through a proper severity classifier instead of being dumped to stderr.

[0.1.3] — 2026-04-24

Fixed

  • Release workflow — Windows build failed on GitHub Actions with "Cannot compute electron version from installed node modules" because npm workspaces hoist electron to the repo root, outside where electron-builder looks. Pinned electronVersion: 41.2.2 in electron-builder.yml to bypass the auto-detection.
  • Added --publish never to build:{win,mac,linux} scripts so electron-builder doesn't race against the softprops/action-gh-release step (also silences the implicit-publishing deprecation warning).

[0.1.2] — 2026-04-24

Added

  • GitHub Actions CI (.github/workflows/ci.yml) — typechecks and builds all workspaces on every push to main and every pull request (Ubuntu runner, Node 22).
  • Windows release automation (.github/workflows/release.yml) — pushing a v*.*.* tag triggers a windows-latest build of the NSIS installer via electron-builder and publishes it as a GitHub Release with auto-generated notes.
  • Launcher now builds workspace packages (tsc -b) before npm run dev, so fresh clones / ZIP downloads work without the "Cannot find module @freecrawl/..." error.

Changed

  • electron-builder.yml productName is now FreeCrawl SEO Tool (reflected in the installer filename and install directory).
  • Launcher refactored so all goto labels live outside (...) blocks (cmd.exe parses parenthesized blocks in a single pass, which was causing the window to close silently on some machines).

[0.1.1] — 2026-04-24

Added

  • Windows one-click launcher (FreeCrawl-SEO-Tool-Start.bat) — verifies Node.js and npm, offers to run npm install if dependencies are missing, then launches the desktop app.
  • Versioned window title — the app window now displays FreeCrawl SEO Tool v<version>, read from app.getVersion(); prevented the renderer's <title> from overriding it.

Changed

  • Renamed the application from FreeCrawl SEO to FreeCrawl SEO Tool across the window title, HTML title, and menu labels.

[0.1.0] — 2026-04-24

Added

  • Crawler engine: undici-based HTTP client (128 connections, keep-alive, cacheable-lookup DNS), rate limiting via p-queue, robots.txt compliance, manual redirect handling (each 3xx hop stored as its own row), per-request AbortController timeout.
  • HTML parsing: cheerio htmlparser2 fast path with entity decoding; extracts title / meta description / H1 / H1 count / H1 length / H2 count / word count / canonical / meta robots / X-Robots-Tag / image alt.
  • Link extraction: 16-column Screaming Frog-parity inlink/outlink metadata (type, alt text, target, path type, link path breadcrumb, link position, link origin).
  • SQLite storage: node:sqlite (no native compile), WAL mode, batch UPSERT, multi-row INSERT, schema_version table, conditional (function-based) migration system — up to v8.
  • Desktop UI: Electron 41 + electron-vite 5, React 19 + Tailwind 3.4 + Zustand 5, dense dark theme.
  • Tabs: Internal, External, Response Codes, URL, Page Titles, Meta Description, H1, H2, Content, Images, Broken Links, Canonicals, Directives, Links.
  • Table features: @tanstack/react-virtual virtualization for 100K+ rows, column resize + sorting, Row number column, row selection (Ctrl/Shift), cell selection, column selection, mouse drag-select (row/cell/column).
  • Seamless live sort: chunk-replace with stable getItemKey keeps sort order smooth while a crawl is still running.
  • Issues panel: 12 categories (missing title/meta/H1, long/short title & meta, duplicate title, multiple H1s, slow response, large page, 4xx, 5xx, redirect, missing alt text).
  • Advanced Table Search: Screaming Frog-style AND/OR group dialog — 24 fields, 12 operators, numeric/text type aware.
  • Bottom Detail Panel: Details / Inlinks / Outlinks / Images / SERP Snippet / HTTP Headers / Link Metrics tabs for the selected URL.
  • XML Sitemap generator from the File menu.
  • CSV export from every tab.
  • CLI: Headless Node CLI (apps/cli) — start URL + depth/max/out parameters.
  • User preferences: column widths, tab state, and "don't ask again" flags persisted to <userData>/preferences.json.
  • Clear confirmation: pop-up with "Don't ask again" checkbox; Clear button disabled when the table is empty.
  • Zero-delay Start button: immediate progress emit + optimistic state.
  • ESC exits fullscreen, native menu bar, removal of non-applicable menu entries.
  • Scrollbar styling: thinner edges, squared corners, larger hit area.

Changed

  • Migrated HTTP client from global fetch to a tuned undici Agent; throughput target ~5 URL/s → 80–150 URL/s.
  • UI preferences moved from localStorage to a JSON file; crawl data no longer persisted in localStorage.

Fixed

  • "table url..." runtime error caused by a migration version mismatch — addressed by an idempotent repair_images_schema (v5) migration.
  • Canonicals tab column bleed caused by duplicate React keys — fixed with a ColumnSpec.id field.
  • Broken rendering of quote and other characters in the SERP snippet (entity decoding).