TL;DR: I built MagicKit — a free AI toolbox for image generation, AI writing, and video making. No sign-up, no API key, no paywall. The whole thing is open source on GitHub.
Every AI tool these days wants you to sign up, hand over an API key, or subscribe before you can even try it. I wanted the opposite: open the page and just create.
So I spent a few evenings building MagicKit — three tools in one page:
| Layer | Choice | Why |
|---|---|---|
| Backend | Node.js + Express | One file, easy to deploy |
| Frontend | Pure HTML/CSS/JS | No build step, no framework bloat |
| AI | Pollinations free API | No key required |
| Video | FFmpeg | Battle-tested, runs on a tiny VPS |
The entire backend sits at around 60 MB RAM, because my server only has 1.6 GB to work with.
The free image API only allows one queued request per IP. Concurrent requests instantly return 429 Queue full. My first naive implementation fell over immediately.
The fix:
async function generateImageWithRetry(prompt, width, height) {
for (let attempt = 0; attempt < 5; attempt++) {
await globalRateLimitGate(); // 3s minimum spacing
const file = await downloadWithCurl(buildUrl(prompt, width, height));
if (!isRateLimitError(file)) return file;
await sleep(3000 * (attempt + 1)); // 3s, 6s, 9s...
}
throw new Error('Image service busy, please try again');
}
socket hang up from the HTTP client
Node's https module kept dropping connections to the image endpoint under slow responses. I replaced it with a curl child process:
curl -L --max-redirs 5 --max-time 120 --connect-timeout 10 -o output.jpg "$URL"
Boring, predictable, and it never hangs half-open.
My first video pipeline used zoompan + xfade filters together. On a 2-core box with 1.6 GB RAM, long runs produced truncated, unplayable MP4s.
The reliable version uses the concat demuxer and a single simple filter for scaling/padding:
ffmpeg -f concat -safe 0 -i list.txt \
-vf "scale=1080:1920:force_original_aspect_ratio=decrease,\
pad=1080:1920:(ow-iw)/2:(oh-ih)/2,format=yuv420p" \
-c:v libx264 out.mp4
No fancy transitions, but the file always plays. Lesson: on constrained hardware, finish reliably beats fancy.
1.6 GB RAM means nothing can be buffered in memory. Generated images go straight to disk, videos stream through FFmpeg, and the queue keeps at most one job in flight.
🔗 Live demo: http://47.80.8.174
💻 Source: https://github.com/kaketiti/magickit
Self-hosting takes about a minute:
git clone https://github.com/kaketiti/magickit.git
cd magickit
npm install
npm start
It's MIT licensed — fork it, remix it, deploy your own.
Feedback is genuinely welcome — what would you add first? Drop a comment or open an issue on GitHub.