Guide

An HTML code generator that refuses Inter on purpose

mk0r is the only HTML code generator in this category with an anti-AI-slop design contract baked into every sandbox. The agent that writes your HTML reads that contract on startup. Everything about the default output, fonts, colors, icons, copy, is shaped by rules you can read in the repo.

m
mk0r engineering
9 min
4.9from Builders who wanted HTML that does not look AI-generated
globalClaudeMd at src/core/vm-claude-md.ts line 19 ships as /root/.claude/CLAUDE.md
Line 144 of the contract: never default to Inter, Roboto, Arial, or system fonts
Line 170 anti-pattern: purple or indigo gradients on white backgrounds

Most tools in this category have no opinion

Open a handful of the sites that currently rank for this topic and the pattern is the same. You fill in a form for a table, a form, or a pricing grid. You click generate. You get a blob of HTML that you paste somewhere. The output uses Inter because the template used Inter. It has a centered hero with a purple to indigo gradient button because that is the default the template author shipped five years ago. It has a row of uniform cards with icons because that is what a feature section looks like to the template.

None of those tools have an opinion about what good HTML looks like. They have a template. The template has a visual style frozen in time, and every page you generate inherits it. If you want something that does not look like every other generator output on the internet, you are in charge of changing it after the fact.

mk0r is different because the agent that produces your HTML reads a file before it starts. That file is opinionated about every one of those defaults. It is versioned in a git repo. You can read it. You can argue with it. You can override it per request. But it exists, and the HTML you receive is shaped by it whether you know the file is there or not.

The anchor fact: a markdown file inside every sandbox

Open src/core/vm-claude-md.ts in the appmaker repo and jump to line 19. There is a TypeScript constant called globalClaudeMd. The body of that constant is a markdown document. Lines 97 through 221 are the Design Constraints, Frontend Design Quality, and Copywriting sections. Those are the rules. The excerpt below is a readable pull of the most load-bearing ones.

src/core/vm-claude-md.ts (excerpt from globalClaudeMd)

That constant does not just sit in source. The build step at scripts/prepare-e2b-context.ts writes it to disk as /root/.claude/CLAUDE.md before the E2B template is sealed. When a sandbox spins up for your session, that file is already there. When Claude Code initializes inside the sandbox, it reads the file into context. By the time you type the first character of your HTML description, the agent has already absorbed the contract.

How the contract reaches the VM

The shipment path is one function call per file. scripts/prepare-e2b-context.ts imports globalClaudeMd from src/core/vm-claude-md and writes it to a build-context directory. The E2B template build copies that directory into the image at the same path. Then every new sandbox starts with the file in place.

scripts/prepare-e2b-context.ts

Two other files on the same path matter for the HTML you get back. skillFrontendDesign becomes /root/.claude/skills/frontend-design/SKILL.md, a more aggressive design layer that loads when the agent is asked to build a UI. skillCopywriting becomes /root/.claude/skills/copywriting/SKILL.md, which shapes every bit of text inside the HTML.

What the HTML-writing agent is looking at before it writes

globalClaudeMd
skillFrontendDesign
skillCopywriting
mk0r agent
Your HTML
Copy in the page
Layout

The full contract, line by line

These are the floor defaults for any HTML mk0r produces. Every one of them is overridable with an explicit request, and every one of them is in the repo as a checkable fact. No vibes, no hidden prompt.

Baked into /root/.claude/CLAUDE.md

  • Three colors maximum (black, white, one accent)
  • Tailwind palette for accents, no custom hex unless you supply one
  • Light theme default, dark only on request
  • No decorative icons on feature cards or marketing blocks
  • No icon library installed (Lucide, Heroicons, FontAwesome) without asking
  • Never default to Inter, Roboto, Arial, or system fonts
  • Distinctive display font plus refined body font from Google Fonts
  • No purple or indigo gradients on white backgrounds
  • No uniform rounded cards in a grid with icons
  • No generic centered hero with a gradient button
  • No Lorem Ipsum or placeholder images left in
  • No exclamation points, ever

Default HTML shape: category norm vs. mk0r

FeatureTypical HTML code generatormk0r
Default font for headingsInter, Roboto, or the system font stackA distinctive Google Fonts display face picked per project
Decorative icons on feature cardsYes, often from Lucide or Heroicons by defaultForbidden by contract unless you ask for them
Purple to indigo gradient heroThe category default for a decadeListed as an anti-pattern in the contract, line 170
Uniform cards-in-a-grid with iconsThe category default for a decadeListed as an anti-pattern, line 171
Exclamation points in generated copySprinkled throughoutBanned, line 199 of the contract
Placeholder images or Lorem Ipsum left inCommon in generated outputListed as an anti-pattern, line 175
Where to audit the aesthetic contractNo such contract existssrc/core/vm-claude-md.ts, lines 97 to 221

Numbers you can audit in the repo

0
Line of vm-claude-md.ts where globalClaudeMd begins
0
Line of the “never default to Inter” rule
0
Colors the contract allows by default
0
Named anti-patterns in the contract (lines 170 to 175)

Each of these resolves to a specific part of src/core/vm-claude-md.ts. Clone the repo, open the file, count the lines.

Contract philosophy

The rules at line 99 are prefixed “These rules apply unless the user explicitly overrides them.” That phrase is the whole point. The contract is a floor, not a ceiling. You get non-generic output by default. You keep full power to steer it anywhere, including back into category-standard shapes if that is what a specific page needs.

What you do not get is the outcome most generators deliver, which is a page that looks like every other generator output on the internet because the template had no taste.

Copy inside the HTML follows the same model

The Copywriting section starts at line 186 of globalClaudeMd. It is not a style guide for the landing page of mk0r, it is a style guide for any copy inside the HTML the agent generates for you. Empty states, error messages, button text, onboarding screens, they all inherit these rules.

src/core/vm-claude-md.ts (copy rules excerpt)

The concrete effects: your generated pricing page does not say “Get started on your journey.” Your form submit button does not say Submit. Your 500 state does not say “An error occurred.” Those are category-standard outputs. The contract is specifically against them.

Walk-through of one prompt

Here is what happens between you typing a description and getting a preview URL back. Every step either reads the contract or applies it.

1

VM boots, agent starts

E2B template mk0r-app-builder starts a sandbox. Claude Code launches inside it and immediately scans /root/.claude/ and /app/.

2

Agent reads /root/.claude/CLAUDE.md

That file is the globalClaudeMd constant from src/core/vm-claude-md.ts line 19. Design Constraints, Frontend Design Quality, and Copywriting sections enter context.

3

Agent loads /root/.claude/skills/frontend-design/SKILL.md

A second layer: the skill description tells the model to commit to a bold aesthetic direction and never converge on generic choices across generations.

4

You type your HTML description

The agent now plans the HTML against the rules it just read. Three colors max, no decorative icons, distinctive typography.

5

Agent writes .tsx into /app/src

Components land in /app/src/components/. Tailwind v4 compiles. Vite hot-reloads the preview on port 5173.

6

You receive a URL, not a snippet

The preview URL serves the rendered HTML. The aesthetic floor is set by a file you can open and audit.

When this is the wrong tool

If you want HTML that looks exactly like a classic form generator would produce, use a classic form generator. If you are auditing a legacy file somebody else wrote, a linter or formatter is the right tool. If you are producing constraint-heavy email HTML where tables are the layout language, the design contract here does not translate.

mk0r is the right pick when you want the default to be non-generic, the aesthetic rules to be traceable to a file in a repo, and the output to be a running preview URL you can iterate on by describing changes in plain English.

Watch an HTML page get generated against the contract

Bring a page you want built. We will open vm-claude-md.ts together on the call and watch the agent pull from it while it writes.

Frequently asked questions

Frequently asked questions

Where exactly is the anti-AI-slop contract defined?

In one TypeScript constant called globalClaudeMd at src/core/vm-claude-md.ts line 19. The body of that constant is a markdown file. Lines 97 to 184 inside it are the Design Constraints and Frontend Design Quality sections, which include the three-color maximum at line 102, the no-decorative-icons rule at line 111, the AI slop header at line 127, the no-Inter rule at line 144, and the anti-pattern list at lines 170 to 175. That constant is written to /root/.claude/CLAUDE.md inside every sandbox by scripts/prepare-e2b-context.ts at line 73. The agent that produces HTML reads that file on startup.

So the agent will literally refuse to use Inter?

It will refuse to default to Inter. The rule at line 144 of vm-claude-md.ts is: 'Never default to Inter, Roboto, Arial, or system fonts.' If you ask for Inter by name, the agent honors your request. If you give no direction, it will pick a distinctive display font paired with a body font from Google Fonts instead. The contract is about defaults, not about overriding your taste when you have one.

What else is in the design contract besides fonts?

Three colors maximum (black, white, one accent), Tailwind palette only for the accent unless you give a brand color, light theme by default, no decorative icons anywhere, no icon libraries installed without a request, no purple or indigo gradients on white backgrounds, no uniform cards-in-a-grid with icons, no generic centered hero with a gradient button, no Lorem Ipsum, no exclamation points in copy, no buzzwords like streamline or seamless. The full list is lines 97 to 221 of src/core/vm-claude-md.ts.

Is this just prompt-level advice, or is it actually applied?

Applied. The file ships as /root/.claude/CLAUDE.md, which Claude Code reads automatically at session start. The model treats it as persistent context for every turn inside the session. When the agent writes a component, it is planning against those rules. Every HTML page you get back from mk0r is the output of a model that had just finished reading a markdown file telling it what generic AI output looks like and not to produce it.

There is also a frontend-design skill, what does that add?

skillFrontendDesign at src/core/vm-claude-md.ts line 340 gets written to /root/.claude/skills/frontend-design/SKILL.md. It is a second, more aggressive layer that loads when the user asks for a UI. It repeats the anti-slop framing, instructs the agent to commit to a bold aesthetic direction before writing any code, and warns against converging on common choices like Space Grotesk or purple gradients across generations. Between the global CLAUDE.md and this skill, the agent is told twice, in two different places, not to produce generic HTML.

Does the contract cover copy inside the HTML too?

Yes. The Copywriting section starts at line 186 of globalClaudeMd. It forbids exclamation points, filler words (very, really, just, actually, basically, simply), and marketing buzzwords (streamline, optimize, innovative, cutting-edge, revolutionary, seamless). Button text must describe the action, not say Submit or Continue. Empty states must guide the user to a real next action. Error messages must say what went wrong and what to do about it. If mk0r writes HTML for a pricing page, the copy inside the page is shaped by those rules.

Why does the generator category not already do this?

Because most HTML code generators are static form-to-snippet converters. You pick options, they interpolate templates. There is no model, there is nothing to ask for taste, there is no place for a design opinion to live. The tools that do wrap a model almost universally feed it a neutral system prompt that describes the task and nothing about aesthetics. mk0r is opinionated on purpose, and the opinions are in-repo, checkable files rather than vibes inside the prompt.

Can I disable the contract if I want generic-looking HTML?

You can override it per prompt. Tell the agent 'use Inter, use a purple-to-indigo gradient, add emoji icons on every card,' and it will. The rules at line 99 are prefixed 'These rules apply unless the user explicitly overrides them.' The point is the floor, not the ceiling. You get a non-generic default and you keep the ability to dial it back toward whatever convention you need.

How do I verify any of this myself?

Clone the appmaker repo, open src/core/vm-claude-md.ts, jump to line 19, read. Then run npm run e2b:prepare and look in docker/e2b/files/root/.claude/CLAUDE.md, which is the literal file that ships inside the sandbox. Every claim on this page points back to a line number, and the file is under a few thousand lines total. You can audit the entire design contract in under ten minutes.

Do I need to sign up to try it?

No. Open mk0r.com, type what you want, hit enter. An anonymous Firebase session is created on page load and owns your prototype. Sign-in is only requested when you want to publish to a custom domain or switch to a paid model variant. The path from cold visit to first generated HTML page is one prompt.