A self-hosted Bitly clone: create short links, serve the redirect, record every click, and browse the analytics from a dashboard app.
Windmill concepts demonstrated
- Raw app — the dashboard: create, list, inspect and delete links.
- HTTP route trigger — serves the public redirect at
l/:slug. - Preprocessor — turns the raw HTTP request into the handler's arguments.
- Custom HTTP response — returns a real 302 redirect instead of JSON.
- Datatables — stores the links and every click.
Layout
bitly_create_link.ts Create a short link (slug optional → generated)
bitly_list_links.ts All links + total clicks, last click, status
bitly_get_link_detail.ts One link + 30-day click series (analytics)
bitly_delete_link.ts Delete a link, clicks cascade
bitly_redirect.ts Route handler: resolve slug, log click, 302
bitly_redirect.http_trigger.yaml
bitly_dashboard__raw_app/ Dashboard UI (create / list / inspect / delete)
How it runs
- A visitor hits
<instance>/api/r/w/<workspace>/l/<slug>. - The preprocessor pulls
slug,referrer,user_agentoff the request. mainlooks up the link inbitly.links, inserts a row intobitly.clicks(best-effort — a failed insert never blocks the redirect), and returns the 302.- The dashboard reads the aggregates back through the CRUD scripts.
Try it locally
wmill script preview f/bitly/bitly_list_links -d '{}'
wmill app dev # from inside bitly_dashboard__raw_app/