Stretch. Shrink. Share.
A sleek, Flask-powered web app for shortening, expanding, QR-coding, and validating URLs.
- Expand URLs β Reveal full links.
- QR Code Generator β PNG/SVG output, logo optional.
- URL Shortener β Create branded short links (
/abc123). - Basic Link Checker β HTTP status & reachability tests.
- User Management β View, verify, or delete users via
/admin/users. - Rate Limiting Controls β Fine-tune abuse protection.
- Backend: Flask, TinyDB, Flask-Login, Flask-Bcrypt, Flask-Limiter
- Frontend: TailwindCSS, Vanilla JS
- QR Codes:
qrcode+ Pillow - Utilities:
requests,shortuuid
Create a .env file in your project root:
SECRET_KEY=your_super_secret_key
APP_BASE_URL=http://localhost:5000git clone https://github.com/your-username/slinkr.git
cd slinkr
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python app.pyFirst user to register becomes an admin and is auto-verified. Subsequent users require admin approval.
-
Shorten a URL
curl -X POST "$APP_BASE_URL/api/shorten" \ -H "Authorization: Bearer $TOKEN" \ -d "url=https://example.com" # β {"short_url":"http://.../Ab3XyZ"}
-
Generate a QR Code
curl "$APP_BASE_URL/api/qrcode?url=https://example.com" \ --output qr.png -
Check a Link
curl -X POST "$APP_BASE_URL/api/check" \ -H "Authorization: Bearer $TOKEN" \ -d "url=https://example.com"
cp .env.example .env
# Edit .env: set SECRET_KEY (openssl rand -hex 32), APP_BASE_URL,
# RESEND_API_KEY + EMAIL_FROM for login emails, AUTO_VERIFY_DOMAINS,
# and optionally ADMIN_EMAIL to pre-create the admin account
docker compose up -d --buildThe app listens on 127.0.0.1:8000 (via gunicorn) with data persisted in the
slinkr_data volume (/data in the container, SQLite in WAL mode). A Redis
sidecar provides shared rate-limit storage. Put Nginx or Caddy in front for
HTTPS, keep TRUST_PROXY=1, and set SESSION_COOKIE_SECURE=1 once HTTPS is
live.
Login is passwordless: users enter their email, receive a six-digit code
(sent via Resend), and are logged in β accounts are
created automatically on first login. Domains listed in AUTO_VERIFY_DOMAINS
are verified immediately; everyone else needs admin approval in
/admin/users before they can shorten links or run health checks. Without
a RESEND_API_KEY, codes are printed to the container logs (dev mode).
Existing TinyDB data (slinkr_data.json) is migrated into SQLite automatically
on first start if present in the data directory.
Pushes to main (and v* tags) build a multi-arch image via GitHub Actions
and publish it to GitHub Container Registry. On your VPS, edit
docker-compose.yml to use the image instead of building:
services:
slinkr:
image: ghcr.io/<your-github-username>/slinkr:latestIf the package is private, log in first:
echo $GH_PAT | docker login ghcr.io -u <username> --password-stdin
(PAT needs the read:packages scope.)
-
Use Gunicorn + Nginx or Caddy.
-
Do not run
app.pywithdebug=Truein production. -
Swap TinyDB for PostgreSQL/SQLite for higher scale.
-
Configure
Flask-Limiterwith Redis:limiter = Limiter(app, storage_uri="redis://localhost:6379")
Please read our Code of Conduct first, then:
- Fork the repo
- Create a feature branch
- Run tests:
pytest - Open a Pull Request
MIT Β© Michael Borck
