Guide

Stop picking from a list of 14 GIF makers. Build the one you actually need.

Every article about this starts the same way: 14 tools, feature matrix, pros and cons. The assumption is that one of those 14 matches your workflow. Often it does not. This guide shows the other option: describe the exact GIF generator you wish existed, and have mk0r build it as a real React app in the time it would take to sign up for Filmora.

m
mk0r
7 min
4.8from 10K+ creators
No account required
Real Vite + React + TypeScript output
Dev server + Chrome both live in the VM

The problem with every list of 14

A roundup of GIF makers ranks them on the features the reviewer could think of: file size, export formats, watermarks, price. None of those lists capture the thing that actually matters, which is whether the tool fits your workflow without friction. If your workflow is a little bit unusual, none of the tools fit.

A few examples pulled from real user prompts: a looping quote-card maker locked to one brand font and palette. A screen-recording to GIF tool with a fixed 80 by 24 terminal viewport. A meme builder with five preset captions for one specific community. A Discord sticker generator sized to 320 by 320 and capped at 500 KB. None of those is served well by a generic GIF maker. Each of those is a five-minute build for mk0r.

The shape of a custom build

When you type a prompt into mk0r, VM mode spawns a sandbox with a specific shape. It is the same shape every time, which means the agent can assume the same wiring on every build.

What runs inside the VM

Your prompt
A reference image
Drag-and-drop file
VM: Vite + Claude agent
React + gif.js app
Playwright test loop
Downloadable source

Three ports matter. The Vite dev server listens on 5173 and serves the app the agent is writing. A Playwright MCP server listens on 3001, giving the agent a scripted Chrome it can drive. A Chrome DevTools Protocol endpoint listens on 9222 and feeds screencast frames into a directory at /tmp/video/frames. That is how the agent sees what it just built, not just what it wrote.

Agent session, abbreviated

Why the test loop matters more than the prompt

A GIF encoder has a lot of ways to silently fail. gif.js will happily accept a tainted canvas and produce a blob of mostly transparent frames. MediaRecorder will produce a WebM file that plays in Chrome and not in Safari. A Blob URL can download correctly and contain nothing but a broken header. None of those surface until somebody runs the export and opens the resulting file.

Inside the VM, that somebody is the agent. After writing the code and booting the dev server, it drives a real Chrome to the app, clicks Export, and checks what comes out. If the blob is empty or the mime type is wrong, it reads the console, finds the error, patches the encoder, and tries again. By the time you see the app, the export has been verified end to end.

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

Four GIF generators people have actually built on mk0r

Quote card looper

Upload text, pick a palette, export a 1080 square GIF that loops a three-frame reveal. Fixed brand font baked in, no picker.

Terminal recording

Paste xterm.js output, replay at a chosen speed, export a 640 by 384 GIF with a title card. Cap on duration so nothing over 10 MB.

Discord sticker maker

Drop a PNG, apply a two-ring border, export a 320 by 320 APNG under 500 KB. Warns when the file exceeds Discord's limit.

Screenshot to annotated loop

Drop a screenshot, draw arrows and boxes on top, record a five-second loop of the annotations appearing, export as GIF.

The build, step by step

1

You describe the tool

One sentence is enough. The more specific the shape (canvas size, frame rate, export format, UI controls), the closer the first build lands.

2

VM spins up

A Firecracker-backed VM boots with Vite, Node, Playwright, and a real Chrome installed. The template is pre-warmed so boot is two or three seconds.

3

Agent writes the React app

A Claude agent scaffolds the Vite project, adds gif.js (or MediaRecorder for WebM, or a specific encoder you named), and wires the canvas to the encoder.

4

Agent tests the export

Playwright drives Chrome to localhost:5173, clicks the export button, and reads the download blob. If the mime type is wrong or the blob is empty, the agent patches and retries.

5

You get a working app

The dev server stays up, you can interact with it, iterate with follow-up prompts, and export the source whenever you want to keep it.

What the encoder code actually looks like

This is the core of what the agent writes for a canvas-based GIF. The specifics change per prompt: workers count, quality, delay per frame, palette strategy. The shape stays the same.

src/encodeGif.ts

The agent also drops the gif.worker.js file into the Vite public directory, because Web Workers need a separate script the browser can load. Nothing about that is invented for the prompt, it is the standard gif.js wiring, written correctly the first time because the agent has built it before.

Build your own versus download one of 14

FeaturePick-from-a-list toolsmk0r custom build
Starting shapeThe tool's default canvas, their palette, their UIYour exact canvas size, palette, and controls from sentence one
Export formatWhatever is in the export menuGIF, WebM, APNG, MP4, whichever you name
WatermarkFree tier usually stamps oneNone, you own the code
AccountSign up, confirm email, enter card for trialNo account, no email, no card
Workflow-specific presetsPreset library picker, 30+ generic optionsExactly the presets you asked for, hard-coded
Ownership of outputTheir format, their terms, their hostingReal React source, yours to download and deploy

