Skip to content

krizzu/shortie

Repository files navigation

shortie-logo

A minimal, self-hostable URL shortening service with an admin dashboard for managing links.

Kotlin 2.2.20 Ktor 3.3.2 Kotlin Coroutines 1.10.2 Koin 4.1.1
Exposed 1.0.0-rc-4 HikariCP 7.0.2 Flyway 10.22.0
PostgreSQL Docker Friendly License: Apache 2.0

Features

  • Short-code based URLs for compact links
  • Custom aliases for human-readable links
  • Expiring links with expiration dates
  • Password protected links
  • Modern admin dashboard with a easy UI
  • Docker friendly set up

Demo

Getting started

Copy content from .env-example file into .env. Run docker via docker compose up -d.

Example compose.yaml file:

services:
  db:
    image: postgres:18.1
    container_name: db
    restart: unless-stopped
    volumes:
      - postgres_data:/var/lib/postgresql
    environment:
      POSTGRES_DB: ${APP_DB_NAME}
      POSTGRES_USER: ${APP_DB_USER}
      POSTGRES_PASSWORD: ${APP_DB_PASSWORD}
    healthcheck:
      test: [ "CMD-SHELL", "pg_isready -U ${APP_DB_USER} -d ${APP_DB_NAME}" ]
      interval: 1s

  shortie:
    image: krizzu/shortie:latest
    container_name: app
    restart: unless-stopped
    ports:
      - "4000:80" # api port
      - "4001:81" # dashboard port
    depends_on:
      - db
    environment:
      APP_API_PROXY_PORT: 4000 # keep this in sync with exposed api port for proper redirections
      APP_DB_URL: jdbc:postgresql://db:5432/${APP_DB_NAME}
      APP_DB_PASSWORD: ${APP_DB_PASSWORD}
      APP_DB_USER: ${APP_DB_USER}
      APP_ID_ALPHABET: ${APP_ID_ALPHABET}
      APP_AUTH_SECRET: ${APP_AUTH_SECRET}
      APP_ADMIN_PASSWORD: ${APP_ADMIN_PASSWORD}

volumes:
  postgres_data:

Design

Initial high level design: Excalidraw

Tech stack

  • Kotlin + Ktor → HTTP server and routing
  • Exposed + HikariCP + Flyway → Database access, pooling and migrations
  • Koin → Dependency injection
  • TypeScript + React → Frontend
  • Tanstack Router → Frontend router
  • Tailwind CSS → Styling

Local development

See DEVELOPMENT.md guide.

License

Copyright 2026 Krzysztof Borowy

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.