Skip to content
MintGuides

Go live

Website projects

Site setup, pages, per-page SEO and content blocks — and rendering them on your site in two calls.

Open Projects
On this page

What you get

A website project runs your site’s content; your site shows it.

MINT is where your team edits the website — its pages, their text and images, their SEO. Your site (Next.js, Astro, a static site, anything that can call an API) reads it with two calls. Make one by choosing Website when creating a project; list the site’s domains on the project for analytics.

The website kit

Three ordinary models, in a “Website” sidebar section. Change them like any model.

Model (address)Holds
Pages (pages)Every page: its name, path, status, template, parent and place in the menu.
SEO (seo)Per page: title, description, share image, keywords, canonical URL, hide from search engines.
Contents (web-contents)What each page says, one typed piece at a time — a hero, cards, questions, a list (Contents, page by page).

They start with a read-only public API (List and Read one, open to anyone), which is what the site API uses. Add fields freely; keep the models’ addresses and that public API, or the site API can’t find them.

The site’s own settings — name, logo, favicon, contact details, default SEO, tags — aren’t a model: they’re on Site setup, one set per website. (Websites made before this had a Site settings table; its record was copied to Site setup, and the table can be deleted in the model builder.)

Building a page

A page, its SEO and its content blocks.

  1. Under Pages, add a page: name “About”, path /about (the home page is /), template, and status Draft while you work.
  2. Open it. Its Contents tab lists its blocks — Add there creates one already linked to the page. Add a heading block, a rich-text block, a gallery…
  3. Its SEO tab: add the title and description search engines and link previews show.
  4. Set the page to Published. Your site shows it from then on.
Only published pages are served. Set a page back to Draft or Archived to take it down without deleting it.

Contents, page by page

Pick a page, then add what’s on it. Each piece has a type, and asks only for its own words.

Contents opens with a Page dropdown: choose Home, About… to see that page’s contents in the order they show, or Whole site for what’s on every page — the header and the footer. The arrows move a piece up or down; the pencil opens it.

New content asks first what it is, then shows only that type’s fields. Type in the search box to find a type by name or by what it’s for; above the rest, Suggested offers what usually comes next — an opening for an empty page, the header and footer for the whole site, and after a hero: text, cards, numbers…

TypeWhat it holds
HeroA small line above, a heading, text, a picture, two buttons and a few numbers under it
Hero carouselSlides that move on, each with its own heading, subheading, two buttons and background picture — and how many seconds each shows
Text / Rich textA heading and a few paragraphs — or a longer piece with headings, lists and pictures
CardsA heading and a row of cards, each with a title, small text, description, picture and link — features, services, team, plans
QuestionsQuestions and their answers
NumbersA few figures with a label each
ReviewsQuotes with a name, role and photo
Gallery / Logos / Picture / VideoPhotos, logos, one picture with a caption, or a video
Call to actionA heading, a line and the buttons
ListRecords of one of your models — see Lists of your records
SectionAnything else: headings, text, a picture, buttons and rows
Header / FooterThe words and links at the top and bottom of every page

The types are components, under Build → Components (category content): add a field to one and every piece of that type gets it; make your own component in the content category and it’s offered as a type too. Each piece is checked as its type. Table opens the same records as a table; pieces from before types (one word each, as the site builder made them) are listed under the page and open there.

Every text field is plain words — a box where each new line is a new line on the site — in every type, your own types included. Only Rich text has the editor with headings, lists and links. Words written in the editor before are shown as plain text the next time the piece is opened.

Drafts until you publish. A change — made here, in the table or in the site builder — is a draft: each piece says Draft, Published or Changes not published. Publish on a piece, or Publish the page, puts it on your site and API; the site builder’s Publish puts the words it shows live with the layout. Publishing needs the Publish permission. The site builder writes each section’s words into one piece of the section’s type, so what you add there shows here, in the page’s order.

More in one piece

A Text with a Gallery under it, a Hero with a Section after it: blocks that belong together stay in one piece.

