Skip to content

Repository files navigation

JUKI URL Redirector

A high-performance URL shortener service built with Next.js and Upstash Redis. This service provides a simple API to create, manage, and track shortened URLs with analytics.

Features

  • URL Shortening: Generate short, unique slugs (6 characters) for any URL
  • Custom Slugs: Rename slugs to custom values
  • Analytics: Track views and last access time for each shortened URL
  • Expiration: Set expiration dates for temporary links
  • CORS Support: Pre-configured CORS for JUKI ecosystem and custom origins
  • Redis Storage: Fast, scalable storage using Upstash Redis
  • TypeScript: Fully typed for better developer experience

Tech Stack

  • Framework: Next.js 16 (App Router)
  • Language: TypeScript 5.9
  • Database: Upstash Redis
  • ID Generation: nanoid with custom alphabet
  • Libraries: @juki-team/commons

Project Structure

src/
├── app/
│   ├── [slug]/          # Dynamic route for URL redirection
│   │   └── route.ts
│   ├── api/
│   │   ├── create/      # Create shortened URLs
│   │   │   └── route.ts
│   │   ├── list/        # List all shortened URLs
│   │   │   └── route.ts
│   │   ├── rename/      # Rename slugs
│   │   │   └── route.ts
│   │   └── helpers.ts   # CORS and request helpers
│   └── route.ts         # Root route
├── types/
│   ├── url.ts           # URL-related types
│   └── commons.ts       # Common type exports
├── helpers/             # Utility functions
└── constants/           # Configuration constants

Getting Started

Prerequisites

  • Node.js 18+ or Bun
  • Yarn package manager
  • Upstash Redis account

Environment Variables

Create a .env file in the root directory with the following variables:

NODE_ENV=development

# Upstash Redis Configuration (required)
STORAGE_KV_REST_API_URL=your_upstash_redis_url
STORAGE_KV_REST_API_TOKEN=your_upstash_redis_token

# Optional: Additional allowed CORS origins (comma-separated)
ORIGINS=https://example.com,https://another-domain.com

# Optional: JUKI Service Configuration
NEXT_PUBLIC_JUKI_SOCKET_BASE_URL=
NEXT_PUBLIC_JUKI_SERVICE_V2_URL=
NEXT_PUBLIC_JUKI_TOKEN_NAME=

See .env.example for a template.

Installation

# Install dependencies
yarn install

# Run development server
yarn dev

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

Other Commands

# Build for production
yarn build

# Start production server
yarn start

# Lint code
yarn lint

API Reference

Create Shortened URL

Endpoint: POST /api/create

Request Body:

{
  "url": "https://example.com/very/long/url",
  "expiresInDays": 30,
  "origin": "https://custom-domain.com"
}

Fields:

  • url (required): The original URL to shorten
  • expiresInDays (optional): Expiration in days (0 or omit for no expiration)
  • origin (optional): Custom domain for the shortened URL in response

Response:

{
  "success": true,
  "message": "ok",
  "content": {
    "shortenedUrl": "https://juki.ly/Ab3DeF",
    "slug": "Ab3DeF",
    "url": "https://example.com/very/long/url"
  }
}

Redirect to Original URL

Endpoint: GET /{slug}

Redirects to the original URL and increments view count.

Responses:

  • 302: Redirect to original URL
  • 404: Slug not found
  • 410: Link expired

List All Shortened URLs

Endpoint: GET /api/list

Response:

{
  "success": true,
  "message": "ok",
  "contents": [
    {
      "slug": "Ab3DeF",
      "url": "https://example.com/very/long/url",
      "createdAt": 1234567890000,
      "expiresAt": 1234567890000,
      "views": 42,
      "lastAccessAt": 1234567890000
    }
  ],
  "meta": {
    "total": 1
  }
}

Rename Slug

Endpoint: POST /api/rename

Request Body:

{
  "oldSlug": "Ab3DeF",
  "newSlug": "MyCustomSlug"
}

Response:

{
  "success": true,
  "message": "ok",
  "content": {
    "slug": "MyCustomSlug"
  }
}

Get Version

Endpoint: GET /api/version

Returns the current API version.

Data Model

URL Document

type UrlBodyType = {
  url: string;           // Original URL
  createdAt: number;     // Timestamp (ms)
  expiresAt: number;     // Expiration timestamp (ms), 0 = never expires
  views: number;         // Number of times accessed
  lastAccessAt: number;  // Last access timestamp (ms)
}

Slug Generation

  • 6 characters long
  • Custom alphabet: 23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
  • Excludes confusing characters (0, O, 1, I, l)
  • Collision detection ensures uniqueness

Deployment

Deploy on Vercel

The easiest way to deploy this app is using the Vercel Platform.

  1. Push your code to a Git repository
  2. Import the project to Vercel
  3. Configure environment variables
  4. Deploy

Other Platforms

This is a standard Next.js application and can be deployed to any platform that supports Next.js:

  • Netlify
  • AWS Amplify
  • Railway
  • Render
  • Self-hosted with Docker

License

Private project for JUKI ecosystem.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages