Short links, QR codes and a link-in-bio page β with analytics that tell you who's clicking.
Live demo β shrinkk.vercel.app
- Features
- Screenshots
- Tech stack
- Quick start
- Running against MongoDB
- Configuration
- Deploying to Vercel
- Project structure
- Routes
- Testing
- Contributing
- Author
- Random or custom aliases (
shrinkk.vercel.app/launch) - Titles, tags, search and tag filters
- Pause / resume links and set expiry dates
- Bulk actions β delete, pause, activate, tag or add to your bio page in one go
- Built-in UTM builder for campaign tracking
- Every user gets a public page at
/@username - Avatar upload, display name, bio and social icons (Instagram, X, TikTok, YouTube, LinkedIn, GitHub, email, website)
- Drag-and-drop button ordering with a live phone preview while you edit
- Six themes (Classic, Midnight, Minimal, Sunset, Forest, Mono) plus custom colours, button styles, corner radius and fonts
- Share sheet and a QR code for the page itself
- Clicks and profile views over 7, 30 or 90 days
- Bio click-through rate β how many visitors actually tap a button
- Breakdown by country, device, browser, OS, referrer and traffic source (direct, bio page or QR scan)
- Per-link analytics pages
- Privacy-friendly: no raw IP addresses stored, bots and your own visits aren't counted
- A styled QR code for every link and bio page
- Custom foreground/background colours, PNG or SVG download
- Change username, email or password
- Delete your account and all its data
- CSRF protection, rate limiting and bcrypt-hashed passwords
Dashboard![]() |
Links![]() |
Bio page editor with live preview![]() |
Link analytics![]() |
Account analytics![]() |
Create a link![]() |
Sign up![]() |
Settings![]() |
Public bio pages β three users, three themes:
Link-in-bio on the landing page:
Fully responsive β landing page, dashboard and links on a phone:
| Layer | Choice |
|---|---|
| Backend | Flask 3.1 (app factory + blueprints), Flask-WTF (CSRF), Flask-Limiter |
| Database | MongoDB via PyMongo; avatars in GridFS |
| Frontend | Server-rendered Jinja templates, Tailwind CSS v4, Alpine.js, Chart.js, SortableJS |
| Icons | Lucide + Simple Icons, compiled into one SVG sprite |
| Images | Pillow (avatars resized to 400Γ400 WebP), qrcode for QR codes |
| Hosting | Vercel β Python serverless function + static CDN |
| Tests | pytest + mongomock (no database needed) |
No database needed β the demo runs on an in-memory MongoDB with sample data.
git clone https://github.com/bishalde/Shrinkk.git
cd Shrinkk
# Python dependencies
python -m venv .venv && .venv/bin/pip install -r requirements-dev.txt
# Build CSS and the icon sprite
npm install && npm run build
# Run the seeded demo
.venv/bin/python scripts/demo.pyOpen http://localhost:8080 and log in with:
| Password | |
|---|---|
demo@shrinkk.app |
demo12345 |
Sample bio pages: /@bishal, /@sima, /@basak. Data resets when the server stops.
cp .env.example .env # set MONGO_URI and SECRET_KEY
.venv/bin/python scripts/init_db.py # create indexes, migrate data from older versions
.venv/bin/flask --app app run --debug --port 8080
npm run dev:css # optional: rebuild CSS as you edit templatesAccounts created before the revamp don't have a username yet β they're asked to pick one on their next login.
| Variable | Default | Notes |
|---|---|---|
MONGO_URI |
mongodb://localhost:27017 |
Any MongoDB / Atlas URI. mongomock:// gives a throwaway in-memory database |
MONGO_DB |
shrinkk |
Database name |
SECRET_KEY |
dev placeholder | Required in production β the app refuses to start without it. Generate one with python -c "import secrets; print(secrets.token_hex(32))" |
BASE_URL |
the visited domain | Optional. Forces the domain used in short links and QR codes. Leave unset and links follow whatever domain serves the site |
- Import the repo in Vercel.
vercel.jsonalready sets the build (npm run build), servespublic/from the CDN and routes everything else to the Flask function inapi/index.py. - Add
MONGO_URI,MONGO_DBandSECRET_KEYunder Project β Settings β Environment Variables. - In MongoDB Atlas, allow connections from Vercel (Network Access β
0.0.0.0/0). - Run
scripts/init_db.pyonce against the production database.
Visitor country and city come from Vercel's geo headers, so they only show up once deployed.
Docker
docker build -t shrinkk .
docker run -p 8080:8080 --env-file .env shrinkkβββ app.py # App factory: config, blueprints, error pages
βββ config.py # Settings read from the environment
βββ extensions.py # CSRF, rate limiter, repository access
βββ api/index.py # Vercel entry point
βββ models/ # MongoDB access: users, links, analytics events, GridFS media
βββ routes/
β βββ pages.py # Landing page + anonymous shortener
β βββ auth_routes.py # Sign up, log in, onboarding
β βββ dashboard.py # Dashboard, links, bio editor, analytics, settings
β βββ api.py # JSON endpoints used by the dashboard
β βββ public.py # /@username pages, QR codes, avatars, short-link redirects
βββ services/ # Link rules, themes, socials, QR, images, visitor info
βββ utils/ # Validators, formatting filters, serializers, auth helpers
βββ templates/ # Jinja layouts, pages, partials and UI macros
βββ assets/app.css # Tailwind source (design tokens + components)
βββ public/static/ # Built CSS, icon sprite, JS, favicon (served by the CDN)
βββ scripts/ # demo.py, init_db.py, build-icons.mjs
βββ tests/ # pytest suite
| Path | What it does |
|---|---|
/ |
Landing page with a quick shortener |
/signup, /login |
Authentication |
/dashboard |
Overview: stats, performance chart, top links |
/dashboard/links |
Search, filter, bulk-edit links |
/dashboard/links/<id> |
Per-link analytics and QR studio |
/dashboard/bio |
Bio page editor with live preview |
/dashboard/analytics |
Account-wide analytics |
/dashboard/settings |
Username, email, password, delete account |
/@<username> |
Public bio page |
/@<username>/qr.png |
QR code for a bio page (.svg too) |
/qr/<code>.png |
QR code for a short link (?fg=, ?bg=, ?dl=1) |
/<code> |
Short-link redirect (?src=bio / ?src=qr attribute traffic) |
.venv/bin/python -m pytestThe suite uses mongomock, so it runs without a database.
Contributions are welcome!
- β Star and fork the repo
- Clone your fork:
git clone https://github.com/<your-username>/Shrinkk - Create a branch:
git checkout -b my-feature - Make your changes and run
pytest - Commit and push:
git push -u origin my-feature - Open a pull request π
Bishal De
If Shrinkk is useful to you, you can support it here:
Thank you to everyone who has contributed to Shrinkk π