When you should not build a custom one

If your need is genuinely generic (drop a video, trim, export as GIF, move on), one of the existing web tools like Ezgif or Canva is the right call. They are free and immediate. A custom build is worth the 90 seconds when any of the following is true:

  • Specific output constraints. Exact pixel dimensions, file size caps, specific codec.
  • Repeated workflow. You make the same kind of GIF often enough that picking the same options each time in a generic tool is wasted motion.
  • Brand constraints. One font, one palette, one frame, always. Bake them in.
  • Embed target. You want to ship the tool inside your own site so readers can use it, not just paste a screenshot from another app.

What gets shipped back to you

The VM runs for as long as you keep the tab open and for a while after. While it is running, 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. When you are done, you can publish the app to a subdomain, 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 license that says your output belongs to someone else. Just 0 Vite project with gif.js wired in correctly, 0 accounts to create, and 0 watermarks on your exports.

The kinds of tools worth building

Looping quote cardsTerminal recording to GIFScreenshot annotatorDiscord sticker packerMeme template with fixed captionsCode snippet to animated snippetSlide transition GIFsIcon reveal animationsLogo loops with brand paletteVideo clipper with size cap

Want a custom GIF tool built with you on the call?

Bring the constraints, we build the tool live in the VM. If the first one misses, we iterate on the same call.

Book a call

Frequently asked questions

Why build a GIF generator app instead of using one that exists?

Existing GIF makers are built for a general audience. If your workflow is specific, a stock tool is the wrong shape. Examples we have seen people ask mk0r for: a looping quote-card maker tuned to one brand font and palette, a terminal-recording to GIF with a fixed 80x24 viewport, a meme builder with five preset captions for a niche community, a Discord sticker generator sized for 320x320 and 500KB. Each of those takes longer to configure inside a generic app than mk0r takes to build from scratch.

How does mk0r actually render the GIF?

In VM mode, the agent scaffolds a Vite + React + TypeScript project and pulls in gif.js, which renders GIFs in the browser using Web Workers and a hidden canvas. The agent writes the encoding loop itself: grab frames from a canvas with ctx.drawImage, push them to the gif.js encoder with a specified delay, then call render() and listen for the finished blob. You get the source for the encoder setup, not a black-box export button.

How does mk0r know the export actually works?

The VM has a Playwright MCP server running on port 3001 and a Chrome DevTools Protocol endpoint on port 9222. After the dev server is up on port 5173, the agent navigates Chrome to the app, clicks the Export button, and watches for a download event. If the encoder throws or the blob is empty, the agent reads the console error and fixes the code before handing it back. The feedback loop is measured in seconds, not iterations.

What formats can the generated app export?

Animated GIF is the default because gif.js produces real .gif blobs. If you ask for WebP or APNG instead, the agent will swap in a different encoder (canvas.captureStream() piped to a MediaRecorder for WebM, then ffmpeg.wasm to convert, or the APNG encoder library). MP4 export works too through the MediaRecorder API with H.264. All of these run client side, no server roundtrip.

Can I keep the code?

Yes. Every app mk0r builds is real TypeScript you own. You can open the project from the dashboard, download the repo, deploy it to any host, and keep iterating. There is no proprietary format and no lock-in. If you just want to use it once and discard, that works too.

What frame rates and sizes are realistic in the browser?

Browsers can comfortably encode GIF at 10 to 20 fps at 640x480. Above 30 fps or 1280x720, gif.js slows noticeably because it runs Neuquant color quantization on the main thread during each frame. If you need smooth 60 fps output or large canvases, ask for WebM via MediaRecorder instead, then convert with ffmpeg.wasm. The agent will tell you if a request is going to make the browser tab hang.

How long does the build take?

A simple GIF generator (upload a PNG, add text, loop, export) usually lands in 90 seconds. A more elaborate one (multi-layer compositing, timeline scrubber, preset library) can take two to four minutes. The agent streams its work live, so you can watch the dev server boot, the encoder wire up, and the first export succeed in real time.

What if the GIF I want needs a source video?

The generated app can accept a video file via an <input type="file"> or drag-and-drop, decode it with a <video> element (which gives you per-frame access through requestVideoFrameCallback), and pipe those frames to gif.js. The agent writes that plumbing. You drop your mp4 in, it comes out as a GIF with whatever cropping, text overlay, or filter chain you described.

Describe the GIF generator you wish existed. No signup required.

Build My GIF Tool