Skip to content

LinkForty/core

Repository files navigation

LinkForty Logo

LinkForty Core

Open-source deeplink management engine with device detection and analytics

LinkForty Core is a powerful, self-hosted deeplink management system that enables you to create, manage, and track smart links with device-specific routing, analytics, and UTM parameter support. It's the open-source foundation of the LinkForty platform.

npm version Docker Pulls Docker Image Size License: MIT

Features

βœ… Smart Link Routing - Create short links with device-specific URLs for iOS, Android, and web
βœ… Device Detection - Automatic detection and routing based on user device
βœ… Click Analytics - Track clicks with geolocation, device type, platform, and more
βœ… UTM Parameters - Built-in support for UTM campaign tracking
βœ… Link Expiration - Set expiration dates for time-sensitive links
βœ… Redis Caching - Optional Redis support for high-performance link lookups
βœ… PostgreSQL Storage - Reliable data persistence with full SQL capabilities
βœ… TypeScript - Fully typed API for better developer experience

Installation

npm install @linkforty/core

Quick Start

1. Basic Server

import { createServer } from '@linkforty/core';

async function start() {
  const server = await createServer({
    database: {
      url: 'postgresql://localhost/linkforty',
    },
    redis: {
      url: 'redis://localhost:6379',
    },
  });

  await server.listen({ port: 3000, host: '0.0.0.0' });
  console.log('Server running on http://localhost:3000');
}

start();

2. Docker (Recommended for Production)

Quick Start:

# Pull the latest image
docker pull linkforty/core:latest

# Run with Docker Compose
curl -O https://raw.githubusercontent.com/linkforty/core/main/docker-compose.yml
docker compose up -d

Or use Docker CLI:

docker run -d \
  --name linkforty \
  -p 3000:3000 \
  -e DATABASE_URL=postgresql://user:pass@host:5432/linkforty?sslmode=disable \
  -e REDIS_URL=redis://host:6379 \
  linkforty/core:latest

Features:

  • βœ… Pre-built multi-architecture images (AMD64 + ARM64)
  • βœ… Automatic updates with version tags
  • βœ… Non-root user for security
  • βœ… Built-in health checks
  • βœ… Supply chain attestations (SBOM + Provenance)

See DOCKER.md for complete deployment guide.

API Reference

Create a Link

POST /api/links
Content-Type: application/json

{
  "userId": "user-uuid",
  "originalUrl": "https://example.com",
  "title": "My Link",
  "iosUrl": "myapp://product/123",
  "androidUrl": "myapp://product/123",
  "webFallbackUrl": "https://example.com/product/123",
  "utmParameters": {
    "source": "twitter",
    "medium": "social",
    "campaign": "summer-sale"
  },
  "customCode": "summer-sale",
  "expiresAt": "2024-12-31T23:59:59Z"
}

Response:

{
  "id": "link-uuid",
  "userId": "user-uuid",
  "short_code": "summer-sale",
  "original_url": "https://example.com",
  "title": "My Link",
  "ios_url": "myapp://product/123",
  "android_url": "myapp://product/123",
  "web_fallback_url": "https://example.com/product/123",
  "utmParameters": {
    "source": "twitter",
    "medium": "social",
    "campaign": "summer-sale"
  },
  "is_active": true,
  "expires_at": "2024-12-31T23:59:59Z",
  "created_at": "2024-01-01T00:00:00Z",
  "updated_at": "2024-01-01T00:00:00Z",
  "clickCount": 0
}

Get All Links

GET /api/links?userId=user-uuid

Get a Specific Link

GET /api/links/:id?userId=user-uuid

Update a Link

PUT /api/links/:id?userId=user-uuid
Content-Type: application/json

{
  "title": "Updated Title",
  "isActive": false
}

Delete a Link

DELETE /api/links/:id?userId=user-uuid

Get Analytics Overview

GET /api/analytics/overview?userId=user-uuid&days=30

Response:

{
  "totalClicks": 1234,
  "uniqueClicks": 567,
  "clicksByDate": [
    { "date": "2024-01-01", "clicks": 45 }
  ],
  "clicksByCountry": [
    { "countryCode": "US", "country": "United States", "clicks": 234 }
  ],
  "clicksByDevice": [
    { "device": "mobile", "clicks": 789 }
  ],
  "clicksByPlatform": [
    { "platform": "iOS", "clicks": 456 }
  ],
  "topLinks": [
    {
      "id": "link-uuid",
      "shortCode": "summer-sale",
      "title": "My Link",
      "originalUrl": "https://example.com",
      "totalClicks": 123,
      "uniqueClicks": 67
    }
  ]
}