Under a piece’s own fields, More in this block adds more blocks to it. While it’s empty it suggests what goes well with the piece — under a Text: a Picture, a Gallery, a Video; under a Section: Cards, a Gallery, a Picture — one click adds one. Add opens every type with a search box, the suggested ones first (Enter adds the first match) — any type but List, which is a piece of its own — and shows that type’s fields. Each block moves up and down, folds away, is copied or removed; one piece holds up to 20. The list says +2 blocks beside a piece that has them.

They go live with the piece when it’s published, in the order you put them. The site builder only changes the piece’s own words; the blocks you added here stay.

Slugs: how a site finds a piece

Every piece has a slug — a short name like home-intro. That’s what connects it to your site.

A slug is made for each new piece from its page and type (home-hero-3f9a2c), or you type your own when you add or edit it: lowercase letters, numbers and dashes, one piece per slug. The list shows each piece’s slug with a copy button, and the piece’s form shows the addresses to read it.

Your siteHow it reads the piece
Made with the site builderEach text on the page is tied to a piece’s slug and field — you don’t need the address. Change a slug, and places that use the old one stop showing it until they’re tied again.
Your own site or app — one pieceGET /public/api/web-contents/by-slug/home-intro?apiKey=mint_pk_… — its type, its words, and the blocks added under it (block: the piece’s own first, then the others in order, each with its type in __component).
Your own site or app — a whole pageGET /public/api/pages/by-path?path=/about&apiKey=mint_pk_… — the page, its SEO, and its pieces in the order they show. Draw each by its type, or pick one out by its slug.
Both answer with what’s published only — a draft, a hidden piece or a removed one isn’t there. The key is your project key, from API → Keys; more in The site API.

Lists of your records

Show your projects, posts or products on a page: which ones, how many, in what order.

  • Model — whose records it shows. The site reads them as any visitor would, so the model needs its public API on for listing; one without is offered with the reason.
  • How many and Order by — newest first, the cheapest first, by name.
  • Which records — conditions on its fields (Featured is Yes, Year is more than 2020), all of them or any one. With none, every record its public API shows.
  • Card title, text and picture — which of its fields each card shows, and Each card links to: /projects/{slug} fills in each record’s own values.

It shows now lists what it would show at this moment, or why it shows nothing.

Older content blocks

Websites made before content types kept one word per record. Category says what kind.

The first time the site builder opens such a site, each section’s words move into one piece of its type — the page looks the same. The old records stay until the next Publish, then go to the table’s Archived view.
CategoryUses the fields
ContentContent (heading or main text), Sub content, Button text and Url
Rich contentRich content — formatted text with headings, lists, links and images
List / List of linksList — one entry per item
CardCards — rows of image, title, subtitle and description
Image / GalleryImage / Gallery
VideoVideo URL
Section / OtherWhatever your site’s design needs
  • Priority orders blocks on the page — higher first. Section and Slug let your site group or find a particular block (“hero”, “faq”).
  • Is visible off, or status Draft, hides a block without deleting it.
  • Background colour, font colour and font sizes are there for blocks that need their own style; Note and Ref image are for your team only.

SEO

One SEO record per page: Title (up to 120 characters) and Description (up to 320) for search results, a Share image for link previews, keywords and tags, a Canonical URL if the page lives at another address too, and Hide from search engines. Your site puts them in the page’s head (see the example below); pages without one fall back to the site settings’ defaults.

A page’s SEO page

Open a row on Website → SEO to edit all of that page’s SEO on one page, with its score and previews beside it.

The fields are in five parts: Search result, Sharing, Search engines, Structured data and Sitemap. The buttons at the top jump to each part. Beside them, the score and the Google and shared-link previews change as you type.

Changes are kept on the page until you press Save (or ⌘S / Ctrl+S). While there are any, a bar at the bottom offers Discard and Save, and leaving the page asks first.

