Skip to content
JGuckPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Shorty Logo

⚑ Shorty - URL Shortener

A modern, full-stack URL shortener application built with Kotlin. Features a beautiful React-based frontend and a robust Kotlin/JVM backend with real-time communication via Ktor and kotlinx RPC.

πŸš€ Features

  • URL Shortening: Quickly convert long URLs into short, shareable links
  • Base64 URL-Safe Encoding: Efficient 6-character shortened URLs using Base64Url encoding
  • Real-time API: WebSocket-based communication between frontend and backend using kotlinx RPC
  • Beautiful UI: Modern, responsive React interface with smooth animations
  • Database Persistence: SQLite database for storing URL mappings
  • Comprehensive Testing: Full test coverage with kotlin.test for both backend and common modules
  • Cross-Platform: Kotlin Multiplatform project (JVM backend, JS frontend, Common shared API)

πŸ“‹ Project Structure

Shorty/
β”œβ”€β”€ common/                 # Shared Kotlin code
β”‚   β”œβ”€β”€ src/commonMain     # Shared API definitions
β”‚   β”‚   β”œβ”€β”€ ShortId.kt     # Base64 encoding/decoding utilities
β”‚   β”‚   └── ShortyApi.kt   # RPC interface definition
β”‚   └── src/commonTest     # Shared tests
β”‚
β”œβ”€β”€ server/                # Kotlin/JVM Backend
β”‚   β”œβ”€β”€ src/main/kotlin
β”‚   β”‚   β”œβ”€β”€ Application.kt # Server entry point
β”‚   β”‚   β”œβ”€β”€ de/shorty/service/
β”‚   β”‚   β”‚   β”œβ”€β”€ ShortyImpl.kt      # Core service implementation
β”‚   β”‚   β”‚   └── model/ShortsTable.kt  # Database table definition
β”‚   β”‚   └── de/shorty/api/
β”‚   └── src/test/kotlin
β”‚       └── ShortyImplTest.kt      # 17 comprehensive test cases
β”‚
β”œβ”€β”€ frontend/              # Kotlin/JS Frontend
β”‚   β”œβ”€β”€ src/jsMain/kotlin
β”‚   β”‚   β”œβ”€β”€ App.kt         # Main application component
β”‚   β”‚   β”œβ”€β”€ Main.kt        # Entry point
β”‚   β”‚   β”œβ”€β”€ RPC.kt         # RPC client initialization
β”‚   β”‚   └── components/
β”‚   β”‚       β”œβ”€β”€ Logo.kt           # Logo component
β”‚   β”‚       β”œβ”€β”€ ShortLinkForm.kt  # URL input form
β”‚   β”‚       β”œβ”€β”€ ShortLinkResult.kt # Result display
β”‚   β”‚       └── ErrorMessage.kt   # Error handling
β”‚   └── src/jsMain/resources
β”‚       └── shorty_logo.png       # Application logo
β”‚
└── build.gradle.kts       # Root build configuration

πŸ› οΈ Technology Stack

Frontend

  • Kotlin/JS: Kotlin compiled to JavaScript
  • React 19: Modern UI framework
  • Emotion CSS: Styled components solution
  • Ktor Client: HTTP/WebSocket communication
  • kotlinx RPC: Type-safe RPC over WebSocket

Backend

  • Kotlin/JVM: Backend server logic
  • Ktor Server: HTTP server and WebSocket support
  • Exposed: SQL framework for database operations
  • SQLite: Embedded SQL database
  • kotlinx RPC: Type-safe RPC support
  • kotlinx Coroutines: Async/await support

Testing

  • kotlin.test: Lightweight testing framework
  • JUnit Platform: Test runner

πŸ“¦ API Reference

ShortyApi Interface

@Rpc
interface ShortyApi {
    suspend fun shortenUrl(url: Url): ShortId
    suspend fun resolveShortId(shortId: ShortId): Url?
    suspend fun getAllShortIds(startIndex: Long = 0, count: Int = 100): List<Pair<ShortId, Url>>
    suspend fun deleteShortId(shortId: ShortId): Boolean
}

URL Format

Shortened URLs follow the pattern:

http://localhost:8080/s/{base64EncodedId}

Where {base64EncodedId} is a URL-safe Base64 encoded 32-bit integer (6 characters).

Helper Functions

  • encodeShortIdToBase64(shortId: ShortId): String - Encode a ShortId to Base64Url
  • decodeShortIdFromBase64(encoded: String): ShortId - Decode Base64Url to ShortId

