DEV Community

Manak
Manak

Posted on

LinkBreeze. The self-hosted Linktree alternative. Migrate in 30 seconds. One-line install.

LinkBreeze is a self-hosted alternative to Linktree. I built it because Linktree's $15/mo Pro plan didn't justify the feature set, email capture is another $9/mo, embed widgets are paywalled, link scheduling is paywalled. I wanted something I actually own: my data on my server, no subscription, no tracking pixels.

The interesting technical bit: the public page ships zero client-side JavaScript.

The entire link-in-bio page, themes, animations, hover effects, QR codes, embed widgets, renders server-side as pure HTML/CSS. No React runtime, no hydration, no framework JS. The visitor downloads HTML + CSS + their fonts. Page loads in under 300ms. That's it.

Feature gap vs. the competition (what pushed me to build this):

Feature Linktree LinkStack LittleLink Shako LinkBreeze
Price $15/mo Free Free Free Free
Admin Panel Slow ✅ Fast
Multi-Page Paid
Migration Wizard
Built-in Analytics Paid Basic ✅ Full
External Analytics
Email Capture Paid
Embed Widgets Paid
Link Thumbnails Paid
Link Scheduling Paid
Themes Paid Limited CSS only Config ✅ Full Token System + Import/Export
Custom CSS
Language Closed PHP HTML Astro TypeScript
Docker Deploy N/A Complex Simple Simple One command
License Closed AGPL MIT GPL MIT

Live demo (read-only): https://linkbreeze-demo.omnirise.dev/alex
Admin demo: https://linkbreeze-demo.omnirise.dev/login (demo / demo1234)
Repo: https://github.com/Manak-hash/LinkBreeze

I'd genuinely appreciate feedback, bug reports, or feature suggestions. What's missing compared to what you'd expect from a self-hosted tool like this?

Top comments (3)

Collapse
 
amitfeldman profile image
Amit Feldman

"Migrate in 30 seconds" is the right pitch for this category — Linktree lock-in is real and self-hosters are the most loyal users you'll get. From a scan of the demo instance (linkbreeze-demo.omnirise.dev): five of six security headers are already set (HSTS is even preload-grade), which makes the one gap stand out — no Content-Security-Policy. For a links product that's the highest-value header: your pages exist to aggregate third-party URLs and embedded content, exactly the surface CSP governs.

Since it's Next.js and open-source, the fix has leverage beyond your demo — put it in next.config in the repo and every self-hoster gets it by default:

async headers() {
  return [{
    source: '/(.*)',
    headers: [{ key: 'Content-Security-Policy',
      value: "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:" }]
  }]
}
Enter fullscreen mode Exit fullscreen mode

Start with Content-Security-Policy-Report-Only if you let users embed arbitrary widgets — see what would break, then enforce. img-src https: matters here since avatars/thumbnails come from user-supplied domains. Happy to run a full free scan of the demo if useful — just say the word.

Collapse
 
manak_ profile image
Manak

Great catch, and thanks for the detailed scan. You're right, CSP is the gap. The other five headers are set in next.config.ts but CSP was deliberately parked because we support custom embed widgets in some link styles and I wanted to avoid breaking live pages before auditing which sources actually need allowlisting.

Your Report-Only suggestion is the right first step. I'll ship that in the next config update so self-hosters get it by default, then move to enforcement once we've collected enough reports to know what breaks.

On img-src https:, that's necessary for this product. Users supply their own avatar URLs and link thumbnails come from arbitrary domains (gravatar, og:image scrapes, etc.). Can't whitelist specific origins without breaking the core use case. Worth the tradeoff for a links product, but agreed it should be a conscious decision, not an accident.

Would genuinely appreciate the full scan. Go for it. Anything else you find, drop it as a GitHub issue or here, whichever you prefer. The demo instance stays up.

Collapse
 
amitfeldman profile image
Amit Feldman

Full scan delivered — ran the complete pass against the demo instance (linkbreeze-demo.omnirise.dev): 14 pass, 1 warn, 1 fail.

What passes: HSTS preload-grade, X-Frame-Options SAMEORIGIN, nosniff, Referrer-Policy strict-origin-when-cross-origin, Permissions-Policy locked down, TLS valid (44 days, TLS 1.3), title/meta/single-h1 clean, robots.txt and sitemap.xml both 200, ~400ms total response. Solid baseline.

The two findings:

  1. CSP (the fail — you know this one). Your Report-Only plan is exactly right for the embed-widget situation. One addition worth making while you're in there: since users can embed arbitrary widgets, frame-src and connect-src matter more for you than img-src. img-src https: is a defensible tradeoff for avatars and og-image thumbnails, but an unconstrained connect-src is how a malicious embedded widget exfiltrates data. Report-Only will show you exactly which origins your real widgets need.

  2. Image alt text (the warn): 2 of 3 images on the demo page have no alt. On a links page that's SEO and accessibility surface — and since end users supply the images, it's worth making alt a prompted field in the product itself rather than a note in the docs.

The free scan covers the headers/TLS/SEO surface. If you want the deeper pass before launch traffic, the full Quick Scan ($49) goes further: exposed files and secrets (.env, .git, backups), dependency/SRI checks, forms and auth surface, performance budget, and a prioritized fix list — and for an open-source project the report doubles as a security section for the README. It's at gumroad.com/l/keikf if useful.

Either way, happy to re-run the free scan once Report-Only ships — watching for it.