Across the site lists the site SEO health problems this page is part of, like another page with the same title, with links to those pages. It reflects the last save. Page opens the page’s own record, and View on site opens it on your domain. The Link preview tab checks the live page the way Facebook, LinkedIn, WhatsApp, X and Slack read it (Link previews) — save and publish a change before checking it; on a page drawn per record, type one record’s address. Overview, Comments and History are in the tabs, as on any record. To link the SEO to a different page, use Edit in the row’s ⋯ menu on the table.

The SEO score

Beside each page’s SEO, and under Basics in the edit form: a score from 0 to 100 and what to fix, worked out as you type.

Type the page’s Focus keyword, the one phrase people would search to find it, and the checks look for it. The score is Good from 80, Needs work from 50 and Poor below that, and it shows under the Google preview too. Problems come first, each with what to do.

CheckGood when
Visible to search enginesHide from search engines is off. A hidden page can’t rank at all.
Title and descriptionTitle 30–60 characters, description 70–160. Longer ones get cut off in results.
Keyword in the titleIt’s there, near the start.
Keyword in the descriptionIt’s there. Google shows the searched words in bold.
Keyword in the addressIt’s in the page’s path, like /wireless-headphones. Not checked on the home page.
Keyword in the main headingThe page’s first heading has it.
Keyword in the opening wordsIt’s in the first 100 words.
How oftenAbout 0.5–3% of the words. More reads as stuffing.
One page per keywordNo other page has the same focus keyword. Two pages after one phrase both rank lower.
Page length300 words or more.
One main headingA page built elsewhere has exactly one h1.
Short sentencesUnder 20 words on average (English pages).
Share imageThe page has its own. Using the site’s image counts half.

The page’s words come from the site builder for pages built there (the saved draft), and from the live page for a site built elsewhere. When they can’t be read, the checks that need them are left out rather than failed, and the score says why. The focus keyword is never published.

Structured data

Under Structured data on a page’s SEO: say what the page is and fill in a short form, for star ratings, prices, opening hours and FAQs in search results.

Pick the Schema type and its form appears. The page’s title, description, address and share image are added for you, so the form only asks for the rest. Under it, Google needs lists what the type can’t do without, and Would help what makes the result richer.

TypeThe form asks for
OrganizationName and logo (the site’s when left empty), phone, email, address, social profiles.
Local BusinessThe same, plus the kind of business, price range, a map link and opening hours. Google needs the address.
ProductBrand, SKU, image, price and currency, availability, rating and number of reviews. Google needs a price with its currency, or a rating with its count.
Article, Blog PostingAuthor and their page, published and updated dates, image. The site is the publisher.
FAQ PageQuestions and their answers. Only pairs with both are used; they should be on the page too.
EventStart and end, in person or online or both, status, venue and address or the online link, ticket price and link, performer, organiser.
ServiceThe service, the area served, who provides it, and a starting price.

On a page made one per record, like /shoes/[slug], each text field has a { } button: pick one of the record’s fields and every shoe’s page fills it in, for example the price from {{record.price}}.

Advanced: your own JSON-LD still takes any JSON object; it goes over the form, so what you write there wins. After publishing, the link under the form opens Google’s Rich Results Test for the page (for a page per record, test one record’s address). On the home page, Site setup → SEO’s structured data is used when the page’s type is Auto.

Site SEO health

At the top of Website → SEO: problems that only show when your published pages are looked at together, and the gaps on each.

Each problem lists its pages; click one to open its SEO page. Errors come first, then warnings, then notices. Check again (the arrows) runs it once more after you’ve fixed something.

ProblemWhat to do
The whole site is hidden from search engines (error)Site setup → SEO → Indexing is off. Turn it on when the site is ready.
Canonical URL points to a page that isn’t on the site (error)Search engines follow it and drop the page. Point it at a published page, or clear it.
Hidden from search engines, but in the menuAllow indexing, or take the page out of the menu.
Pages with the same title / descriptionGive each page its own, so search engines can tell them apart.
Pages with the same focus keywordTwo pages after one phrase both rank lower. Give each its own phrase.
No title of their own / No descriptionWrite them in the page’s SEO. Without a title, results show the page’s name.
Titles over 60 / descriptions over 160 characters (notice)The end gets cut off in search results. Put what matters first.
No share imageAdd one to each page, or a default in Site setup → SEO (then it’s only a notice).
Hidden from search engines (notice)Check these are meant to be hidden.
Published pages with no SEO here (notice)For a site built elsewhere, these keep their own SEO. Add them on Website → SEO to set it here.

Only published pages count. Pages made one per record (like /blog/[slug]) aren’t compared with other pages, since their titles are filled in per record.

The site API

Three read-only calls, with the project key (API → Keys).

CallAnswers
GET /site{ settings, menu } — the site settings, and the menu: [{ _id, name, path, parent }].
GET /pages/by-path?path=/about{ page, seo, contents } — the published page at that path, its SEO (or null), and its visible, published blocks in order. 404 if there’s no published page there.
GET /web-contents/by-slug/home-introOne published piece by its slug: its type and block — its own words first, then any blocks added under it. 404 if there’s none.
const site = await fetch('https://mint-c5e1255519fc.herokuapp.com/public/api/site?apiKey=mint_pk_…').then(r => r.json());
const about = await fetch('https://mint-c5e1255519fc.herokuapp.com/public/api/pages/by-path?apiKey=mint_pk_…&path=/about').then(r => r.json());
const intro = await fetch('https://mint-c5e1255519fc.herokuapp.com/public/api/web-contents/by-slug/home-intro?apiKey=mint_pk_…').then(r => r.json());

Need something else — every block with section “faq”, say? The models’ own public API is there too: GET /web-contents?section=faq.

Rendering your site

One route that renders whatever path is asked for.

An example with Next.js — fetch the page by its path, put its SEO in the head, and draw each block by its category. Any framework works the same way.

// app/[[...slug]]/page.tsx — Next.js, one route for every page
const API = 'https://mint-c5e1255519fc.herokuapp.com/public/api';
const KEY = 'mint_pk_…'; // the project key — API → Keys

const load = async (slug: string[] = []) => {
  const path = '/' + slug.join('/');
  const res = await fetch(`${API}/pages/by-path?apiKey=${KEY}&path=${encodeURIComponent(path)}`, { next: { revalidate: 60 } });
  return res.ok ? res.json() : null;
};

export async function generateMetadata({ params }) {
  const data = await load((await params).slug);
  return data?.seo
    ? { title: data.seo.title, description: data.seo.description,
        openGraph: { images: data.seo.image ? [data.seo.image] : [] },
        robots: data.seo.noIndex ? { index: false } : undefined }
    : {};
}

export default async function Page({ params }) {
  const data = await load((await params).slug);
  if (!data) return notFound();
  return (
    <main>
      <h1>{data.page.name}</h1>
      {data.contents.map(block => <Block key={block._id} block={block} />)}
    </main>
  );
}
function Block({ block }) {
  switch (block.category) {
    case 'rich-content': return <section dangerouslySetInnerHTML={{ __html: block.richContent }} />;
    case 'image':        return <img src={block.image} alt={block.name} />;
    case 'gallery':      return <div className="gallery">{block.gallery.map(src => <img key={src} src={src} alt="" />)}</div>;
    case 'list':         return <ul>{block.list.map(item => <li key={item}>{item}</li>)}</ul>;
    case 'card':         return <div className="cards">{block.card.map((c, i) => <article key={i}><h3>{c.title}</h3><p>{c.description}</p></article>)}</div>;
    case 'video':        return <video src={block.videoUrl} controls />;
    default:             return <section><h2>{block.content}</h2><p>{block.subContent}</p>
                           {block.btnText && <a href={block.url}>{block.btnText}</a>}</section>;
  }
}

Images

Image fields hold the file’s public address from your project’s Media, ready for an img tag.

Rich content is HTML written by your team. Render it only from your own project, as here — never pass HTML from visitors through the same path.

The website’s home

