@linkforty/core
v1.4.2
Published
Open-source deeplink management engine with device detection and analytics
Maintainers
Readme
@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.
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/coreQuick 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. Self-Hosting with Docker
# Clone the examples
git clone https://github.com/linkforty/core.git
cd core/examples
# Start services
docker compose up -d
# Server will be available at http://localhost:3000API 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-uuidGet a Specific Link
GET /api/links/:id?userId=user-uuidUpdate 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-uuidGet Analytics Overview
GET /api/analytics/overview?userId=user-uuid&days=30Response:
{
"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=30Redirect Short Link
GET /:shortCodeThis 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 nanoidDetect 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-saleAdvanced 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 (Self-Hosted)
For local development or self-managed infrastructure:
git clone https://github.com/linkforty/core.git
cd core/examples
docker compose up -dSee examples/docker-compose.yml for complete Docker setup.
Manual Deployment
For custom infrastructure needs:
- Install dependencies:
npm install @linkforty/core - Set up PostgreSQL database (13+)
- Set up Redis (optional but recommended)
- Run migrations:
npm run migrate - 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
Roadmap
- [ ] Webhook support for click events
- [ ] Bulk link operations via API
- [ ] Link grouping and tags
- [ ] A/B testing support
- [ ] QR code generation
- [ ] Custom domain support (in SaaS version)
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
- Documentation: https://docs.linkforty.com
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Built with:
- Fastify - Fast web framework
- PostgreSQL - Powerful database
- Redis - In-memory cache
- nanoid - Unique ID generation
- geoip-lite - IP geolocation
- ua-parser-js - User agent parsing
