Build with AI
Let Claude build the site, structured for cmsspot
cmsspot has a free build guide you can add to your own Claude. It is an MCP server with no login and no actions: it only answers how a site should be put together to be fast, easy to find and editable in cmsspot from the first day.
Add it to Claude
The server lives at mcp.cmsspot.com, where its own page describes the tools, shows what a check looks like, and answers the questions. The button opens Claude's connector dialog with the address filled in:
In Claude Code or the terminal:
claude mcp add --transport http cmsspot-build https://mcp.cmsspot.com/build
In Claude.ai or Claude Desktop by hand: Settings, Connectors, Add custom connector, and paste https://mcp.cmsspot.com/build. There is nothing to sign in to.
Then ask for a site
Say what the business is and which pages you want. Claude reads the guide, builds the files from the templates, writes the content, and checks every page against the guide before it hands them over. For example:
You get a folder with index.php, pages/, include/header.php, include/footer.php, css/style.css and .htaccess, ready to upload. Connect it in cmsspot, point Pages at pages/, and the owner can edit it.
Convert an existing site
Have a site on a builder, a theme or another CMS? The guide server has a convert_page tool that does the mechanical part of bringing a page to the cmsspot structure: title and description into variables, the page split into a page file and header and footer includes, lazy loading on images, builder class names removed. It then lists what needs a reader: which text should be a real heading or paragraph, which cards should be a group, which images lack alt text. The prompt convert_site takes Claude through a whole site this way and ends with a check on every page.
Start from a Figma design
Figma should not export the HTML. Read the design through Figma's own MCP server in the same Claude session, and let Claude build the pages from the design data with this guide. How Figma to cmsspot works.
What the guide gives Claude
- A tool that returns the guide, in full or one section at a time.
- Starter files for the page, article, header, footer, a repeated block, the stylesheet and
.htaccess. - A converter that does the safe, mechanical part of bringing an existing page to the structure.
- A check that reads one page and lists what to fix: title and description lengths, headings, images, scripts, schema and secrets.
- Three ready prompts:
build_site,convert_siteandfigma_to_site.
The server reads only what you send it, stores nothing, and has no access to your sites or your cmsspot account.
The guide, if you prefer to read it yourself
For the shorter, human version with a quick start, content types, a contact form and where to find SFTP access at your host, see Getting started.
cmsspot edits plain HTML and PHP sites over SFTP. It reads your pages and turns headings, paragraphs, images, links and the menu into fields, and it writes only the changed field back. It does not need a special structure. But a site built the way described here is easier to edit, faster to load, and better for search engines and AI assistants. Follow it when you build a new site, and the owner gets clean editing from day one.
This guide is written for an AI assistant or a developer building a small business site: five to forty pages, a few articles, no shop and no user accounts.
1. Folder layout
/ the website root (point cmsspot at this folder)
index.php the front page (a single file that becomes a tab, or a page in pages/)
pages/ one file per page: about.php, services.php, contact.php
articles/ one file per article, same shape as a page
include/
header.php <!doctype> to the opening of <main>, plus the menu
footer.php closing of <main> to </html>
css/
style.css one stylesheet for the whole site
uploads/ images the owner adds (cmsspot uploads here)
img/ images that belong to the design (logo, icons)
.htaccess clean URLs and caching
robots.txt
sitemap.xml
Rules:
- One page per file. Never generate pages from a database or a loop.
- Use
pages/andarticles/(or any folder names; cmsspot lets the owner map a folder to a tab). - Keep the shared parts in
include/header.phpandinclude/footer.php. cmsspot gives them their own tabs. - Keep the owner's images in
uploads/and the design images inimg/. The owner should never need to touchimg/. - No build step. The files on the server are the files the browser gets.
2. The page file
Every page sets its own title and description as plain variables at the top, then includes the header, writes its content inside <main>, and includes the footer.
<?php
$page_title = 'Oak dining tables made to order in Aabenraa';
$page_desc = 'Solid oak dining tables from 160 to 300 cm, built in our workshop in Aabenraa. Three finishes, delivery across Denmark, six weeks from order.';
require __DIR__ . '/../include/header.php';
?>
<main>
<h1>Oak dining tables made to order</h1>
<p>We build solid oak dining tables in our workshop in Aabenraa, from 160 to 300 cm, with or without extension leaves.</p>
<h2>Three finishes</h2>
<p>Natural oil, white oil or smoked. All three are hard wax oils that are easy to maintain at home.</p>
<h2>Price and delivery</h2>
<p>A 200 cm table starts at 14,900 kr. Most tables leave the workshop within six weeks, and we deliver across Denmark.</p>
<a class="button" href="/pages/contact/">Ask for a quote</a>
</main>
<?php require __DIR__ . '/../include/footer.php'; ?>
Why it matters:
$page_titleand$page_descas plain quoted strings. cmsspot finds the variable, edits it, and counts the full title with the site name the way Google shows it. Do not build the title with functions or concatenation on the page.- A real
<h1>, real<h2>sections and real<p>paragraphs. They become fields. Text wrapped in nested<div>s or<span>s does not. - Keep logic out of the page. If something needs PHP, do it in the header or in a separate include. cmsspot locks text inside PHP blocks, so the owner cannot edit it.
- Links as plain
<a href>. Buttons as<a class="button">. cmsspot edits the text and the target.
3. The header include
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?= htmlspecialchars($page_title ?? 'Oak & Ash Workshop') ?> | Oak & Ash</title>
<meta name="description" content="<?= htmlspecialchars($page_desc ?? 'Handcrafted oak furniture from Aabenraa.') ?>">
<link rel="stylesheet" href="/css/style.css">
<link rel="icon" href="/img/favicon.svg" type="image/svg+xml">
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"LocalBusiness","name":"Oak & Ash Workshop","address":{"@type":"PostalAddress","streetAddress":"Havnevej 12","postalCode":"6200","addressLocality":"Aabenraa","addressCountry":"DK"},"telephone":"+45 74 62 10 20","url":"https://oakandash.dk/"}
</script>
</head>
<body>
<header class="site-header">
<a class="logo" href="/"><img src="/img/logo.svg" alt="Oak & Ash Workshop" width="140" height="40"></a>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/pages/furniture/">Furniture</a></li>
<li><a href="/pages/workshop/">The workshop</a></li>
<li><a href="/pages/contact/">Contact</a></li>
</ul>
</nav>
</header>
Rules:
- Title and description printed from the variables with a fallback. The
| Oak & Ashsuffix is counted as part of the title. - The menu is a plain
<ul>of<li><a>inside<nav>. That is what the Menu tab edits. - Site-wide schema (LocalBusiness or Organization) in the header. Page-specific schema (an Article, a FAQ) goes in the page, as its own
<script type="application/ld+json">block with plain JSON, no PHP inside. - No framework CSS, no font loader, no analytics script by default. Add them only when asked.
4. The footer include
<footer class="site-footer">
<p>Oak & Ash Workshop · Havnevej 12, 6200 Aabenraa · <a href="tel:+4574621020">+45 74 62 10 20</a> · <a href="mailto:hello@oakandash.dk">hello@oakandash.dk</a></p>
<p>Open Monday to Friday 8 to 16. Visitors welcome on Fridays from 13.</p>
</footer>
</body>
</html>
Phone, address and opening hours in the footer are the typical globals: the owner marks them once in cmsspot and they are kept in sync everywhere they appear.
5. Repeated blocks (groups)
Team members, services, cases, prices: write every item with the same markup, inside one container.
<section class="team">
<h2>The team</h2>
<article class="person">
<img src="/uploads/anna.jpg" alt="Anna Berg, cabinetmaker" width="400" height="400" loading="lazy">
<h3>Anna Berg</h3>
<p>Cabinetmaker since 2009. Anna builds most of our tables.</p>
</article>
<article class="person">
<img src="/uploads/jonas.jpg" alt="Jonas Holm, joiner" width="400" height="400" loading="lazy">
<h3>Jonas Holm</h3>
<p>Joiner and the one who answers the phone.</p>
</article>
</section>
The owner can turn this into a group in cmsspot and then add, reorder and remove items. For that to work, every item must be the same element with the same children in the same order.
6. Images
- Always
widthandheight, so the layout does not jump while loading. alttext that says what is in the picture, with the name and the place if they matter.loading="lazy"on every image below the first screen. Never on the hero image.- Size images for the layout: a 400 px column does not need a 3000 px file. Use WebP or a well-compressed JPEG.
- Owner images in
uploads/. The owner replaces an image in cmsspot and the new file goes there.
7. CSS and scripts
- One stylesheet,
css/style.css, loaded in the head. No framework. Write the ten to twenty rules the site needs. - System fonts or one self-hosted font file. No external font service by default.
- No JavaScript unless a feature needs it. A mobile menu toggle is a few lines inline at the end of the body. Anything else is a decision, not a default.
- Nothing render-blocking before the content. The page should paint as soon as the HTML arrives.
8. SEO
- Title: 40 to 60 characters including the site suffix. The most important words first.
- Description: 120 to 158 characters. Say what the page offers and why to click.
- One
<h1>per page that says what the page is about.<h2>for each section. - A sitemap.xml that lists every page and article. cmsspot can rebuild it.
- Clean URLs without
.php, through.htaccess. - Internal links in the text, with real anchor text.
9. GEO (being quoted by AI assistants)
- One question per section: the heading asks it, the first paragraph answers it in two or three sentences.
- Put the name, the place and the fact in the sentence: "Oak & Ash builds oak tables in Aabenraa, from 14,900 kr." That is the sentence an assistant quotes.
- Prices, hours, addresses and conditions in text, never only in an image or a table built by script.
- Short paragraphs. Plain words. No tabs, sliders or accordions hiding the content.
- A FAQ section on the most important pages, with FAQPage schema in a plain JSON-LD block.
10. .htaccess
RewriteEngine On
# Clean URLs: /pages/about/ -> pages/about.php, /about/ -> about.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ $1.php [L,QSA]
RewriteRule ^(pages|articles)/([a-z0-9-]+)$ /$1/$2/ [R=301,L]
# Front page
DirectoryIndex index.php
# Cache static files
<FilesMatch "\.(css|js|png|jpg|jpeg|webp|svg|woff2)$">
Header set Cache-Control "public, max-age=2592000"
</FilesMatch>
# Protect includes
<FilesMatch "^(header|footer)\.php$">
Require all denied
</FilesMatch>
Adjust the rewrite rules to the folder names you chose. The include/ folder must not be reachable over the web.
11. Security basics for the site itself
- No passwords, API keys or tokens in any page or include. If a form needs a mail service, keep the key in a file outside the web root and exclude it in cmsspot.
- Forms: validate on the server, add a honeypot field, and rate limit.
header("X-Content-Type-Options: nosniff")andX-Frame-Options: SAMEORIGINfrom.htaccessor the header include.- No
eval, noincludeof user input, no file writes from the pages.
12. From a Figma design
Figma does not export HTML that fits this guide. Export plugins produce deep div nesting, absolute positioning and generated class names, which is the opposite of what cmsspot, Google and AI assistants read well. Do not export HTML from Figma.
Use Figma's own MCP server instead, in the same Claude session as this guide. Figma's MCP server gives the assistant the design as data: frames, text, colours, spacing, fonts and image exports. The assistant then writes the pages from that data, following this guide.
How to do it:
1. Add Figma's MCP server to Claude. The hosted one is the one to use: claude mcp add --transport http figma https://mcp.figma.com/mcp. Figma's guide: https://help.figma.com/hc/en-us/articles/32132100833559 2. Add this guide: claude mcp add --transport http cmsspot-build https://mcp.cmsspot.com/build. 3. Select the frame in Figma and ask: "Read the selected design through Figma and build it as a plain PHP site for cmsspot. Follow the cmsspot guide. Headings, paragraphs and buttons must be real h1, h2, p and a elements. Export the images and put them in img/. One stylesheet with the design's colours and type. Then run check_page on every page."
What to insist on when the assistant works from a design:
- A text layer that looks like a heading becomes an
h2, never adivwith a big font. - A row of cards that look the same becomes one repeated block with identical markup (section 5), so it can become a group.
- Spacing and colours go into
css/style.cssas a few rules, not as inline styles on every element. - The layout is built with flex or grid in CSS, not with absolute positions from the canvas.
- Decorative images go in
img/; content images the owner will change go inuploads/.
13. Converting an existing page
An existing page, from a builder, a theme or another CMS, can be brought to this structure in two steps.
The mechanical step is safe to automate. The convert_page tool does it: it moves the title and description into $page_title and $page_desc, splits the file into a page, a header include and a footer include when it can see where the content starts and ends, adds loading="lazy" to images below the first, and strips builder class names. It never guesses about meaning.
The meaning step needs a reader. After convert_page, the assistant goes through the page and:
- turns text that works as a heading into a real
h2orh3, and text that works as a paragraph into a realp; - rewrites repeated cards or list items so every item has the same markup;
- moves phone, address and opening hours into the footer include, so they can become globals;
- removes scripts and stylesheets the page no longer needs;
- writes
alttext for images that lack it, and addswidthandheight; - shortens or lengthens the title and description to the ranges in section 8.
Then check_page on every page, until nothing is left to fix. Converting a twenty-page site this way is usually an afternoon.
14. Checklist before handing the site to cmsspot
- Every page sets
$page_titleand$page_descas plain strings at the top. - Header and footer are includes, and the menu is a
<ul>inside<nav>. - Every page has one
<h1>,<h2>sections and real<p>paragraphs. - Repeated blocks use the same markup for every item.
- Every image has
width,height,alt, andloading="lazy"below the fold. - One stylesheet, no framework, no scripts unless needed.
- Titles 40 to 60 characters, descriptions 120 to 158.
- Site-wide schema in the header, page schema in plain JSON-LD blocks.
- Clean URLs, sitemap.xml and robots.txt in place.
- No secrets in any file under the web root.
When this holds, connect the site in cmsspot, point Pages at pages/ and Articles at articles/, add index.php as an extra file on Pages, and everything is editable without touching the code.
Get started
Connect the site you built
Create a free account, add the server, and the owner can edit from the first day.