Open a website project and its dashboard is about the site.

  • Traffic — page views, visitors, visits and bounce rate for the last 30 days, against the 30 before, and views per day. The full reports are on Analytics.
  • Set up — what’s still missing: name, logo, favicon, default SEO, a published page, SEO on every page, a domain, tracking. Each has a link to where it’s set; the list goes once everything is done.
  • Pages — each page’s path, status, whether it has SEO, and how many content blocks it has.

Numbers, charts and lists you add in the dashboard builder show below.

Site setup

Site → Site setup: everything a website needs besides its pages, on one page — not a table.

Its tabs are General, Contact & social, SEO, Tracking, Server-side, Code, Redirects & headers, Domains and Check the site. Each setting is a card with its own Save, enabled once you change something. Your site reads it all from the site API, so a change is live within a minute with no code change. Changing it needs the Build permission; domains need Manage projects.

Name, logo and favicon

General has the site’s name, tagline, logo, favicon and footer text, and its theme: primary and secondary colour and font. Images come from your Media library. The analytics script adds the favicon to pages that don’t have one.

Contact and social links

Contact & social: email, phone, WhatsApp, opening hours, address and a map embed, and the full addresses of your Facebook, Instagram, X, LinkedIn, YouTube, TikTok and Pinterest pages. Your site shows the ones you fill in.

Default SEO

On the SEO tab, Default SEO is the same SEO editor as each page’s: a Google preview on your site’s domain, then Basics, Social (with a share preview), Indexing, Structured data and Sitemap, with counters and SEO checks. Above it, the title template — %s · Acme makes a page called “About us” show as “About us · Acme”.

What it covers depends on the kind of field. The meta title, description, share image and keywords are the home page’s, and the fallback for any page without its own. Settings — the Open Graph type, the X card and image, indexing switches, max snippet and image preview, sitemap priority and change frequency — apply to every page that doesn’t set its own. Share titles and descriptions, the schema type, custom JSON-LD and the canonical URL are the home page’s only, so pages don’t all share one.

Each page’s own SEO is under Website → SEO, or a page’s ⋯ → Name, address & SEO in the site builder: A page’s SEO.

Tracking tags and pixels

Paste an ID, save its card, and the tag is on every page — the analytics script adds it.

TagThe ID looks like
Google Analytics 4G-XXXXXXXXXX
Google Tag ManagerGTM-XXXXXXX
Google AdsAW-123456789
Meta PixelA long number
TikTok PixelCapital letters and digits
LinkedIn InsightThe partner ID, a number
Pinterest TagA long number
X (Twitter) Pixelo1a2b
Snap PixelA 36-character ID with dashes
Microsoft ClarityThe project ID
HotjarThe site ID, a number

This works on any site with the analytics script on its pages. Page views on sites that change pages without reloading are counted by the pixels too. MINT analytics turns the panel’s own visit counting on or off. A site that renders its tags itself adds data-no-tags to the script.

Server-side tracking

Browsers block a good share of tracking; this server can send the events too.

ProviderWhat the server sends — and what it needs
Meta Conversions APIPage views, Lead (a record your site sends in, e.g. a contact form) and CompleteRegistration (a customer signs up). Needs the Meta Pixel ID and an access token from the pixel’s Conversions API settings.
Google Analytics (Measurement Protocol)generate_lead and sign_up. Needs the Google Analytics ID and an API secret from your web data stream.

Turn each on in Site setup → Server-side. Keys are kept on the server: once saved, the panel only shows that one is set, with Replace and Remove. Meta gets each page view from the pixel and the server with the same event id, so it counts it once; Google can’t do that, so page views go to Google from the browser only. Visitors are matched by IP address, browser and the platform’s cookie; an email or phone in a form is hashed before it’s sent.

So a lead is matched to the visitor who sent it, the site adds window.MintAnalytics?.headers() to the headers of its own calls to the site API. Use Meta’s test event code while you check it in Events Manager → Test events, then clear it.

Add script

