Guide

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.

m
mk0r
8 min
4.8from 10K+ creators
No account required
Real Vite + React + TypeScript output
PNG export tested in a real Chrome

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

Your sentence
Template images
Follow-up prompts
VM: Vite + Claude agent
React meme component
Playwright export test
Downloadable source

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.

0Vite port
0Playwright MCP port
0Chrome DevTools port
0sSeconds, typical build

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.

Agent session, abbreviated

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

1

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.

2

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.

3

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.

4

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.

5

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.

src/exportMeme.ts

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

FeatureImgflip, Canva, Mematicmk0r custom meme app
TemplatesTheir library, thousands of generic onesExactly the templates you uploaded, and nothing else
LayoutFixed: one image, top and bottom captionAny layout: 2, 4, 6 panels, grid, card, custom
Export sizeTheir default, sometimes with a paywallThe exact pixel dimensions you asked for
WatermarkOften on free tierNone, you own the code
SourceHosted web tool, no sourceReal Vite + React + TypeScript, download the zip
AccountEmail, password, sometimes card for trialNo account, no email, no card
Community-specific shapePick the closest generic, live with itBuilt to your specific layout from sentence one
Export verifiedThey hope it worksPlaywright 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

Drakeposting, Drakes onlyGalaxy Brain six-panelBug or feature two-panelSlack roast cardTeam trading cardDiscord sticker packerOffice insider joke templateLaunch-day hype generatorCat meme from your cat onlyProduct bug-screenshot captionerQuarterly retro meme cardReaction GIF with your face

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