πŸ” Static Analysis (Detekt)

This project uses Detekt for Kotlin static analysis. Configuration lives in config/detekt/detekt.yml.

Run Detekt:

./gradlew detekt

Run Detekt for a specific module:

./gradlew server:detekt
./gradlew common:detekt
./gradlew frontend:detekt

Reports are generated in build/reports/detekt/.

πŸ§ͺ Testing

Running Tests

Common Module Tests:

./gradlew common:jvmTest

Server Module Tests:

./gradlew server:test

Test Coverage

  • 16 Server Tests: CRUD operations, edge cases, special characters, pagination
  • 6 Common Tests: Base64 encoding/decoding, round-trip validation, error handling
  • 100% Pass Rate: All tests use kotlin.test annotations with camelCase naming

πŸš€ Getting Started

Prerequisites

  • Java 11+
  • Gradle 7.0+
  • Node.js (for frontend assets)

Running Frontend (Development Mode)

The frontend runs on port 3000 with hot-reload support:

./gradlew frontend:jsBrowserDevelopmentRun

Then open http://localhost:3000 in your browser. API requests are routed to http://localhost:8080.

Running Server

Option 1: Run server only (without frontend)

Simply run the main function in server/src/main/kotlin/Application.kt from your IDE.

Option 2: Run server with latest frontend

This command compiles the production frontend and bundles it with the server:

./gradlew server:runApp

Note: This is slower due to production webpack compilation, but uses the latest frontend code.

The server will start on http://localhost:8080.

πŸ’‘ How It Works

  1. User enters a long URL in the frontend input field
  2. Frontend calls shortenUrl() via RPC WebSocket
  3. Backend generates a random ShortId and stores the mapping
  4. Frontend receives the ShortId and encodes it to Base64Url
  5. Shortened URL is displayed: http://localhost:8080/s/{encodedId}
  6. User can copy the shortened URL to clipboard
  7. Anyone can access the short link and be redirected to the original URL

πŸ–ΌοΈ Application Flow

  1. Enter URL

Enter URL

  1. Shortened Result

Shortened Result

πŸ“ Multiplatform Architecture

Common Module (de.shorty.api)

  • Defines the ShortyApi RPC interface
  • Contains ShortId type (32-bit Int)
  • Provides Base64Url encoding/decoding utilities
  • Compiled to both JVM and JS targets

Server Module (de.shorty.service)

  • Implements ShortyApi interface
  • Manages SQLite database with Exposed
  • Handles concurrent requests with coroutines
  • Provides REST/RPC endpoints

Frontend Module (React + Kotlin/JS)

  • Displays beautiful UI with Emotion styling
  • Manages local state with React hooks
  • Communicates with backend via RPC
  • Lazy loads and displays results

πŸ”’ Security Considerations

  • Base64Url Encoding: Uses URL-safe alphabet (- and _ instead of + and /)
  • Input Validation: All URLs are validated before storing
  • Database Isolation: Each test uses an isolated in-memory database
  • Error Handling: Graceful error messages for invalid inputs

πŸ“Š Performance

  • Encoding/Decoding: O(1) time complexity for Base64Url operations
  • Database: SQLite with optimized queries and indexing
  • API Response: Sub-100ms for typical URL shortening
  • Frontend: Production webpack bundle ~1MB (minified)

🀝 Contributing

This project demonstrates best practices for:

  • Kotlin Multiplatform development
  • Type-safe RPC communication
  • React/Kotlin/JS integration
  • Comprehensive testing with camelCase naming
  • Component-based UI architecture

πŸ“„ License

Copyright 2023-2024 Jochen Guck, Use of this source code is governed by the Apache 2.0 license.

πŸ“š Documentation

  • DESIGN_DECISIONS.md - Comprehensive design decisions document explaining:
    • Why 32-bit Integer with collision detection instead of UUID (22 chars vs 6 chars)
    • Base64Url encoding strategy
    • Database choice (SQLite)
    • RPC framework selection (kotlinx RPC)
    • Component architecture
    • Testing strategy
    • Multiplatform module design
    • Error handling approach
    • And more architectural insights

🎯 Future Enhancements

  • Github actions (Automated tests, Dependabot)
  • Docker image generation (automated)
  • Integration Tests (User Stories)
  • Analytics dashboard for URL statistics
  • URL expiration/TTL support
  • QR code generation
  • User authentication and URL management

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages