Skip to content

paoloronco/Lynx

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

152 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Lynx

Your personal links hub

Version

Lynx is an open-source, self-hosted link page manager: public profile page, admin panel, SQLite storage, theme editor, analytics, and secure admin access in one small app.

πŸ“Œ Contents

🎬 Demo

Watch the demo

Watch the demo

✨ Features

  • πŸŽ› Admin panel: edit profile, links, theme, password, and reset options from one dashboard.
  • πŸ‘€ Public profile: name, bio, avatar, social links, page title, meta description, favicon, and footer text.
  • πŸ”— Flexible cards: classic links, text cards, bulleted/grouped content, separators, icons, emojis, and images.
  • 🎨 Theme control: colors, gradients, fonts, spacing, radius, blur, glow, button styles, link styles, and custom CSS.
  • πŸ‘ Live preview: check the public page while editing.
  • πŸ“Š Analytics: click tracking with an admin chart.
  • πŸ—“ Scheduling: show or hide links by date range.
  • πŸ™ˆ Visibility toggles: hide links without deleting them.
  • πŸ“± Mobile-friendly editing: responsive UI and touch drag-and-drop ordering.
  • πŸ“¦ Import/export: backup and restore links and themes as JSON.
  • πŸ—„ Standalone storage: SQLite by default, no Firebase or Supabase required.
  • πŸ”’ Optional HTTPS: enable a self-signed HTTPS listener with ENABLE_HTTPS=true.

πŸ” Security

  • Passwords are hashed with bcryptjs using 12 salt rounds.
  • Sessions use signed JWTs with a 12-hour expiry.
  • The frontend stores JWTs encrypted in localStorage with AES-GCM.
  • SQLite access uses parameterized queries.
  • API, auth, login, reset, and SPA routes are rate-limited.
  • Docker startup requires JWT_SECRET to avoid unstable sessions after restart.
  • Optional RESET_TOKEN supports token-protected recovery if you are locked out.

πŸ›  Tech Stack

πŸš€ Quick Start

Pick the path that matches what you want to do.

⚑ Run Lynx locally

Use this if you want to try Lynx on your machine with a production-style flow: the React app is built first, then the Express server serves both the frontend and the API.

Requirements

  • Node.js ^20.19.0 or >=22.12.0
  • npm
  • Git

1. Clone the repository

git clone https://github.com/paoloronco/Lynx.git
cd Lynx/LYNX

2. Install dependencies

npm ci
npm run install:server

3. Build and start

npm run start

npm run start runs the frontend build and then starts the backend server.

Open:

On the first admin visit, Lynx asks you to create the admin password. The username is always admin.

Local data is stored in LYNX/server/lynx.db unless you set DATA_DIR.

πŸ§‘β€πŸ’» Development mode

Use this when you are editing the code and want frontend hot reload.

Development mode uses two running processes:

The Vite server gives you hot reload for React and proxies /api requests to the Express server.

1. Install dependencies once

cd Lynx/LYNX
npm ci
npm run install:server

2. Start the backend in the first terminal

cd Lynx/LYNX
npm run server:dev

3. Start the frontend in the second terminal

cd Lynx/LYNX
npm run dev

Keep both terminals open while developing.

Open:

Stop either process with Ctrl+C.

🐳 Quick Docker run

Use this if you want the fastest container-based setup.

From the repository root:

docker compose up -d

The included docker-compose.yml uses:

  • image: paueron/lynx:latest
  • port: 8080
  • volume: ./lynx-data:/app/data

Before exposing the app, replace the sample JWT_SECRET in docker-compose.yml.

Open:

βš™οΈ Configuration

Environment variables
Variable Default Notes
JWT_SECRET random outside Docker Required in Docker. Use a long random value in production.
NODE_ENV unset Set to production for production deployments.
PORT 3001 local, 8080 Docker HTTP server port.
DATA_DIR LYNX/server local, /app/data Docker Stores lynx.db and persistent data.
ENABLE_HTTPS false Set to true or 1 for self-signed HTTPS.
SSL_PORT 8443 HTTPS port.
FRONTEND_URL same-origin mode Optional dev CORS/CSP origin, e.g. http://localhost:8080.
RESET_TOKEN unset Enables token-protected reset endpoints. Use at least 32 characters.
πŸ’Ύ Data persistence
  • Local: data is stored in LYNX/server/lynx.db unless DATA_DIR is set.
  • Docker: mount /app/data so the database and uploads survive container updates.

🐳 Docker

Docker Compose

From the repository root:

docker compose up -d

The included docker-compose.yml uses:

  • image: paueron/lynx:latest
  • port: 8080
  • volume: ./lynx-data:/app/data