Paste any script a provider gives you and it’s on every page of your website.

  • Open Site setup → Add script and press Add script.
  • Give it a name (so you know it later), choose where it goes — in <head> (tags that must load first, verification metas), at the start of <body> (a <noscript> fallback) or at its end (chat widgets) — and paste the script exactly as given, with its own <script> or <meta> tags.
  • Add. It’s saved at once and live within a minute. Switch it off to pause it without losing it; Edit or Remove it any time.

Good for Google Tag Manager, Microsoft Clarity, Hotjar, a chat widget (Tawk.to, Crisp, Intercom), a Facebook domain-verification tag — anything a provider gives you as HTML. On a site made in the site builder the scripts are written into each page’s HTML, so they run on the first load and verification checkers find them; a site with its own code gets them from the analytics script. Only add scripts you trust: they run with full access to your pages and visitors.

Indexing, robots.txt and sitemap

  • Let search engines index the site — off while you build; robots.txt then asks them all to stay away.
  • Sitemap — a sitemap.xml named in robots.txt: your published pages, and every record a template page shows (each blog post at /blog/my-post, each product) with the date it last changed and its image. Anything marked Hide from search engines is left out: a page, a whole template page, or one record with its own switch.
  • Extra sitemap addresses — pages Mint doesn’t know about, one per line: /old-page, or a full address on your site. Addresses on other domains are ignored.
  • Main domain — the address used in the sitemap and robots.txt.
  • Google Search Console and Bing — the verification codes, added as meta tags.

Your site serves them from the site API: /site/robots.txt and /site/sitemap.xml — the tab shows the full addresses. A site built with AI wires them up for you.

Past 5,000 addresses the sitemap becomes an index of numbered parts, /sitemap.xml?part=1, ?part=2 and so on, as search engines expect. Sites made in the site builder and sites behind the MINT Worker pass the part on for you; a site you serve yourself should pass ?part= on to the site API too.

Your robots.txt and AI crawlers

Site setup → SEO → robots.txt: what search engines and AI crawlers may read. Built for you, or written by you in full.

Built for you starts from the Indexing settings: everything allowed (or everything blocked while indexing is off), your Extra rules, and the Sitemap line. Each crawler has a switch; turn one off and the file tells it to stay away.

CrawlerWhat it’s for
Googlebot, BingbotSearch results. Blocking one takes your site out of that search engine.
Google-ExtendedTraining Gemini. Doesn’t affect Google Search.
GPTBotTraining OpenAI’s models.
ChatGPT-UserChatGPT opening a page when someone asks it to.
ClaudeBotTraining Anthropic’s models.
PerplexityBotPerplexity’s answer engine.
CCBotCommon Crawl, an open web archive many AI models are trained on.
BytespiderTraining ByteDance’s models (TikTok’s owner).
Applebot-ExtendedTraining Apple’s models. Doesn’t affect Siri or Spotlight.

Write the whole file starts from the file built for you, and the site then serves exactly what you write: the switches, Extra rules and Indexing don’t change it. With indexing off, every page still says noindex.

Under the editor you see the file and a check for the usual mistakes: the whole site blocked, Googlebot or Bingbot blocked, no Sitemap line, a Sitemap line without a full address, Noindex lines (search engines ignore them), and lines crawlers don’t understand. Crawlers are asked, not forced: the well-known ones listen, others may not.

Redirects and headers

Redirects send an old address to a new page or another site — 301 permanent when a page moved for good, 302 temporary otherwise. Response headers are sent with your pages, for security (X-Frame-Options, Content-Security-Policy) or caching. Both come to your site in GET /site under config; its code applies them (a site built with AI does).

Domains

Where your site is live, e.g. example.com and www.example.com. Analytics only counts visits from these (and from localhost while you build), so others can’t send visits in your name. With none, visits from anywhere count.