Get Link-Specific Analytics

GET /api/analytics/links/:linkId?userId=user-uuid&days=30

Redirect Short Link

GET /:shortCode

This endpoint automatically redirects users to the appropriate URL based on their device type.

Configuration

Server Options

interface ServerOptions {
  database?: {
    url?: string;           // PostgreSQL connection string
    pool?: {
      min?: number;         // Minimum pool connections (default: 2)
      max?: number;         // Maximum pool connections (default: 10)
    };
  };
  redis?: {
    url: string;            // Redis connection string (optional)
  };
  cors?: {
    origin: string | string[];  // CORS allowed origins (default: '*')
  };
  logger?: boolean;         // Enable Fastify logger (default: true)
}

Environment Variables

DATABASE_URL=postgresql://localhost/linkforty
REDIS_URL=redis://localhost:6379
PORT=3000
NODE_ENV=production
CORS_ORIGIN=*

Database Schema

Users Table

Column Type Description
id UUID Primary key
email VARCHAR(255) Unique email
name VARCHAR(255) User name
password_hash VARCHAR(255) Hashed password
created_at TIMESTAMP Creation timestamp
updated_at TIMESTAMP Last update timestamp

Links Table

Column Type Description
id UUID Primary key
user_id UUID Foreign key to users
short_code VARCHAR(20) Unique short code
original_url TEXT Original URL
title VARCHAR(255) Link title
ios_url TEXT iOS-specific URL
android_url TEXT Android-specific URL
web_fallback_url TEXT Web fallback URL
utm_parameters JSONB UTM parameters
targeting_rules JSONB Targeting rules
is_active BOOLEAN Active status
expires_at TIMESTAMP Expiration date
created_at TIMESTAMP Creation timestamp
updated_at TIMESTAMP Last update timestamp

Click Events Table

Column Type Description
id UUID Primary key
link_id UUID Foreign key to links
clicked_at TIMESTAMP Click timestamp
ip_address INET User IP address
user_agent TEXT User agent string
device_type VARCHAR(20) Device type (mobile/desktop)
platform VARCHAR(20) Platform (iOS/Android/Web)
country_code CHAR(2) Country code
country_name VARCHAR(100) Country name
region VARCHAR(100) Region/state
city VARCHAR(100) City
latitude DECIMAL Latitude
longitude DECIMAL Longitude
timezone VARCHAR(100) Timezone
utm_source VARCHAR(255) UTM source
utm_medium VARCHAR(255) UTM medium
utm_campaign VARCHAR(255) UTM campaign
referrer TEXT Referrer URL

Utilities

Generate Short Code

import { generateShortCode } from '@linkforty/core';

const code = generateShortCode(8); // Returns 8-character nanoid

Detect Device

import { detectDevice } from '@linkforty/core';

const device = detectDevice(userAgent); // Returns 'ios' | 'android' | 'web'

Get Location from IP

import { getLocationFromIP } from '@linkforty/core';

const location = getLocationFromIP('8.8.8.8');
// Returns: { countryCode, countryName, region, city, latitude, longitude, timezone }

Build Redirect URL with UTM Parameters

import { buildRedirectUrl } from '@linkforty/core';

const url = buildRedirectUrl('https://example.com', {
  source: 'twitter',
  medium: 'social',
  campaign: 'summer-sale'
});
// Returns: https://example.com?utm_source=twitter&utm_medium=social&utm_campaign=summer-sale

Advanced Usage

Custom Route Registration

import { createServer } from '@linkforty/core';

const server = await createServer({
  database: { url: 'postgresql://localhost/linkforty' },
});

// Add custom routes
server.get('/custom', async (request, reply) => {
  return { message: 'Hello World' };
});

await server.listen({ port: 3000 });

Using Individual Route Handlers

import Fastify from 'fastify';
import { initializeDatabase, redirectRoutes, linkRoutes } from '@linkforty/core';

const fastify = Fastify();

// Initialize database separately
await initializeDatabase({ url: 'postgresql://localhost/linkforty' });

// Register only specific routes
await fastify.register(redirectRoutes);
await fastify.register(linkRoutes);

await fastify.listen({ port: 3000 });

Deployment

LinkForty can be deployed in multiple ways depending on your needs:

πŸš€ Production Deployment (Recommended)

Deploy to managed platforms with minimal DevOps overhead:

Fly.io (Recommended)

  • Global edge deployment
  • Managed PostgreSQL and Redis
  • Auto-scaling and SSL included
  • Starting at ~$10-15/month

View Fly.io deployment guide β†’

See infra/ directory for all deployment options and platform-specific guides.

🐳 Docker Deployment (Recommended for Self-Hosting)

Production-ready Docker images available on Docker Hub:

# One-command deployment
curl -O https://raw.githubusercontent.com/linkforty/core/main/docker-compose.yml
docker compose up -d

Image Details:

  • Registry: linkforty/core
  • Tags: latest, v1.x.x, main
  • Architectures: linux/amd64, linux/arm64
  • Base: Node.js 22 Alpine (minimal, secure)
  • Security: Non-root user, SBOM attestations

Version Pinning (Recommended):

services:
  linkforty:
    image: linkforty/core:v1.4.0  # Pin to specific version

See DOCKER.md for complete deployment guide including:

  • Environment configuration
  • Health checks
  • Backup strategies
  • Production best practices

Manual Deployment

For custom infrastructure needs:

  1. Install dependencies: npm install @linkforty/core
  2. Set up PostgreSQL database (13+)
  3. Set up Redis (optional but recommended)
  4. Run migrations: npm run migrate
  5. Start server: node server.js

Other Platforms

Community-maintained templates available for:

  • AWS (ECS/Fargate)
  • Google Cloud Run
  • Railway, Render, and more

See infra/CONTRIBUTING.md to add support for additional platforms.

Performance

  • Redis caching: 5-minute TTL on link lookups reduces database queries by 90%
  • Database indexes: Optimized queries for fast link lookups and analytics
  • Async click tracking: Non-blocking click event logging
  • Connection pooling: Efficient database connection management

Security

  • SQL injection protection: Parameterized queries throughout
  • Input validation: Zod schema validation on all inputs
  • CORS configuration: Configurable CORS for API access control
  • Link expiration: Automatic handling of expired links

Mobile SDK Integration

LinkForty Core supports iOS Universal Links and Android App Links for seamless deep linking in mobile applications.

iOS Universal Links Setup

  1. Set environment variables:

    IOS_TEAM_ID=ABC123XYZ  # Your Apple Developer Team ID
    IOS_BUNDLE_ID=com.yourcompany.yourapp
  2. Configure in Xcode:

    • Add "Associated Domains" capability
    • Add domain: applinks:yourdomain.com
  3. Verify AASA file:

    curl https://yourdomain.com/.well-known/apple-app-site-association

    Expected response:

    {
      "applinks": {
        "apps": [],
        "details": [
          {
            "appID": "ABC123XYZ.com.yourcompany.yourapp",
            "paths": ["*"]
          }
        ]
      }
    }

Android App Links Setup

  1. Get your SHA-256 fingerprint:

    # Debug keystore
    keytool -list -v -keystore ~/.android/debug.keystore \
      -alias androiddebugkey -storepass android -keypass android
    
    # Release keystore
    keytool -list -v -keystore /path/to/release.keystore \
      -alias your-alias
  2. Set environment variables:

    ANDROID_PACKAGE_NAME=com.yourcompany.yourapp
    ANDROID_SHA256_FINGERPRINTS=AA:BB:CC:DD:...
    
    # Multiple fingerprints (debug + release)
    ANDROID_SHA256_FINGERPRINTS=AA:BB:CC:...,DD:EE:FF:...
  3. Configure in AndroidManifest.xml:

    <intent-filter android:autoVerify="true">
      <action android:name="android.intent.action.VIEW" />
      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />
      <data android:scheme="https" />
      <data android:host="yourdomain.com" />
    </intent-filter>
  4. Verify assetlinks.json:

    curl https://yourdomain.com/.well-known/assetlinks.json

    Expected response:

    [
      {
        "relation": ["delegate_permission/common.handle_all_urls"],
        "target": {
          "namespace": "android_app",
          "package_name": "com.yourcompany.yourapp",
          "sha256_cert_fingerprints": ["AA:BB:CC:..."]
        }
      }
    ]

Available Mobile SDKs

  • React Native: npm install @linkforty/react-native-sdk
  • iOS: Coming soon
  • Android: Coming soon
  • Flutter: Coming soon

See SDK Integration Guide for detailed documentation.

Testing Domain Verification

Test iOS Universal Links with Apple's validator:

https://search.developer.apple.com/appsearch-validation-tool/

Test Android App Links with Google's validator:

adb shell am start -a android.intent.action.VIEW \
  -d "https://yourdomain.com/test"

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for details.

License

MIT License - see LICENSE file for details.

Related Projects

  • @linkforty/ui - React UI components for link management
  • LinkForty Cloud - Hosted SaaS version with additional features

Support

Built with:

About

Deeplink management engine with device detection and analytics

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published