Skip to content

TinySlash – Modern Link Management & Secure Sharing Platform TinySlash is a modern, full-stack SaaS platform that enables users to create short links, generate QR codes, and convert files into secure, shareable links with password protection and expiration controls.

License

Notifications You must be signed in to change notification settings

tinyslash-tech/tinyslash

Repository files navigation

🔗 Tinyslash - Enterprise Link Management Platform

Version Build Status License

Tinyslash is an industry-grade, SaaS-ready URL shortening and link management platform. Built for scale with a microservices-ready architecture, it features advanced analytics, custom domains, QR code generation, and team collaboration tools.

Live Production: https://tinyslash.com
Live Development: https://dev.tinyslash.com


📚 Table of Contents

  1. System Architecture & Design
  2. Detailed Tech Stack
  3. Project Structure
  4. Authentication Flow
  5. Core Features Implementation
  6. Admin System
  7. Local Development Setup
  8. Contribution Guide for Interns
  9. Troubleshooting

🏗️ System Architecture & Design

Tinyslash is built on a Decoupled Client-Server Architecture designed for high availability and horizontal scalability.

1. High-Level Architecture

  • Frontend (SPA): A React 18 application handling the presentation layer. It communicates with the backend via RESTful APIs and utilizes JWT for stateless authentication.
  • Backend (API): A Spring Boot 3.2 application acting as the core logic engine. It handles business rules, request validation, and database orchestration.
  • Data Layer (MongoDB): We use MongoDB (NoSQL) for its flexible schema, allowing us to store complex analytics data in a single document (e.g., nesting click data by country/device within the URL document).
  • Edge Layer (Cloudflare): Handles DNS, SSL termination for custom domains (SaaS), and serves as a global CDN to reduce latency.

2. Request Flow Lifecycle

  1. User Request: User clicks a short link (e.g., tinyslash.com/xyz123).
  2. DNS Resolution: Cloudflare routes traffic to our Render backend.
  3. Backend Processing:
    • UrlShorteningService intercepts the request.
    • Looks up shortCode: xyz123 in Redis Cache (Hit) or MongoDB (Miss).
    • Extracts metadata (Browser, OS, IP -> Country).
    • Async Analytics: Fires an event to increment click counters without blocking the redirect.
  4. Response: Returns 302 Found with the Location header set to the original URL.

🛠️ Detailed Tech Stack

Frontend (tinyslash-frontend)

  • Core: React 18, TypeScript 5 (Strict Mode)
  • Build Tool: Vite (for fast HMR and optimized builds)
  • Styling:
    • TailwindCSS 3: Utility-first styling for rapid UI development.
    • Framer Motion: Complex layout animations and transitions.
    • Lucide React: Consistent icon set.
  • State Management:
    • Context API: For global app state (Auth, Theme).
    • React Query (TanStack): For server state caching and synchronization.
  • Routing: React Router DOM v6
  • Analytics Visualization: Recharts (D3-based composable charts).
  • HTTP Client: Axios with interceptors for token refreshment.

Backend (tinyslash-backend)

  • Core: Java 17 LTS, Spring Boot 3.2.0
  • Database: MongoDB 6.0 (via Spring Data MongoDB).
  • Security:
    • Spring Security 6 (FilterChain based).
    • JJWT: For extensive JWT creation and validation.
    • Google OAuth2 Client: For social login flows.
  • Utilities:
    • Lombok: Reduces boilerplate (Getters/Setters/Builders).
    • Jackson: JSON serialization/deserialization.
  • Build Tool: Maven 3.8+
  • Testing: JUnit 5, Mockito.

📂 Project Structure

Backend (tinyslash-backend/url-service)

Follows a Layered Architecture ensuring separation of concerns:

src/main/java/com/urlshortener/
├── controller/         # API Layer: Handles HTTP requests, validation, and JSON responses.
│   ├── AuthController.java      # /api/v1/auth/** (Login, Register, Google)
│   ├── UrlController.java       # /api/v1/url/** (Create, Update, Delete)
│   └── RedirectController.java  # /{shortCode} (The public redirect endpoint)
├── service/            # Business Logic Layer: The complexity lives here.
│   ├── UrlShorteningService.java # Core logic for shortening and analytics.
│   └── UserService.java         # User management logic.
├── repository/         # Data Access Layer: Interfaces extending MongoRepository.
├── model/              # Domain Entities: POJOs mapped to MongoDB documents.
│   ├── ShortenedUrl.java        # Stores URL data + Embedded Analytics Maps.
│   └── User.java                # User profile + Role data.
├── config/             # Configuration Classes.
│   ├── SecurityConfig.java      # CORS, CSRF, and FilterChain rules.
│   └── MongoConfig.java         # Database connection settings.
├── security/           # Security Components.
│   └── JwtAuthenticationFilter.java # Intercepts requests to validate "Bearer" tokens.
└── admin/              # Admin Module.

Frontend (tinyslash-frontend)

Organized by Feature-First structure:

src/
├── components/         # Atomic & Molecular Components.
│   ├── ui/             # Generic UI (Button, Input, Card).
│   └── features/       # Feature-specific (UrlList, AnalyticsChart).
├── pages/              # Page-level Components (Views).
│   ├── Dashboard.tsx
│   ├── LandingPage.tsx
│   └── Auth/           # Login/Register pages.
├── context/            # Global Contexts.
│   └── AuthContext.tsx # Handles User session state.
├── services/           # Service Layer (API calls).
│   ├── api.ts          # Axios instance configuration.
│   └── authService.ts  # Auth-related API calls.
├── hooks/              # Custom React Hooks.
│   └── useAnalytics.ts # Hook for fetching analytics data.
└── App.tsx             # Main Router configuration.