Before exposing the app, replace the sample JWT_SECRET in docker-compose.yml.

Docker CLI
docker pull paueron/lynx:latest

docker run -d --name lynx \
  -p 8080:8080 \
  -e NODE_ENV=production \
  -e PORT=8080 \
  -e JWT_SECRET="replace-with-a-long-random-secret" \
  -v lynx_data:/app/data \
  paueron/lynx:latest

Open:

Optional HTTPS
docker run -d --name lynx \
  -p 8080:8080 \
  -p 8443:8443 \
  -e NODE_ENV=production \
  -e PORT=8080 \
  -e JWT_SECRET="replace-with-a-long-random-secret" \
  -e ENABLE_HTTPS=true \
  -v lynx_data:/app/data \
  paueron/lynx:latest

Then open https://localhost:8443. The browser will warn because the certificate is self-signed.

☁️ Railway

Deploy on Railway

Railway can deploy the repository using the root Dockerfile.

  1. Create a new Railway project from the GitHub repository.
  2. Let Railway use the Dockerfile in the repository root.
  3. Add:
NODE_ENV=production
PORT=8080
JWT_SECRET=replace-with-a-long-random-secret
  1. Deploy the service.
  2. Add a public domain from the Railway service settings.

Railway already provides HTTPS at the edge, so ENABLE_HTTPS is normally not needed there.

🌍 Other hosting options

Lynx can run anywhere that supports a Node app or a Docker container: Render, Fly.io, DigitalOcean App Platform, Google Cloud Run, Heroku Container Runtime, Azure App Service, AWS Elastic Beanstalk, Koyeb, Northflank, CapRover, Dokku, and Coolify.

For any container deployment, persist /app/data and set JWT_SECRET.

πŸ“ Changelog

v4.0.0

Admin experience

  • Redesigned the Admin panel with a clearer dashboard layout, status metrics, sticky centered navigation, and a lighter operational workspace.
  • Improved the Links editor with a clearer toolbar, content creation cards, save state visibility, and a more helpful empty state.
  • Added animated profile checklist guidance and save confirmation feedback for theme changes.
  • Kept the public page preview isolated from the Admin styling so it continues to reflect the saved public theme.

Loading and compatibility

  • Added a single public-page payload endpoint to load profile, links, and theme together and avoid flashes of default content.
  • Preserved compatibility with existing SQLite databases through additive migrations only.
v3.8.0

Integrations

  • Added Google Analytics 4 integration in the Admin panel (new Integrations tab).
  • The GA4 Measurement ID (G-XXXXXXXXXX) is stored in the database and injected as a gtag.js script on the public page only β€” the admin panel is never tracked.
  • Content Security Policy updated to allow googletagmanager.com and google-analytics.com script and connect sources.
  • Measurement ID is validated client-side before saving (format G-XXXXXXXXXX).
v3.7.0

Critical fixes

  • Fixed production blank page behavior caused by CORS/CSP headers blocking API calls in production containers.
  • Fixed stale frontend assets in Docker builds by cleaning dist before building.
  • Fixed legacy database migration handling.
  • Fixed missing fs import in database.js.

Production stability

  • Improved production CORS handling for same-origin and reverse-proxy deployments.
  • Refined Content Security Policy settings.
  • Added static asset serving logs for deployment troubleshooting.
  • Improved database migration validation and error handling.
v3.6.0
  • Added live preview inside the admin panel.
  • Added a View Public Page action from the admin header.
  • Added link visibility toggles.
  • Added mobile drag-and-drop ordering.
  • Removed sensitive authentication logs.
  • Removed unused Supabase and Firebase code.
  • Fixed duplicate database migration logic.
  • Removed debug logging from PublicLinkCard.
v3.5.1
  • Updated vulnerable frontend, backend, and Docker dependencies.
  • Resolved Dependabot alerts and Docker image CVEs reported at the time of release.
  • Optimized Docker build time by avoiding source builds where precompiled binaries are available.
v3.5.0
  • Added editable profile fields with line-break support in the bio.
  • Added social link controls and profile picture display controls.
  • Added text cards and bulleted lists.
  • Added JSON import/export for links and themes.
  • Added theme controls for page styling, typography, title, meta description, and footer text.
  • Added Docker startup validation for JWT_SECRET.
  • Added optional self-signed HTTPS support with ENABLE_HTTPS=true.

πŸ“„ License

MIT License. See LICENSE.txt.

About

Lynx is an open-source, self-hosted link manager that helps you gather all your digital touchpoints in a single page, with secure authentication and a fully customizable design.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors