---
title: "How to ship one h1, title, meta description and JSON-LD on Replit"
slug: title-meta-schema-replit
published: 2026-09-24T13:24:02.070925+00:00
updated: 2026-09-24T13:24:02.070925+00:00
author: "Asif Rahman"
author_url: https://masifrahman.com
category: "AI Readiness"
tags: check:C3, platform:replit, Replit, structured data, JSON-LD, meta description, technical SEO
description: "Replit's SEO Rating scores title, meta description and h1 order, but never scores JSON-LD. Here is how to ship all four C3 signals on an Agent-built app."
url: https://aiscan.site/blog/title-meta-schema-replit
---

## Quick summary

| Question | Answer |
|---|---|
| Where does Replit check this? | The **SEO Rating** card in the **Growth** pane, calculated after every publish |
| Does that rating cover all four C3 signals? | No. Title, meta description and heading structure are scored; JSON-LD is not |
| Why not? | The Lighthouse audit behind the rating lists "Structured data is valid" as a **manual** check, never scored automatically |
| Where do the fixes actually live? | `client/index.html` on an Agent-built app (Autoscale), editable by hand or through SEO Agent on a paid plan |
| Time to fix | About 10 minutes, plus a republish |
| AIScan check | **C3**, structured HTML, in the `content` dimension |

**Start by scanning the app you actually deployed.** `npx aiscan-cli yourapp.replit.app`, or paste the URL into [AIScan](https://aiscan.site/), no account needed. Row C3 reports these four signals directly, and the same free pass covers every other content, discoverability, bot-access and capabilities check the platform grades.

## Replit doesn't have a settings panel. It has an audit that runs after you publish.

Every other platform in this series keeps title, description and schema somewhere you can open before going live: a template file, a `metadata` export, a settings tab. Replit's equivalent, the **SEO Rating**, only exists once a deployment is public. According to Replit's own documentation on the feature, verified on 24 September 2026, publishing an Autoscale, Reserved VM or Static app produces a Lighthouse audit of your live URLs within a minute or two, shown as a badge in the Publishing tool: Healthy, Needs Work or Weak.

If the rating has room to grow, **SEO Agent** turns the findings into one-click fixes. It lives in the **Growth** pane and groups issues into four categories:

| SEO Agent category | What it covers |
|---|---|
| AI Readiness | Signals aimed at crawlers that aren't traditional search engines |
| Crawlability & Discovery | `robots.txt`, `sitemap.xml`, link structure |
| Landing Page Rendering & Metadata | Title tags, meta descriptions, heading order, alt text |
| Performance Proxies | Load-time signals that feed into the same score |

Two things gate the tool itself, both stated on the same page: the app must already be published, and the builder must be on a **paid plan**. A free-plan project shows an upgrade prompt where the fix buttons would sit. Replit's documentation, fetched from docs.replit.com the same day, lists structured data among what SEO Agent will fix: "Structured data: JSON-LD markup that helps search engines show rich results." Title tags, meta descriptions and heading order are on that same list. Read only that list and C3 looks fully covered by one "optimize my SEO" request to Agent.

## The gap: Lighthouse scores three of these signals, and skips the fourth

| Lighthouse SEO audit | Automatically scored? |
|---|---|
| Document has a `<title>` element | Yes |
| Document has a meta description | Yes |
| Heading elements appear in a sequentially descending order | Yes |
| Structured data is valid | **No, manual check only** |

Google's own Lighthouse documentation for the last row, fetched from developer.chrome.com on 24 September 2026, places "Structured data is valid" under a section it calls **Manual checks**, the audits Lighthouse cannot score on its own and instead leaves for a human to confirm with Google's Rich Results Test. That means an app can carry a Healthy SEO Rating with zero JSON-LD anywhere on the page, because the one signal that would catch it was never part of the score to begin with. AIScan's C3 check reads the delivered HTML directly and reports a genuine pass or fail on structured data, which is the reading Replit's own badge cannot give you.

## Fix the title and meta description first — this part Replit already catches

On an Agent-built app, the front end lives under `client/`, with Vite's `root` pointed at that folder and `build.outDir` set to `dist/public`, the same scaffold covered in [the llms.txt guide for Replit](https://aiscan.site/blog/llms-txt-replit). The `<title>` and `<meta name="description">` tags sit in the `<head>` of **client/index.html**, and because Vite ships that file once at build time, both tags are present in the raw response even though the rest of the page is client-rendered.

Two ways to set them:

1. **Ask Agent.** Open the **Growth** pane, find the **SEO Rating** card, click **Run scan with Agent**, then expand **Landing Page Rendering & Metadata**. **Fix with Agent** on the title or description row hands that one finding to Agent; **Fix all with Agent** sends every open issue at once. Review the change, click **Apply changes to main version**, then republish.
2. **Edit the file directly.** Open **client/index.html** in the file tree and write the two tags by hand. A generic scaffold title such as "Vite + React + TS" is the most common finding here.

Most Agent-built apps serve one page to every route, so getting these two tags right in that single file covers the whole app. An app with genuinely separate routed pages needs per-route title and description handling, typically a library such as `react-helmet-async` in a client-rendered React app, which is a larger change than SEO Agent's one-click fix.

## JSON-LD lives in the same file, but you have to check it yourself

Add structured data to the same `<head>`, either by asking Agent for it (it is on SEO Agent's own documented fix list) or by pasting a script tag directly:

```html
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "WebApplication",
  "name": "Your App Name",
  "url": "https://yourapp.replit.app",
  "applicationCategory": "BusinessApplication"
}
</script>
```

Because the SEO Rating never scores this, a Healthy badge is not evidence it worked. Confirm it two ways instead: fetch the raw page and look for the script tag yourself, then run the URL through Google's Rich Results Test, the same manual step Lighthouse's own documentation points to in place of an automatic score.

## The h1 problem is Autoscale's rendering order, not a missing element

This is the signal most likely to fail on an Agent-built app, and Replit's own rating is the least likely tool to catch it. The production server, per the scaffold's `server/vite.ts`, serves the same **client/index.html** shell for every path and lets your React code fill in the actual content, including any `<h1>`, after the browser runs the JavaScript bundle. Lighthouse executes that JavaScript in a real browser before it audits the page, so the SEO Rating sees the finished heading and can report success. A fetch that never runs JavaScript, `curl`, most AI agents, AIScan's own crawler, sees the static shell and nothing else: zero headings in it.

Static Deployments don't have this problem. According to Replit's deployment documentation, a Static Deployment serves pre-rendered files directly rather than running a server, so whatever heading is baked into the build is what every reader gets, JavaScript or not. On Autoscale and Reserved VM apps built by Agent, the fix is to put a real `<h1>` matching the text your app actually renders as its main heading directly inside **client/index.html**, so it exists before any script runs rather than only after. Preview any Agent-applied fix before accepting it: a heading added next to an existing large unstyled one can produce two h1s instead of one.

## Confirm all four signals on the domain that actually ships

Fetch the deployed app the way an agent would, without a browser:

```bash
curl -s https://yourapp.replit.app/ | grep -oE '<h1[^>]*>[^<]*</h1>'
curl -s https://yourapp.replit.app/ | grep -oE '<title>[^<]*</title>'
curl -s https://yourapp.replit.app/ | grep -c 'application/ld+json'
```

Expect exactly one `<h1>` carrying real page text, one non-generic `<title>`, and at least one `application/ld+json` match. Zero on any of those three is the finding to fix, regardless of what the Growth pane currently shows.

## Where AIScan fits, and where it doesn't

AIScan's C3 check reads the same unrendered HTML described above and reports the same four signals as a pass or fail, with no plan gate and no publish requirement standing between you and the answer. What it does not do is rewrite your files, tell you whether your JSON-LD type is the best choice for your app, or replace judgment about whether a heading is genuinely descriptive. That part stays with you or with Agent; AIScan's job is telling you, honestly, whether the fix landed.

## Ship the fix, then keep the rating honest

Republish after any change here. Replit's rating and AIScan's scan both read the live domain, never the workspace preview. Then run the scan again, `npx aiscan-cli yourapp.replit.app` against the published URL, reading row C3. From there, [the full Replit setup guide](https://aiscan.site/blog/ai-readiness-setup-replit) covers the rest of the content, discoverability and bot-access checks the same scan reports, and [the check reference](https://aiscan.site/docs/checks/content) explains what each one asserts. Browse [/guides](https://aiscan.site/guides) for the rest of this series.

