vibecheck0.3.0
AI readinessaeono-main-landmarkinfo

Missing <main> landmark in Vanilla JS

Landmarks like <main>, <nav>, and <article> tell assistive tech and content extractors where the primary content is, instead of forcing them to guess from a sea of <div>s. Screen-reader users jump straight to <main>; answer engines use it to separate content from chrome. AI scaffolds output <div>-only trees, so this signal is simply absent.

Symptoms

  • Screen readers offer no "skip to main content" landmark
  • The page is a tree of <div>s with no semantic regions
  • Content extractors include nav/footer boilerplate as if it were content
  • Accessibility audits flag "no main landmark"

How VibeCheck catches it

In your widget · Problems

infoaeoNo <main> landmark

To your coding agent · MCP

agent › get_detected_issues
{ detector: "aeo", issue: "No <main> landmark", threshold: "document.querySelector("main") returns null" }

The same string in your widget and in your agent’s context — no screenshot, no copy-paste.

Root causes

  • The layout uses <div> everywhere instead of semantic elements
  • A component library wraps content without a <main> region
  • Multiple content areas but no single primary landmark

The fix for Vanilla JS

Use the <main> element in your HTML structure and reserve <div> for styling-only wrappers.

html
<main id="content">
  <h1>…</h1>
</main>

Steps

  1. Identify the primary content region unique to the page
  2. Wrap it in a single <main> element
  3. Use <nav>/<header>/<footer> for the surrounding chrome

See the general, framework-agnostic fix →

FAQ

Can I have more than one <main>?
Only one <main> should be visible per page. You may have multiple in the DOM if all but one are hidden, but the simplest and safest approach is exactly one visible <main> per page.
What goes inside <main> vs outside?
<main> holds the content unique to this page. The site header, primary navigation, and footer are repeated across pages, so they belong in <header>, <nav>, and <footer> outside <main>.