Self-hosted timer generator with visual presets, evergreen deadlines, API key auth, and multi-layer caching. Zero external dependencies.
Each preset configures colors, fonts, box styles, and separators. Override any parameter via URL.
No SaaS fees, no vendor lock-in, no external dependencies. Just PHP + GD.
Rounded, gradient, or outlined boxes around each digit group with configurable padding and radius.
Configurable colon or dash separators between DD:HH:MM:SS groups, auto-sized and centered.
Relative countdowns that start from "now". Perfect for landing pages and automated funnels.
Pin a deadline to a user ID. First visit saves the deadline, subsequent visits use it.
PHP filesystem cache + Cache-Control headers + CDN edge caching. Most requests never hit PHP.
Per-key daily quotas, IP rate limiting. Control who generates timers and how many.
BebasNeue, Inter Bold, Montserrat Bold. All OFL licensed. Auto-layout picks optimal size.
Local or remote images with cover, contain, or stretch fit. Transparent GIF support via chroma key.
No Docker, no build tools, no database. Just clone, configure, and point your web server.
Get the source code and set up API keys.
The filesystem cache needs writable directories owned by your web server user.
Configure Caddy, nginx, or Apache with PHP-FPM to serve the project directory.
If you use StackPilot for VPS management, deploy with a single command:
./local/deploy.sh countdown-timer --ssh=vps --domain=timer.example.com
All GIF generation requires a valid API key. Add &key=YOUR_KEY to every request. Keys are stored in keys.json with per-key daily quotas.
Normal evergreen timers reset on every page load. Add a uid parameter to pin the deadline to a specific user. First request saves the deadline, all subsequent requests count down to the same moment.
All parameters are passed as URL query strings. Presets set defaults that individual parameters can override.
| Parameter | Description | Default |
|---|---|---|
| key required | API key for authentication | - |
| preset | Named preset (dark-boxes, gradient-cards, minimal-light, bold-color, transparent) | - |
| time | Absolute target datetime (e.g. 2026-12-25T00:00:00) | now |
| evergreen | Relative duration (e.g. 2h, 1d 2h 30m, 90m) | - |
| uid | Unique ID for persistent evergreen deadline | - |
| tz | Timezone (e.g. Europe/Warsaw) | UTC |
| width | Image width in pixels (100-1200) | 640 |
| height | Image height in pixels (40-400) | 140 |
| seconds | Animation frames / duration (1-120) | 30 |
| boxColor | Background color (hex without #) | 000 |
| fontColor | Digit color (hex) | fff |
| font | Font: BebasNeue, Inter-Bold, Montserrat-Bold | BebasNeue |
| fontSize | Digit font size in px (omit for auto) | auto |
| boxStyle | Box style: rounded, gradient, outline, none | none |
| boxBg | Box background color (hex) | 2d2d4a |
| boxRadius | Box corner radius in px | 10 |
| boxPadding | Padding inside boxes in px | 12 |
| separator | Separator between groups (: or - or empty) | : |
| sepColor | Separator color (hex) | fontColor |
| labelColor | Label text color (hex) | fontColor |
| bgImage | Background image (URL or local path) | - |
| bgFit | Background fit: cover, contain, stretch | cover |
| transparent | Transparent background (1 or true) | false |