The rel attribute has been captured on every backlink since that
table was added, but never displayed — a dofollow vs. nofollow
backlink is a real difference for SEO/competitive analysis, not just
a link count. Links with none of those tokens show as "dofollow".
Verified against real data (existing noopener-only link renders as
dofollow) plus a temporary synthetic nofollow+sponsored row to
confirm that branch too, removed after confirming.
Filters sites by server/powered_by/generator (e.g. "Shopify",
"WordPress", "nginx"), combinable with the existing keyword/TLD
filters. Results table now also shows each site's detected platform.
Verified: platform=Wix correctly isolates the one known Wix site,
tld=es+platform=nginx narrows to the 12 real nginx-hosted .es sites,
and the no-match case renders the empty state correctly.
WarcRecordFetcher was splitting out and discarding the HTTP response
headers to get at the HTML body — now it keeps and parses them, so
Server/X-Powered-By headers get captured alongside the <meta
name="generator"> tag already sitting in the parsed DOM. No extra
requests: same WARC segment already fetched for --with-metadata.
Site copies these from its homepage capture, same as
title/description/keywords. New badges on the site detail page show
the detected platform (e.g. "Wix.com Website Builder") and server
signature at a glance.
Verified against real .es data: correctly detected Wix
("00padel.es"), nginx/Apache/Cloudflare server headers, and PHP
X-Powered-By headers across the batch.
Shows inbound links (who links to this site, via Site::inboundLinks())
with the referring site, source page, and anchor text — paginated
separately from the Pages table via a distinct page-name query param
so both can paginate independently. Also surfaces a simple outbound
link count and a "N backlinks from M referring domains" summary.
Verified against real data: crawled podcastyradio.es (previously only
known as a backlink target from 00podcast.es) and confirmed its detail
page correctly shows that inbound link with the right anchor text.
The actual "who sells honey with a .es domain" feature: search sites
by keyword — matched against page title/description/keywords/body
text via a new MySQL fulltext index on site_pages — combined with an
optional TLD filter on the domain. Results are sites ranked by number
of matching pages. Shows nothing until a filter is entered, so it
doesn't just duplicate the plain Sites browse page.
Verified against real .es data pulled in for the test (dominio ->
4 matching sites, correctly ranked and TLD-filtered).
Home page is now a Livewire-powered, searchable/paginated Site list
(search by domain) instead of the stock Laravel welcome page. Clicking
a site goes to a plain controller-rendered detail page listing its
pages. Shared layout at resources/views/components/layouts/app.blade.php.
Adds Site/SitePage models and the crawlindex:fetch command, which pulls
CDX index records from Common Crawl and optionally enriches them with
page title/description/keywords/body text extracted from the WARC
archive. CDX/WARC access and the site/page upsert logic live in
CommonCrawlIndexService and WarcRecordFetcher.