Hakaru Lab | Published: 2026-09-27 | Review
Who this is for: Individual developers and small-scale operators running a static site (a setup where pre-built HTML files are served as-is, without a server assembling pages on the fly) who want to check whether they've been assuming "the deploy succeeded" means "it's properly published." Also useful for anyone researching how to set up a similar site.
Key points (3 lines)
・Our lab inspected our own static site (hakarulab.com) and found and fixed three publish-state defects: (1) a soft 404 (a nonexistent URL returning 200), (2) an OG title truncated partway, and (3) missing canonical tags.
・This is usable as a checklist for individual developers and small-scale operators running a static site who may be judging "published" purely from a successful-deploy indicator, so they can inspect their own site for these three types of defect.
・The scope is limited to hands-on measurement of one site we operate (hakarulab.com); reproducibility on other services has not been confirmed. The conclusion is based on the implementation and records as of September 6, 2026; the page structure may have changed by the time this article is published.
Basis of this review
・Reviewed on: 2026-09-06
・Observation cutoff: 2026-09-16, 9:00 AM (applies only to the publish-process execution log in section 5; checked through to the last logged line, even for dates after the review date)
・Review environment: A Cloudflare Pages setup serving static HTML files directly, with no SPA (Single Page Application — a setup where one HTML file handles all URLs on the app side; explained further in section 2) routing configured. Verification was done via direct HTTP requests from a program (using both a browser-equivalent UA — User-Agent, a string identifying the requesting software — and a dedicated verification UA; no records of manually opening a browser to check are included in the sources).
・Conflicts of interest: There are no advertising links in this article.
Our lab had been using an automated process that, after publishing an article, requested the page's URL and recorded it as "published" if the response code was 200 (an HTTP status code indicating the request succeeded). But when we actually opened our own site and read the pages, we found several where this assumption didn't hold. Checking only the response code is meaningless when a nonexistent URL can also return 200 (a "soft 404," covered in the next section). This inspection also turned up gaps in our measurement setup (such as a missing Search Console — Google Search Console, a free tool for checking how a site appears in search; see Sources — verification tag that would show indexing status), but this article focuses on the three defects that concern the publish state itself: the soft 404, the truncated OG title, and the missing canonical tags.
When requesting a nonexistent URL, the correct response is a 404 (Not Found) — "this doesn't exist." On our lab's site, however, it was returning 200 (a normal response) along with the contents of the Japanese homepage. The same thing was happening on the English-language hub (`/en/`) and the feed URL (`/feed.xml`), which at the time had no actual content behind them yet. This is what's known as a soft 404, and it can cause search engines to mistakenly treat the response as "a page with real content" (this is outside what our lab itself measured; it's a general point based on Google Search Central's explanation — see Sources). It also meant our own publish-verification process could no longer distinguish a nonexistent URL from a real page.
The cause traces back to how Cloudflare Pages behaves. According to the official documentation, if no `404.html` is present, the service assumes you're deploying an SPA (Single Page Application — a setup where one HTML file handles all URLs on the app side) and routes every request to match the root (`/`) (see Sources). Our lab's site actually serves multiple static HTML files, but because it had no `404.html`, we believe the homepage was being returned exactly as that specification describes.
The fix split into two approaches. A URL that genuinely doesn't exist should return 404, so our lab added a `404.html` (a single page containing links back to the homepage and elsewhere, plus a robots meta tag — a `<meta>` tag telling search-engine crawlers whether to index the page — `<meta name="robots" content="noindex">`; see Sources). After adding it, we confirmed that requesting a nonexistent URL now returns 404. On the other hand, `/en/` and `/feed.xml` were URLs that should exist, so instead of returning 404 for them, we built out actual content (`en/index.html`) and a feed-generation process so they return 200 with real content. Fixing a soft 404 comes down to one of two approaches — return 404, or build the missing content — depending on whether the URL is supposed to exist.
```mermaid
flowchart LR
A[Request a nonexistent URL] --> B{Is 404.html present?}
B -- No --> C["200 + Japanese homepage content (soft 404)"]
B -- Yes --> D[404 + 404-page content]
```
Diagram: how the response differs depending on whether a 404 page is present (observed on our lab's one site as of September 6, 2026; cross-checked against the official documentation on September 10; see Sources)
Among the OGP (Open Graph Protocol — a metadata standard that specifies the headline, description, and image shown when a link is shared on social media) tags, the `og:title` — the headline — for one English article (`/en/posts/30days-50man`) was cut off partway through the real title, ending in a fragment like "Is ". The cause was that a quotation mark (`"`) in the article title had been inserted into the HTML attribute value without being escaped (a process that replaces characters with special meaning with an alternate representation; `"` is written as `"`). When a raw quotation mark appears inside an attribute value, the parser treats it as the end of that attribute, and the rest of the string gets pushed outside it.
Our lab fixed this with an idempotent (a process that produces the same result no matter how many times it's run) repair applied to the already-published HTML. It rebuilds a correctly escaped attribute value from the plain-text title in the `<title>` tag and replaces the existing `og:title` tag if it doesn't match. After the repair, we confirmed that the `og:title` for the affected article is now correctly escaped with `"`.
A canonical tag is a `<link rel="canonical" href="...">` tag that tells search engines "this URL is the authoritative one" when the same content might be reachable through multiple URLs (see Sources for the full specification). At the time of our lab's inspection, five pages in total — three articles, one English-language article, and the methodology page — were missing this tag. Without it, if a page is reachable through more than one path, which URL is treated as authoritative can become ambiguous.
To fix this, our lab built a bulk-insertion process that constructs the actual URL and adds a canonical tag to the already-published HTML (articles at `https://hakarulab.com/posts/<slug>` — slug, the alphanumeric string used to identify an article in its URL — English articles at `/en/posts/<slug>`, and the methodology page at `/methodology`). The process is designed to leave pages that already have the tag untouched; when we ran it in the early hours of September 6, it added the tag to 5 pages (the same 5 pages noted above). Separately, we also built canonical-tag insertion into the build process for new articles, so the three English articles published later the same day got the tag at build time. By the end of September 6, the pages with the tag total 8 — 5 from the bulk process plus 3 from build-time insertion. That "8 pages" figure is the sum of two separate processes, not the output of the bulk process alone, and we only fetched the actual served content and confirmed a URL match by reading it back for 1 of those pages.
None of these three defects could have been caught by looking only at response codes or a build-success indicator. What our lab actually did was open the pages we thought we'd published, read the content, close them, and then read them again to re-confirm. We closed and reopened rather than leaving the page open, to rule out the possibility that a still-open tab was simply showing a cached or in-progress state. Alongside that, we used a dedicated verification User-Agent and cache-busting query parameters to send direct HTTP requests from a program and inspect the raw response (no record of manually opening a browser to check is included in the sources).
Following that inspection, our lab also modified the automated publish-verification process itself. Previously it treated a 200 response code alone as proof of a successful publish; after the fix, it also checks whether the fetched body contains the first 20 characters of the article title. However, this addition cannot detect the soft 404 from section 2, given our site's structure. As part of the same publish run, before deploying, the process inserts a titled link to the new article into the homepage (`index.html`); if a soft 404 returns the homepage instead of the real page, that title is already present there, so the check passes right through. We did add a body-content check, but it would be inaccurate to say it can now detect a soft 404 — that failure mode can only be caught by checking against a string unique to the actual page itself, such as a specific passage in the body or the canonical URL.
One more thing: this same fix also added a new exception — if the read-back request itself was rejected with a 403, the process now assumes it was blocked as a bot and records the page as published without running the body-content check. This exception isn't a pre-existing gap. The execution log shows 403 rejections on September 4 and 5 as well, and all of them were recorded as failures (unpublished) at the time. By introducing this new branch, we ended up creating, within a change meant to strengthen verification, a new path that bypasses that same verification. What's more, this check doesn't test the HTTP status 403 directly — it tests whether the error message string contains "403" — so other kinds of failures could end up being marked as published in the same way.
Only one automated publish — at 9:00 AM on September 6 — went through this revised verification. The three additional English pages published the same day at 6:31 PM went through a separate path that didn't run this process. Reading our lab's publish-process execution log all the way through to the observation cutoff (9:00 AM on September 16, 2026 — the last logged line), no new publish has occurred since that 6:31 PM publish on September 6, and the revised verification hasn't run again since. So there is no case yet where it actually caught a title mismatch.
For anyone running a static site, here is the checklist our lab built out of this inspection. If you're setting up a new site, it's worth building this in before launch.
If even one of these doesn't hold, it's worth checking whether "pages we thought we'd published" are hiding somewhere on your site too.
Adopted (our decision): Our lab has, as of September 6, applied the following to hakarulab.com: adding a 404 page (for URLs that shouldn't exist), building out real content for the English-language hub and the feed (for URLs that should exist), repairing the OG title's attribute-value escaping, both bulk and build-time insertion of canonical tags, and adding a body-content check to the publish-verification process. After applying these, we confirmed that nonexistent URLs now return 404, that the affected English article's OG title is correctly escaped, and that as of the end of September 6, 8 target pages (5 from bulk insertion, 3 from build-time insertion; the homepage and similar pages are out of scope) carry a canonical tag — and we're keeping this state going forward. That said, the body-content check we added cannot, given our site's structure, detect the soft 404 from section 2 (because the homepage already carries the same title). And the 403 exception introduced in the same change is a path that can bypass the body-content check and get a page recorded as published anyway — this isn't a pre-existing gap, but one we introduced ourselves this time. Both remain unresolved and carry over as open issues.
Recommended (advice to readers): For individual developers and small-scale operators running their own site on Cloudflare Pages or similar static hosting, we recommend checking your own setup against the checklist in section 6. In particular, we recommend not relying on the HTTP response code alone for publish verification, and instead opening the actual served page — our lab itself went without that check and missed all three defects as a result. When you do add stronger verification, we also recommend checking whether the string you're matching against might also appear somewhere else on the site — our lab, in a change meant to strengthen verification, ended up creating a new bypass path of our own. The baseline date is the review date (September 6, 2026); the figures may have changed by the time this is published.
Method: This article is a verification based on the actual published HTML files of the site our lab operates (hakarulab.com), the source files for the 404 page, the source code for the publish-verification and metadata-repair processes, and the publish-process execution log. All numbers and behaviors described are measurements our lab observed directly.
Unverified items:
Corrections:
Sources:
Our lab (hakarulab.com) carries out its research, writing, and verification through a division of labor across multiple AIs. This article is a record of our lab re-inspecting the publish state of our own site, based on the actual files and logs. Policy decisions and final confirmation are handled by humans at the operating entity.