Plain HTML
Next release
How midcode serves a folder of .html files itself, marks each element as it sends the page, edits the files in place and links midcode.css from every page.
This ships with the next release of midcode. The version you can download today (1.1.2) doesn’t have it yet.
midcode edits a folder of .html files with no framework and no build step. It serves the folder itself, reloads the page when a file changes, and writes each edit (text, classes, attributes, new elements, their order) into the .html file, with the rest of the file left byte for byte as it was. You don’t need Node or a package.json. midcode 1.1.2 and earlier open a folder of HTML to check every breakpoint and leave comments, without editing.
At a glance
| Plain HTML | |
|---|---|
| Detected by | An index.html at the folder’s root, and nothing else midcode knows how to run |
| Runs with | midcode’s own static server |
| Elements are marked by | That server, as it sends each page |
| Editing | Text, classes, attributes, tag; insert, move, duplicate, delete, wrap in a stack |
| Components | None: every element is written where it shows |
| Pages | Every .html file, at the path it’s served from. New pages at the top of the folder |
| Styles | mid: utilities, with midcode.css at the folder’s root and a <link> in every page |
| Tried with | A plain HTML site, and the one New project creates |
How midcode runs it
A folder is plain HTML when it has an index.html at its root and midcode finds nothing else to run:
none of the files that give away another stack (
artisan,manage.py,_config.yml,index.phpand the rest of the list in Any other stack);and either no
package.json, or one with none of the frameworks midcode knows and nodevscript.
midcode then serves the folder on http://localhost:4310 (the first free port from there) and writes one line in the log: midcode serves <folder> on http://localhost:4310. The server is small on purpose:
A folder’s address answers with its
index.html, and/aboutanswers withabout.html.Nothing is cached, so what you see is what’s on disk.
It reloads every frame when a
.html,.css,.js,.jsonor image file in the folder changes, whoever changed it: midcode, your editor or an agent.
How elements get their marks
The marks are added to each page as the server sends it. Your file:
<!doctype html>
<html lang="en">
<head>
<title>Oak and Iron</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<main>
<h1>Welcome</h1>
<p class="lead">Handmade furniture.</p>
</main>
</body>
</html>What the canvas receives:
<body data-mc="index.html:7:3">
<main data-mc="index.html:8:5">
<h1 data-mc="index.html:9:7">Welcome</h1>
<p data-mc="index.html:10:7" class="lead">Handmade furniture.</p>
</main>
<script>new EventSource('/__midcode/reload').onmessage = () => location.reload()</script></body>data-mc is the file, line and column where the element is written. The script at the end is what reloads the page. Both exist only in what’s served: the file on disk is never given a mark or a script. <html>, <head> and everything in it, <script>, <style> and <noscript> aren’t marked.
What you can edit
Click an element and the right panel shows where it’s written, as file:line. The editor’s pages describe each tool: select, move and resize, text and media, the style panel, Insert, Layers.
Text. Double-click and type:
- <h1>Welcome</h1>+ <h1>Welcome back</h1>A text is edited when everything inside its element is written text. A < you type is written as <.
Styles. The style panel writes classes on the element (see Styles below):
- <p class="lead">Handmade furniture.</p>+ <p class="lead mid:text-[20px] mid:md:text-[18px]">Handmade furniture.</p>Attributes. A link’s href, an image’s alt, an input’s type and placeholder, a <select> and its options are read from the tag and written back as plain attributes: a text as href="/about.html", a switch that’s on as disabled, a number as maxlength="40".
Structure. Insert adds plain markup at the selection or at the end of the page. Drag an element before, after or inside another one in the same file, and the comment right above it travels with it. Several elements can be deleted, moved or wrapped in a stack (⇧A) at once, and ⌥-drag leaves the element where it is and puts a copy where you drop it, in the same file.
midcode’s reader is tolerant on purpose. An <li> or a <p> that’s never closed, an attribute without quotes or a stray closing tag are read as they are and stay as they are: only the range you edit changes, and nothing is tidied or reformatted. A tag with a dash in its name (a custom element) is an element like any other.
Pages
Every .html file in the folder is a page, at the path the server answers it from:
| File | Page |
|---|---|
index.html | The home page |
about.html | /about.html |
blog/index.html | /blog |
blog/first-post.html | /blog/first-post.html |
node_modules and folders whose name starts with a dot or _ aren’t listed. Pick a page from the page menu in the top bar (Pages and navigation).
“New page” in that menu writes a new .html file at the top of the folder. Type its path without the extension: /about makes about.html. The file gets a copy of the home page’s <head>, so it links the same stylesheets, with its own <title>:
<!doctype html>
<html lang="en">
<head>
<title>About</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<main>
<h1>About</h1>
<p>A new page, made in midcode.</p>
</main>
</body>
</html>A path with a folder in it is refused (“In a folder of HTML, a new page goes at the top of the site: /about”), because the copied <head> links its files by paths that only hold at the top. Make a page in a subfolder by hand, or with your agent, and it appears in the list. “Remove” moves a page’s file to the Trash.
Site settings
The globe in the top bar opens Site settings. In a folder of HTML every page has its own <head>, so there are two kinds of form: one for the site, written in index.html, and one for each page, written in that page’s file (right-click a page in the page menu, then “Page settings…”). The title, the description, the language, search engines, the favicon and the social image are tags of that <head>:
<head>- <title>Oak and Iron</title>+ <title>Oak and Iron, furniture</title> <link rel="stylesheet" href="styles.css">+ <meta name="description" content="Handmade furniture."> </head>A tag that’s there has its value changed. A new one goes last in the <head>, indented and closed like its neighbours. Images are copied to the top of the folder as favicon and og-image, with the extension of the file you picked, and linked by that name.
Styles
A folder of HTML has no Tailwind build, so midcode uses its own utilities: Tailwind 4’s, written with the prefix mid: and turned into plain CSS by midcode itself. Your own stylesheets and classes aren’t touched.
The first style edit sets this up, as one undoable step:
midcode.cssis created at the folder’s root, with the CSS of exactly themid:classes found in your files.Every
.htmlpage gets one<link>to it at the end of its<head>, indented like the line above. A page in a subfolder gets the relative path (../midcode.css).
<link rel="stylesheet" href="styles.css">+ <link rel="stylesheet" href="./midcode.css"> </head>A page you add later gets its <link> with the next style edit. midcode.css is rewritten whenever the classes in your files change, and it’s part of your site: publish it with the pages. Colors, fonts and text styles you make in the Styles list of the Assets tab go in .midcode/theme.css. Without Tailwind explains the syntax and why every rule is !important; Theme and design tokens covers the theme file.
Limits
Markup that a script builds in the browser has no marks: it’s edited in that script.
Nothing is shared between pages. A header repeated in ten files is ten elements, and an edit changes the one you clicked.
A page has to be an
.htmlfile. The server doesn’t send an.htmfile as a page.midcode reads
{{ … }},{% … %}and{# … #}as something a template language computes, because many generators call their templates.htmltoo. A text with one of those in it isn’t edited on the canvas, and a{{you type is written as an entity.A new image is copied to
public/images/and referenced as/images/<file>, the way frameworks with apublic/folder serve it. midcode’s static server serves the folder itself, so after swapping an image check that itssrcpoints at where the file is.Insert’s interactive components (carousel, tabs and the like) are React and answer “Needs a React page”. Icons go in as inline SVG.
Components don’t apply here. the free canvas comes with the next release, kept in
midcode-scratch.htmlbeside your pages.A page’s form in Site settings has a title, a description, the search engines switch and a social image. The language and the favicon are in the site’s form, which writes
index.htmlonly: another page keeps thelangand the icon its own file says.
Troubleshooting
The canvas asks “How does this site run?” There’s no index.html at the root of the folder you opened, so midcode didn’t take it for a plain site. Open the folder that holds index.html, or tell midcode how to serve it: see Any other stack.
It opens as something else. A package.json with a dev script, or a file like index.php or _config.yml, makes midcode run that instead of serving the folder. The Dev server log in the top bar shows what it ran.
A style shows on one page and not on another. The other page has no <link> to midcode.css. Make any style edit and midcode adds the missing ones.