The quickest way is on Analytics, under the project’s name: once the snippet is on your site, the site your visits come from shows there with Add beside it, one click. Add domain (or Domains) opens the list: every site visits came from in the last 30 days, a box to type one in (a whole address like https://www.example.com/about is fine), and the domains you have, each with a × to remove. Adding a domain needs the Manage projects permission.

Check the site

Is every tag really on the live site?

Check the site opens your live home page (the main domain, or the first domain) and shows each tag set here as On the site, Check this or Not on the site. It also finds tags the page adds by itself: the same ID twice means every visit is counted twice; another ID means the page has its own. Google Tag Manager confirms your container exists, and Meta confirms the Conversions API token is valid and made for your pixel. Each Tracking card shows its result from the last check.

Connect a website you already have

Site → Website setup → Existing website: one line on your site, then pick which pages take their SEO from here.

A site that’s already built — WordPress, Webflow, Wix, Squarespace, Shopify, or one made by an agency — connects without rebuilding it. You get this project’s Analytics on it, and you edit the SEO of the pages you choose here instead of in the site.

  1. Paste the snippet into the <head> of every page, as high as you can. Website setup shows it with your project key filled in, and where it goes on each platform (a header-code box or your theme’s header).
  2. Add the pages Mint should handle: on Website → Pages, a page with its address as it shows in the browser (/about), set to Published; then its SEO on Website → SEO.
  3. Test the connection: open your site once in a browser, then type a page’s address in Website setup and press Test connection.

What Test connection checks

CheckWhat it tells you
DomainThe address is one of your domains (Site setup → Domains). Visits from other addresses aren’t counted.
SnippetThe page’s HTML has the snippet with this project’s key and data-seo. Added by a tag manager or a plugin that loads it later? It may not be in the HTML; Visits then shows whether it runs.
VisitsPage views are arriving, with the last page and when. This shows the snippet runs in visitors’ browsers.
SEOWhether the page takes its SEO from here or keeps its own, and whether the HTML your server sends already has it (then link previews see it too).

Connected means nothing is missing and the snippet is on the page or visits are arriving. For the raw answer a page gets, open /site/head with its path (below): "found": false means the page isn’t added.

Which SEO a page gets

  • A page you added to SEO: what you fill in here replaces the page’s own title, description, share image and the rest. A field you leave empty keeps the page’s own, and Default SEO only fills in tags the page doesn’t have.
  • Any other page: keeps its own SEO. The snippet leaves it alone, even with Default SEO set.
  • /about, /about/ and /about.html are the same page. Changes reach the site within a minute, without a deploy.

Link previews and other crawlers

Google runs the snippet, so it reads the SEO. WhatsApp, Facebook, LinkedIn and X previews, and most other crawlers, only read the HTML your server sends. If you can edit your site’s server, Website setup has short code for PHP, Node / Express and Next.js that prints the same tags into the page there. It prints nothing for pages you haven’t added, so your own tags stay. Keep the snippet in the page too: it counts the visits.

GET https://mint-c5e1255519fc.herokuapp.com/public/api/site/head?apiKey=mint_pk_…&path=/about
GET https://mint-c5e1255519fc.herokuapp.com/public/api/site/head?apiKey=mint_pk_…&path=/about&format=html
No access to the site’s code at all? Connecting through your own Cloudflare account is coming next, so the SEO is in the HTML for every crawler without touching the code.

Website setup: connect your code

Site → Website setup: how a site you build yourself reads this project — step by step, for your framework.

Pick what your site is built with — Plain HTML, React (Vite) or Next.js — and the page shows the code for each step, already filled in with your project’s API address, project key and domain. Copy it into your site:

  1. Keys — where they go: a small site.js for plain HTML (there’s no build step), .env for Vite, .env.local for Next.js — and the same names on your host.
  2. Connect — a few lines that call the site API: the site and its menu, a page by its path, a piece by its slug, a list of records.
  3. Show a page — one route that draws whatever page is asked for.
  4. Analytics — the analytics script in every page’s head (Next.js: the root layout). It counts route changes in React apps by itself, and brings in every tag from Tracking and Add script.
  5. SEO — each page’s title, description and share image from Website → SEO, and robots.txt and sitemap.xml passed on from this project (a rewrite on Netlify or Vercel, two route handlers in Next.js).
Plain HTML and Vite apps are drawn in the browser. Google reads them, but link previews (WhatsApp, Facebook, LinkedIn) only see the HTML file — write the title, description and share image there too. Pages that must rank or share well are best on Next.js, which renders them on the server.

Keys, and where each setting goes

Two values go in your code; everything else is set here and reaches the site without a deploy.

SettingWhere it goes
Site API addressYour settings: MINT_API (server), VITE_MINT_API (Vite), NEXT_PUBLIC_MINT_API (Next.js client code).
Project key (mint_pk_…)MINT_API_KEY, VITE_MINT_API_KEY or NEXT_PUBLIC_MINT_API_KEY. It’s publishable: it reads only what’s published and what your endpoints allow, so it can be in a page.
Server key (mint_sk_…)Only your server’s settings, as MINT_SERVER_KEY — never with VITE_ or NEXT_PUBLIC_, never in a page. Make one on API → Keys, only if your server calls endpoints that need it.
Google Analytics, Tag Manager, pixelsSite setup → Tracking
Chat, verification and other scriptsSite setup → Add script
Default title, description, share imageSite setup → SEO
Each page’s SEOWebsite → SEO
Your domainSite setup → Domains

After the first deploy, add the site’s domain (analytics counts visits only from your domains) and run Check the site. On Vercel or Netlify, environment variables go in the project’s settings; Vite writes them into the build, so redeploy after changing one.

Build your site with AI

Build the site with Claude Code (or any AI editor) and it’s managed from here the moment it’s deployed.

Connect your AI to this website project, then ask it to build your site — “a two-page site for my bakery: a home page and an about page, and a menu of our products”. While it writes the code, it puts everything the site shows into this project instead of into the code:

  • Site setup — name, logo, favicon, colours, font, contact details, social links, default SEO, tags, and the domains it’s deployed on.
  • Pages — each with its SEO and its content blocks in order: headings, text, buttons, lists, cards, images.
  • Images — uploaded to your Media library.
  • Lists — products, services, team, testimonials — become models of their own, linked where they belong, with their public API on.
  • Analytics — the tracker on every page.

The site’s code reads all of it from the site API. Once deployed, change a heading in Contents, a price in Products or the favicon in Site setup, and the live site shows it within a minute — no code change, no redeploy.

Building again

Asking the AI to rebuild or change the site updates the same pages, blocks and records rather than adding copies: pages are matched by path, blocks by their slug on the page, list records by a field such as their slug. A block the AI drops is archived — hidden from the site, still in the panel. Note that a rebuild writes the AI’s text over edits you made in the panel to the same blocks.

The AI shows you the pages and lists it plans before writing them, and nothing is saved if any part is invalid. Its key needs Can build, and your role needs Build and Records: Add and Edit.

Blogs, products and more

A website project is a full project: build a Posts or Products model, make it public (List and Read one, open to anyone), and your site lists them through the public API. Add the sign-in widget for members’ areas, and the tracker to count visits.

Starter code from a template

A website made from a template can come with the code its site starts from.

When the template has starter code, the website’s home shows a Starter code card: a link to the repository, a Deploy it button for its host, and the settings (environment variables) the code needs — your project’s API address and public name already filled in. Copy the repository (or press Deploy it), paste the settings where the host asks for them, and the site shows your pages and content straight away. Change the code as you like; it reads everything through the site API.

Troubleshooting

SymptomWhy, and what to do
“No published page at that path”The page is still a draft, or its path differs — /about, not about.
A block doesn’t showIt’s on another page, Draft, or Is visible is off.
/site returns 404The project is an app — the site API is for website projects.
A tag isn’t on the siteRun Site setup → Check the site: it says whether the analytics script is on the page and which tags it found.
The menu is missing a pageIt isn’t published, or In the menu is off.
Changes take a minute to appearYour site caches the answers (revalidate: 60 above). That’s on your side.