� Authentication Flow

We use a Hybrid Auth System supporting both Email/Password and Google OAuth.

1. Email/Password (Standard)

  1. Client POSTs to /api/v1/auth/login.
  2. Backend authenticates credentials.
  3. On success, Backend returns a JWT (Access Token) validity: 24h.
  4. Frontend stores this token (Secure Storage/Memory).
  5. Frontend attaches Authorization: Bearer <token> to all subsequent requests.

2. Google OAuth (Social)

  1. Frontend uses react-oauth/google to get an authorization_code.
  2. Frontend sends this code to Backend: /api/v1/auth/google/callback.
  3. Backend exchanges code for a Google Access Token via googleapis.com.
  4. Backend fetches user profile from Google.
  5. Backend creates/updates user in local DB.
  6. Backend issues a valid App JWT to the Frontend.

🧩 Core Features Implementation

1. URL Shortening Algorithm

  • Strategy: Random String Gen with Collision Check.
  • Logic:
    1. Generate a 6-character random alphanumeric string (Base62).
    2. Check MongoDB: existsByShortCode(code).
    3. If exists -> User recursion/loop to generate again.
    4. If unique -> Save to DB.
  • Why: Simple, stateless, and efficient for medium-scale.

2. Analytics Engine

  • Data Model: We utilize MongoDB's document model to store analytics inside the URL document.
  • Fields:
    • clicksByCountry: Map<String, Integer> (e.g., {"US": 50, "IN": 120})
    • clicksByDevice: Map<String, Integer>
    • clicksByReferrer: Map<String, Integer>
  • Benefit: Reading a single URL document gives all its analytics instantly. No expensive JOINs or aggregations needed for basic views.

� Admin System

The Admin Dashboard provides superuser control over the platform.

Capabilities

  • User Oversight: View all registered users, their plan status, and total URLs.
  • Content Moderation: ability to delete or ban URLs that violate policies (Phishing/Spam).
  • Global Analytics: View platform-wide growth metrics.

Promoting a User to Admin

Currently done via Database Access:

db.users.updateOne(
  { email: "[email protected]" },
  { $addToSet: { roles: "ROLE_ADMIN" } }
)

🚀 Local Development Setup

1. Database Setup (MongoDB)

  1. Install MongoDB Community Server.
  2. Start the service.
  3. Open MongoDB Compass (GUI) and create a connection: mongodb://localhost:27017.
  4. Create a database named: tinyslash_dev.

2. Backend Setup

  1. Navigate to: cd tinyslash-backend/url-service
  2. Create configuration: src/main/resources/application-dev.yml
    spring:
      data:
        mongodb:
          uri: mongodb://localhost:27017/tinyslash_dev
    google:
      client:
        id: <YOUR_GOOGLE_CLIENT_ID> 
        secret: <YOUR_GOOGLE_CLIENT_SECRET>
    app:
        jwtSecret: <GENERATE_A_LONG_RANDOM_STRING>
        jwtExpirationMs: 86400000
  3. Run the server:
    mvn spring-boot:run
    Server will start on http://localhost:8080

3. Frontend Setup

  1. Navigate to: cd tinyslash-frontend
  2. Create .env file:
    REACT_APP_API_URL=http://localhost:8080/api/v1
    REACT_APP_GOOGLE_CLIENT_ID=<YOUR_GOOGLE_CLIENT_ID>
  3. Install & Start:
    npm install
    npm start
    App will open on http://localhost:3000

🤝 Contribution Guide for Interns

We follow a strict Git Flow process. Please adhere to these rules to maintain code quality.

1. Branching Strategy

  • main: 🛑 PROTECTED. Production code. Do not touch.
  • develop: 🟡 STAGING. This is your base branch.
  • feat/feature-name: 🟢 YOUR WORKSPACE. Create this from develop.
  • fix/bug-name: 🔴 BUG FIX. Create this from develop.

2. Contribution Workflow

  1. Sync Upgrade: Always pull the latest develop before starting.
    git checkout develop
    git pull origin develop
  2. Branch Out:
    git checkout -b feat/add-dark-mode
  3. Commit Often: Use Conventional Commits.
    • feat: add dark mode toggle
    • fix: resolve login spinner issue
    • style: update header padding
    • docs: update readme
  4. Push & PR:
    git push origin feat/add-dark-mode
    • Go to GitHub, open a Pull Request (PR) against develop.
    • Add a description and screenshots of your changes.
    • Assign a senior developer for review.

❓ Troubleshooting

Common Issues

  1. "Connection Refused" (Backend)

    • Cause: MongoDB is not running.
    • Fix: Check services (brew services list on Mac or Task Manager on Windows). Ensure connection URI is correct.
  2. "CORS Error" (Frontend)

    • Cause: Frontend (localhost:3000) is trying to talk to Backend (localhost:8080) but Backend isn't allowing it.
    • Fix: specific allowed origins are defined in AuthController.java or SecurityConfig.java. Ensure @CrossOrigin(origins = "*") is present for dev or http://localhost:3000 is accepted.
  3. "401 Unauthorized"

    • Cause: JWT Token expired or invalid.
    • Fix: Logout and Login again. Check if jwtSecret in application-dev.yml matches what the server is using.

© 2025 Tinyslash Tech. Proprietary Software.

About

TinySlash – Modern Link Management & Secure Sharing Platform TinySlash is a modern, full-stack SaaS platform that enables users to create short links, generate QR codes, and convert files into secure, shareable links with password protection and expiration controls.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published