Guide

The HTML table generator that runs the table

Every other HTML table generator hands you a string and walks away. mk0r generates a live React + Tailwind table on a Vite dev server inside a sandbox, then uses Playwright to click the column headers in a real browser and verify sort works before you see the code.

Build a table now
m
mk0r
8 min
4.8from 10K+ creators
Tested in a real Chromium
Per-turn git history
No signup, no setup

What the top SERP for "html table generator" gives you

I searched the keyword and opened the first five results. Every one of them follows the same pattern: a form asking for row count, column count, border style, cell padding. You click generate, and it prints a blob of HTML and CSS at the bottom of the page with a copy button. Some let you toggle between div based and table based markup. One or two let you pick a color scheme. None of them do any of this:

Render the table in a real browserVerify the sort arrow flips the rowsType into the filter input and check the row countTest it at 375 px and at 1280 pxWire a fetch call to your endpointVersion every edit as a git commitShow you the rendered output in real timeLet you iterate by chattingRe-run accessibility checks after each changeScaffold virtualization for 10k rows

The gap between "a string of HTML" and "a table that actually works in your product" is everything you are going to do by hand after you paste the string. mk0r closes that gap inside the sandbox, not in your editor.

The pipeline under the hood

When you land on mk0r.com and describe a table, a single prompt fans out to a Vite + React + Tailwind project, a browser that can drive itself, and a git repo that captures the diff. Here is the shape of it.

What your prompt touches

Your prompt
Schema hints
Sort / filter spec
mk0r sandbox
Vite dev server
Playwright MCP
Git repo

The three destinations are not ideas. They are processes. Vite serves HMR from /app. Playwright MCP is registered for the agent in buildMcpServersConfig in src/core/e2b.ts around line 153. Git commits come from commitTurn after every chat turn that touches files.

The anchor fact: where Playwright lives in the VM

This is the part no competitor can copy, because it is wired into the sandbox template, not the prompt. When the agent is ready to click your freshly generated table, it calls a tool registered like this:

src/core/e2b.ts (excerpt)

CDP on 127.0.0.1:9222, Chromium binary at /usr/bin/chromium, both preinstalled in the E2B template. That is why Playwright driving the browser is free for every session: the browser is not downloaded on demand, it is already there. The agent navigates to http://localhost:5173 (the Vite dev server), finds the table it just generated, clicks the column header, and reads the DOM back to confirm the rows changed order. If they did not, the next agent turn fixes the broken sort comparator before the turn ends.

What the agent runs while you wait

You see the streamed chat in the UI, but in the VM there is a small terminal session happening for every turn. Below is a faithful trace of what the agent does after it writes UsersTable.tsx and wants to confirm sort works.

agent verifies table sort

The file the agent actually writes

Not pseudo-code, not "here is roughly what the component looks like." This is the kind of output a prompt like "table of users with sortable columns and a filter input" produces, committed to /app/src/components/ inside the VM.

/app/src/components/UsersTable.tsx

You can export the rendered HTML from the browser if you want a flat string. But the thing committed to the repo is a real component your follow-up prompts can keep evolving.

Static HTML generators vs. mk0r

FeatureStatic HTML table generatormk0r
OutputHTML + CSS stringLive React component on a running Vite server
Interactive behaviourNone (static markup only)Sort, filter, row-click tested by Playwright in Chromium
VerificationYou paste it and hopeAgent navigates to localhost:5173 and reads the DOM back
VersioningNoneEvery prompt becomes a real git commit
Signup requiredOften yes (to save tables)No account, no email
Iteration loopCopy, paste, edit by hand, repeatDescribe the change, agent rebuilds and re-tests
Responsive checksManual in your own browserViewport emulation inside the sandbox

What you can ask the table to do

Because the output is a live React component, not a dead string, anything you can describe to the agent lands in the file. Here is the typical surface area once the first table is on the screen.

Sortable columns, verified

The agent clicks every column header in the sandboxed Chromium and reads the row order back. If sort does not work, that turn does not finish.

Filter inputs that actually filter

Type-ahead filters get exercised by Playwright typing into the input and checking the DOM row count before and after.

Row actions

Edit, delete, view: each one ends up as a button with a handler, wired into local state or an endpoint you point the agent at.

Responsive without guesswork

Viewport emulation inside the VM means the agent tests 375 px, 768 px, and 1280 px before it declares the table done.

Accessible by default

Headers use <th scope>, sort state uses aria-sort, and keyboard focus order gets checked by the agent when you ask.

Exportable

Ask for a print stylesheet, a CSV export button, or a 'copy visible rows' action; all of them land as real code.

The numbers that matter for a table

For tables, "fast" is the interaction you did not notice. These are the ceilings the sandbox template and its preinstalled Chromium give you out of the box.

0Chromium CDP port in the sandbox
0Vite dev server port
0Signup steps before your first table
0+

Frame count of the hero concept clip rendered above. Remotion generates it on the fly, same engine the agent can use to animate your table cells.

