Every meme app generator tutorial builds the same thing. Build the one your community needs.
Open any guide on this: imgflip's public API, two useState hooks, a single image with text on top and bottom. Fine for a portfolio project, wrong for an actual community. Drakeposting servers want a Drake-only picker. Office Slack wants a team-roast card sized for an unfurl. Expanding Brain needs four fixed rows, not two. You describe the shape, mk0r writes the React app that fits it.
The problem with every guide online
Search around for how to build a meme app. The result is always the same recipe: fetch from https://api.imgflip.com/get_memes, store the list in state, render one at a time, put two <input> elements on top, generate by POSTing your text fields back to imgflip. It is a portfolio exercise, not a meme app. You get someone else's template library, someone else's image hosting, and someone else's watermark.
A real meme community does not want the same 100 templates everyone has. A Discord server running a joke about their ops engineer wants three photos of the ops engineer, baked in, with the caption font and sticker pack they always use. A product team wants a "bug or feature" two-panel with their brand colors. A meme account wants a fixed six-panel Galaxy Brain, not two text fields over a generic image. None of the tutorials get within 10 feet of that.
mk0r treats your description as the spec. You say what templates go in, what the layout is, what the export target is, and the agent writes the component. The bake-in moves from "after you learn React" to "in the first prompt."
What the sandbox looks like
The VM is the same shape on every build. Three ports, always running, always reachable by the agent. That is why the agent can write, test, and hand you back a working app in one pass rather than a code dump for you to run yourself.
Inside the VM, during a build
The Vite dev server serves your app on localhost:5173 with HMR on. The Playwright MCP server on port 3001 gives the agent a scripted Chrome it can drive with tool calls. A Chrome DevTools Protocol endpoint on port 9222 feeds screencast frames into /tmp/video/frames so you can watch the agent work as it happens.
Why the test loop is the whole point
A meme app has a dozen quiet ways to ship broken. A canvas that loaded a cross-origin image with no crossorigin="anonymous" attribute goes tainted, and the next call to canvas.toBlob throws a SecurityError. A custom font loaded via CSS renders fine on screen but is not ready when dom-to-image snapshots the DOM, so the exported PNG uses a fallback. An SVG overlay that references external icons rasterises blank. None of those break the visible editor, all of them break the actual download.
The agent catches those in the VM, not in your browser. After writing the component and booting Vite, it drives Chrome to localhost:5173, clicks Download, and reads the resulting blob. If the blob is empty, the mime type is wrong, the dimensions do not match what you asked for, the agent reads the console, finds the error, patches the code, and retries. You see the successful export on the first load.
Five meme apps people have actually built on mk0r
None of these would be served by a generic meme tool. Each is built around a specific community's shape, then used in that community and nowhere else.
Drakeposting, Drakes only
One template, four caption slots, fixed Impact with a black stroke, 1080 by 1350 export. No other templates, no font picker, no watermark.
Expanding Brain, six rows
Six fixed rows with the Galaxy Brain backgrounds, one caption per row, 1200 by 1800 export. Captions wrap if over 80 characters.
Team roast card
Slack unfurl-sized (1200 by 630). Upload a photo of a coworker, pick a preset roast, exports as PNG. Locked to one brand color.
Bug or feature two-panel
Product-team meme. Left panel bug, right panel feature. Tailwind-based caption box, company font, 1600 by 800 export for a wiki page.
Discord sticker packer
Upload PNG, apply two-ring border, export 320 by 320 APNG under 500 KB. Warns if the file exceeds Discord's limit.
The build, step by step
You describe the app
Templates, layout, caption rules, export size, export format. The more specific you are, the closer the first build lands. A sentence is enough, a paragraph is better.
VM boots
A pre-warmed sandbox comes online with Vite, Node 20, Tailwind CSS v4, Playwright, and a real Chromium. Boot takes two or three seconds because the template is kept warm.
Agent writes the React component
The agent scaffolds the editor, wires the template picker to an array, adds the caption box, and hooks the Download button to dom-to-image or a canvas encoder, depending on what you asked for.
Agent tests the export in real Chrome
Playwright opens localhost:5173, picks each template, types a test caption, clicks Download, and checks the resulting blob. If a template taints the canvas, the agent patches the code and retries before you see anything.
You get a working app with source
The dev server stays up. Iterate with follow-up prompts, publish to a subdomain, or download the Vite project as a zip. No proprietary format, no lock-in, no watermark.
What the export code actually looks like
This is the shape the agent writes for a DOM-based meme export. The specifics change per prompt (which library, what size, what format) but the shape stays the same. The comment on line 5 is the one people miss in tutorials, and the one that makes the test loop matter.
The crossorigin plumbing sits one level up, in the image tags that load your templates. The agent sets crossorigin="anonymous" on every template image and serves them from the Vite public directory so they pass the same-origin check. That is also the thing the Playwright test verifies: it clicks Download once, reads the blob size, and if it is smaller than a real PNG should be (under 1 KB), patches the crossorigin attribute and retries.
What the agent checks before handoff
- Vite dev server reachable on 5173
- No console errors on initial load
- Each baked-in template renders in the picker
- Caption input updates the visible meme in real time
- Download button produces a blob over 1 KB
- Exported PNG mime type is image/png
- Export dimensions match what you asked for
- Custom fonts are loaded before the export snapshot
Custom build versus every existing option
| Feature | Imgflip, Canva, Mematic | mk0r custom meme app |
|---|---|---|
| Templates | Their library, thousands of generic ones | Exactly the templates you uploaded, and nothing else |
| Layout | Fixed: one image, top and bottom caption | Any layout: 2, 4, 6 panels, grid, card, custom |
| Export size | Their default, sometimes with a paywall | The exact pixel dimensions you asked for |
| Watermark | Often on free tier | None, you own the code |
| Source | Hosted web tool, no source | Real Vite + React + TypeScript, download the zip |
| Account | Email, password, sometimes card for trial | No account, no email, no card |
| Community-specific shape | Pick the closest generic, live with it | Built to your specific layout from sentence one |
| Export verified | They hope it works | Playwright clicks Download and reads the blob |
When you should not build a custom one
If your need is genuinely one-off (make one Drakeposting meme right now, post it, move on) Imgflip is the right call. It is free, it is immediate, and the friction of spinning up anything custom is not worth it. A custom build starts making sense when any of the following is true:
- The meme has a specific shape. A six-panel Galaxy Brain, a trading card, a Slack unfurl, a fixed-ratio Discord sticker. The existing tools do not have a template for that exact layout.
- It is a community tool. You are making the same kind of meme inside your Discord, Slack, or team every week. Picking the same options in a generic tool every time is wasted motion.
- Brand constraints. One font, one palette, one frame, always. Bake them in.
- You want to embed it. Your site, your members, your subdomain. You want readers to generate the meme themselves, not link them to someone else's tool with their watermark on the output.
What you get back
The VM keeps the dev server running while your tab is open, and for a while after. You interact with the live app, refine with follow-up prompts, and see every change reflected in the same Chrome the agent has been testing in. When you are done, publish the app to a subdomain from the dashboard, or download the source as a real Vite project with a package.json, a src directory, and a working npm run dev.
No proprietary format, no lock file pointing at a vendor database, no licence saying your output belongs to someone else. One Vite project with 0 accounts to create, 0 watermarks on the export, and 0% of the source in your hands.
The kinds of meme apps worth building
Want your community meme app built live on a call?
Bring the templates, the constraints, and the target community. We build the app together in the VM and iterate until the export looks right.
Book a call →Frequently asked questions
Why not just use Imgflip or Canva?
Those tools cover the generic two-text-field meme. That works if your meme is a Drake pointing at two options. It falls apart the moment your community has a shape those tools do not have: a six-panel Galaxy Brain, a trading-card layout with stats in the corner, a Slack roast card sized for an unfurl, a niche format only your Discord server uses. mk0r builds to that specific shape because you describe the shape, not pick from a list.
What does mk0r produce that Imgflip does not?
Real TypeScript source. A Vite project with a src directory, a package.json, a working npm run dev, a React component that holds your templates as first-class data, and an export function that renders to a canvas and downloads the PNG. You own all of it. Imgflip hands you an image URL behind their branding and a login screen; mk0r hands you code you can deploy to your own domain.
How does the agent know the export actually works?
The VM has a Playwright MCP server on port 3001 and a Chrome DevTools Protocol endpoint on port 9222. After writing the React component and starting Vite on 5173, the agent drives a real Chrome to the app, clicks the Download button, and inspects the blob that comes out. If the mime type is wrong or the canvas was tainted (a cross-origin image with no crossorigin attribute) the agent sees the empty blob, reads the console, fixes the code, and tries again. By the time you load the preview, a download has already been completed and checked end to end.
Can I give it my own templates?
Yes. Drop an image on the prompt box and the agent stores it in public/templates/, references it by relative URL, and wires it into the template picker. Drop four and get a four-template picker. Drop a zip and the agent extracts and inventories them. Your templates become fixed data in the app, not slots you have to fetch from a third-party API on every build.
What about animated memes, GIFs, stickers?
Static meme export goes through dom-to-image or html2canvas for a fast PNG. If you ask for animated output, the agent swaps the encoder: gif.js for looping GIFs, MediaRecorder for WebM, a canvas.captureStream() pipeline for short MP4s. APNG for Discord stickers. All of these run client side, no server roundtrip, all verified in the VM's Chrome before handoff.
Do I need to know React?
No. You describe the app in plain words. The agent scaffolds, wires, and tests. If you want to make changes without understanding the code, you keep prompting: move the caption box up, bump the bottom padding, swap the default font to Impact with a three-pixel black stroke. The agent applies each change and re-tests in the same Chrome.
How long does a typical build take?
A straightforward meme app (pick a template, type two lines, download) lands in 60 to 90 seconds. Something more specific (four fixed templates, custom font loaded from Google Fonts, 1200 by 1200 export for Instagram, watermark toggle, Discord-sized 320 by 320 APNG output) takes two to three minutes. You watch the dev server boot, the component come together, and the first export succeed in real time.
Can I share or deploy the generated app?
Yes. The VM runs while your tab is open. You can publish the app to a subdomain directly from the dashboard, or download the source as a real Vite project and deploy to any host. No vendor format, no proprietary runtime, no licence that claims your output belongs to someone else.
What stops the meme app from breaking when I add a new image?
The agent stays in the loop after handoff. When you add a new template through the prompt box, the agent drops the file in public/templates/, extends the templates array, and re-runs the Playwright check: open the app, pick the new template, type a line, click download, confirm the PNG came out. If the aspect ratio is off or the caption runs off the image, it adjusts the component before handing it back.
Describe the meme app your community needs. No signup required.
Build My Meme App