r2u is a Persian-first URL shortener — a fork of Kutt with full i18n support, RTL layout, Jalali calendar, and Vazirmatn typography. Shorten links, manage custom domains, view statistics, and more.
- Persian-first: Default locale is Persian (fa) with RTL layout and Vazirmatn font
- Full i18n: Language-agnostic translation system — add any locale by dropping a JSON file
- Jalali calendar: Persian (Shamsi) dates and digits throughout the UI
- Clean layer separation: i18n core, Persian locale, and branding are in separate branches for upstream contribution
- Built on Kutt v3.2.5: All upstream features plus i18n
- Created with self-host in mind:
- Zero configuration needed
- Easy setup with no build step
- Supporting various databases (SQLite, Postgres, MySQL)
- Ability to disable registration and anonymous links
- OpenID Connect (OIDC) login
- Custom domain support
- Set custom URLs, password, description, and expiration time for links
- View, edit, delete and manage your links
- Private statistics for shortened URLs
- Admin page to manage users and links
- Bilingual UI — switch between English and Persian with one click
- RTL layout with logical CSS properties (auto-flips in both directions)
- Customizability and themes
- RESTful API
The only prerequisite is Node.js (version 20 or above). The default database is SQLite.
When you first start the app, you're prompted to create an admin account.
- Clone this repository:
git clone https://github.com/aminupy/r2u.git - Install dependencies:
npm install - Initialize database:
npm run migrate - Start the app:
npm run dev(development) ornpm start(production)
docker compose upVarious docker-compose configurations are available. Use docker compose -f <file_name> up:
docker-compose.yml: SQLite (default)docker-compose.sqlite-redis.yml: SQLite + Redisdocker-compose.postgres.yml: Postgres + Redisdocker-compose.mariadb.yml: MariaDB + Redis
r2u supports multiple languages via flat JSON locale files in /locales. Currently shipped:
| Locale | Language | Direction | Font |
|---|---|---|---|
en |
English | LTR | Nunito |
fa |
Persian | RTL | Vazirmatn |
To add a new language, create locales/XX.json with the same key set as en.json, then add XX to SUPPORTED_LOCALES in server/utils/i18n.js.
Key parity between locales is verified by node scripts/check-i18n-keys.js.
The app is configured via environment variables in a .env file. View .example.env for all options.
All variables are optional except JWT_SECRET on production.
| Variable | Description | Default |
|---|---|---|
JWT_SECRET |
Signs authentication tokens. Use a long random string. | - |
PORT |
App port | 3000 |
SITE_NAME |
Website name | r2u |
DEFAULT_DOMAIN |
Domain the app runs on | r2u.ir |
LINK_LENGTH |
Shortened address length | 6 |
DISALLOW_REGISTRATION |
Disable registration | true |
DISALLOW_ANONYMOUS_LINKS |
Disable anonymous link creation | true |
TRUST_PROXY |
App is behind a reverse proxy | true |
DB_CLIENT |
Database client (better-sqlite3, pg, mysql2) |
better-sqlite3 |
DB_FILENAME |
SQLite file path | db/data |
ENABLE_RATE_LIMIT |
Enable rate limiting | false |
MAIL_ENABLED |
Enable emails (signup, reset, reports) | false |
See .example.env for the full list.
Place custom styles, images, or HTML in the /custom folder:
custom/
├─ css/ # CSS files loaded after styles.css
├─ images/ # Override default images (logo, favicon, etc.)
├─ views/ # Override Handlebars templates
See the Kutt customization docs for details.
- ShareX — Use r2u as your default URL shortener in ShareX.
- Alfred workflow — alfred-kutt
- iOS shortcut — Kutt shortcut
Third-party packages:
| Language | Link | Description |
|---|---|---|
| Python | kutt-cli | CLI client |
| Rust | urlshortener | URL shortener library |
| Node.js | node-kutt | Node.js client |
| Go | kutt-go | Go client |
| Kubernetes | Helm Chart | K8s deployment |
r2u is a fork of Kutt by Pouria Ezzati and The Devs. Logo design by Muthu.
Pull requests are welcome. For the i18n system, see the implementation plan and Persian glossary.