meem makr is a client-side React + TypeScript web app for creating lolcat-style meme images. It lets you upload a local image, paste one from the clipboard, or capture one from your webcam, crop and resize it in the browser, add classic top and bottom meme captions, and export the result as a PNG or JPG.
- Local image upload with no server-side components
- Clipboard image paste with
Cmd+V/Ctrl+V - Webcam capture with an in-preview 3-2-1 countdown
- Drag-to-reposition crop with zoom control
- Top and bottom caption fields
- Impact-style meme text rendering with white fill and black outline
- PNG and JPG export
Install dependencies:
npm installStart the development server:
npm run devThen open the local URL shown by Vite, typically:
http://127.0.0.1:5173/
- Upload an image from your device, paste one from the clipboard, or open the webcam and capture a frame after the countdown.
- Drag the image preview to reposition the crop and use the zoom slider for framing.
- Enter top and bottom caption text, then export the result as PNG or JPG.
Create a production build:
npm run buildPreview the production build locally:
npm run previewEach build embeds a build number (the git commit count at build time) and a build timestamp, shown below the GitHub link in the app header. These are computed in vite.config.ts via git rev-list --count HEAD and baked in as compile-time constants, so they require a git checkout to be present at build time.
The app is served at /meem-makr/ via pm2 + serve on port 4001.
First deploy (run once on the server to set up the directory):
pm2 deploy ecosystem.config.cjs production setupDeploy:
pm2 deploy ecosystem.config.cjs productionNginx config — nginx proxies /meem-makr/ to the local serve process. The trailing slash on proxy_pass strips the prefix before forwarding, so serve sees plain paths rooted at dist/:
location /meem-makr/ {
proxy_pass http://localhost:4001/;
proxy_set_header Host $host;
}- The app runs entirely in the browser and does not upload images to a server.
- Clipboard paste depends on the browser providing image data through the paste event.
- Webcam capture requires browser camera permission.
- Exact Impact rendering depends on whether the font is available on the local system. The app falls back to similar heavy sans-serif fonts when needed.