0 rows

Typical starter dataset scaffolded by the agent. Swap for a fetch to your API in one follow-up prompt.

0 commit

Per chat turn that changes files. Undo is a git checkout, not a retype.

How to build a working table in five prompts

1

Describe the columns and intent

'Build a users table with columns name, email, role, last active. Seed it with 20 plausible rows.' The agent writes UsersTable.tsx and imports it into App.tsx.

2

Ask for sort and see it verified

'Make every column header sortable and show an arrow for the active column.' The agent adds the handler, Playwright clicks every header, and commits only once the DOM reflects the new order.

3

Add a filter input

'Add a filter input at the top that matches on name and email, case insensitive.' Playwright types a query and checks the row count shrinks as expected.

4

Wire it to your data

'Load rows from GET /api/users on mount, with a loading state.' The agent adds useEffect + fetch + error boundary, verifies the network tab, and handles the empty case.

5

Polish, responsive, ship

'Stack rows as cards below 640px and make the whole thing zebra striped.' Playwright emulates the mobile viewport, visually checks the stacked layout, and commits the final version.

When you still want a dead HTML string

Plenty of people search "html table generator" because they want a one-off block to paste into a CMS, a MailChimp template, or an old Wordpress editor. That is a legitimate use case, and mk0r handles it by degrading gracefully. Ask for:

"Give me a single HTML file with inline styles for a pricing table with 3 columns (Free, Pro, Team), 6 feature rows, and a highlighted Pro column. No JavaScript, no external CSS."

You get exactly that: a portable string you can paste. You lose the Playwright verification and the per-turn commit, because there is nothing to run. That is the trade. The key thing: you get to choose which output shape fits the job, and you do not have to leave the chat to switch modes.

Describe a table and watch it build

Frequently asked questions

Frequently asked questions

What does mk0r actually output when I ask for an HTML table?

A React component file at /app/src/ inside the sandbox, styled with Tailwind v4, rendered by Vite on port 5173. You see the rendered table live in a screencast while you type follow-up prompts. If you want raw HTML instead, ask for it: the agent can scaffold a standalone HTML + inline CSS version when that is what you need.

How does mk0r 'test' the generated table in a real browser?

The VM ships with Playwright MCP preconfigured. The wiring lives in buildMcpServersConfig in src/core/e2b.ts around line 153: `npx @playwright/mcp --cdp-endpoint http://127.0.0.1:9222` with env PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/usr/bin/chromium. The agent calls it to navigate to the Vite dev server, click column headers, type into filter inputs, and read back the DOM to confirm the sort order changed. Failures loop back into the agent, not you.

Can I get a plain HTML string I can paste into an existing site?

Yes. Ask for a single self-contained HTML file with inline styles. The agent generates one page, you copy it, done. You trade the Playwright verification and live preview for portability. For bigger tables with sort, pagination, and row actions, keep it in the React project and export when ready.

Is every iteration of the table versioned?

Yes. Every chat turn that produces file changes is a real git commit on a real repo inside the VM. 'Add a sortable Price column' is a commit. 'Make the rows striped' is a commit. 'Undo the striping' is a commit. The history lives in a Freestyle-hosted remote the session persists to, so you can diff and revert across turns.

Do I need to sign up, install anything, or pick a template?

No. Go to mk0r.com, type 'table of 20 users with columns name, email, role, and last active, sortable', and the VM, the git repo, the Vite server, and Playwright MCP all spin up for you. No account, no CLI, no plan picker.

How is this different from Jotform tables, tablesgenerator.com, or divtable.com?

Those tools output a markup string. Type your columns, click 'generate', paste into your site. There is no runtime and no testing. mk0r starts with a running app: the table is a React component, it renders in a browser inside the sandbox, and an agent with Playwright MCP proves that the column you marked as sortable actually sorts. The output is a working screen, not a string.

What if my table needs to fetch data from an API?

The generator scaffolds a fetch hook or mock data, renders the table, then lets you iterate. Ask for 'load from /api/users on mount' and the agent wires useEffect + fetch + error state and verifies the network tab in the sandboxed Chromium. If you have an endpoint, paste the schema into the chat; the columns get inferred from it.

Can the table be responsive without breaking on mobile?

Yes, and the agent checks it. Playwright MCP can emulate viewport sizes inside the sandboxed Chromium. Ask for a responsive layout and the agent typically switches to a stacked card layout below 640px, then re-checks the rendered output at both widths before declaring the turn done.

What about a huge dataset, does it stay fast?

For thousands of rows, ask for virtualized rendering. The agent can scaffold react-virtuoso or TanStack Virtual, verify scroll behavior in the sandbox, and confirm the DOM node count stays bounded. You get a performance profile you can trust because it ran in a browser, not in the agent's imagination.

The best way to understand this is to build one

Describe the columns. Ask for sort. Ask for a filter. Watch the agent verify it in Chromium. Every step is a git commit you can walk back.

Start building on mk0r