Recursivity
All projects
Open source

Jiffy

GIF search without the walled garden

View on GitHub
LanguageTypeScript
InterfaceWeb
DeploySingle Docker container
LicenseMIT
  • Giphy and Klipy results interleaved into one grid, every tile badged with the service it came from.
    Giphy and Klipy results interleaved into one grid, every tile badged with the service it came from.

Find an animated GIF, copy it, send it to a friend. Jiffy queries Giphy and Klipy simultaneously and interleaves the results into one grid, so you are not picking a provider before you have picked a GIF.

It is a single self-contained container — no database, no volumes, nothing to persist — which makes it a good fit for a NAS, a Raspberry Pi, or any always-on box.

Built to be pointed at the open internet

Anyone who can reach the port could otherwise burn through your provider quota, so Jiffy rate-limits its own API before the request ever reaches an upstream. The default is 60 requests per minute across search, autocomplete, trending, and the proxy.

TRUST_PROXY_HEADERS is off by default, and the reasoning is documented rather than assumed: exposed directly, every caller shares one bucket and the limit acts as a global cap; behind a reverse proxy that sets the header, you get per-client limits. Trusting the header without a proxy in front would let anyone spoof it and skip the limit entirely. The app also sets its own CSP and security headers, so a bare docker compose up is protected without nginx in the picture.

Keys stay the operator's business

Provider keys are read at runtime and never baked into the image, so the same image works for anyone. Starting with no keys at all is safe: the app comes up healthy and searches simply return nothing until one is added.

Jiffy ships plain-text attribution — a footer line and a per-result source badge — and deliberately nothing more. No provider logo assets are bundled. Both GIPHY and KLIPY require branded marks for public deployments, and the README is explicit that meeting those terms is the operator's responsibility, including the genuinely unresolved question of where marks belong in a grid that interleaves two providers.

Stack

FrameworkNext.js with TypeScript, standalone output
ProvidersGiphy and Klipy clients behind a shared interleaving/multiplexing layer
ProtectionSelf-imposed rate limiting, CSP and security headers set by the app
DeployOne container on port 3003; a ready-made nginx config with TLS ships in deployment/
Requirements64-bit OS — Next.js ships no native binaries for 32-bit ARM