A simple, hierarchical link sharing application. Like Linktree, but with nested sections, password protection, and full customization — all driven by TOML config files.
bun install
bun devOpen http://localhost:3000.
Create a content/ directory with nested folders. Each folder with a config.toml becomes a section.
content/
├── config.toml # Root page
├── logo.png # Assets served automatically
├── work/
│ ├── config.toml # /work section
│ └── projects/
│ └── config.toml # /work/projects section
└── personal/
├── config.toml # /personal section
└── background.jpg # Section-specific assets
Each config.toml defines a section:
title = "My Links"
description = "Shared resources for the team"
# Access control
# password = "secret123"
# Appearance
# theme = "default" # Theme name (see Themes below)
# dark = "auto" # true, false, or "auto" (default: "auto")
# background = "background.jpg" # Local file or URL
# background_color = "#0f172a" # CSS color
# logo = "logo.png" # Local file or URL
# font = "Inter" # Any Google Font
# color = "violet" # Tailwind color palette name
# accent_color = "#6366f1" # Accent color (hex)
# locale = "en" # Language code (see Localization below)
# inherit = true # Inherit parent styling (default: true)
# Links
[[items]]
title = "Example"
url = "https://example.com"
description = "An example link"
# icon = "icon.png" # Custom icon (local file or URL)
# Text notes
[[items]]
title = "Important Note"
type = "text"
content = "This is a text note displayed inline."
# Images
[[items]]
title = "Team Photo"
type = "image"
file = "photo.jpg" # Local file
# description = "From the offsite"
# Downloadable files
[[items]]
title = "Project Report"
type = "file"
file = "report.pdf" # Local file
# url = "https://s3.example.com/report.pdf" # Or remote URL
# filename = "report-q4.pdf" # Suggested download filename
# Video
[[items]]
title = "Demo Recording"
type = "video"
file = "demo.mp4" # Local file or url = "https://..."
# Audio
[[items]]
title = "Podcast Episode"
type = "audio"
file = "episode.mp3" # Local file or url = "https://..."
# Code snippets (with syntax highlighting)
[[items]]
title = "Quick Start"
type = "code"
language = "bash" # Language hint for highlighting
content = "bun install && bun dev"
# Embeds (iframes)
[[items]]
title = "Location"
type = "embed"
url = "https://www.google.com/maps/embed?..."
# height = 400 # iframe height in px (default: 400)| Type | Fields | Description |
|---|---|---|
link (default) |
url, description, icon |
A clickable external link |
text |
content |
An inline text note |
image |
file or url, description |
An inline image |
file |
file or url, filename, description |
Downloadable file with download button |
video |
file or url, description |
Embedded video player |
audio |
file or url, description |
Embedded audio player |
code |
content, language |
Syntax-highlighted code snippet (highlight.js) |
embed |
url, height, description |
iframe embed (YouTube, Maps, etc.) |
LinkShare ships with several built-in themes: bare, book, carnival, chalk, christmas, comic-sans, cooking, default, dog, easter, halloween, kawaii, retro, sherlock, vaporwave, and win98.
Set a theme per-section in config.toml:
theme = "retro"Each theme is a directory under themes/ containing a theme.toml, Handlebars templates, and a style.css. You can create custom themes by adding new directories there.
The dark option is tri-state:
"auto"(default) — follows the user's system preference viaprefers-color-schemetrue— always darkfalse— always light
dark = trueBy default, child sections inherit their parent's styling (font, theme, colors, logo, background). Override any property in the child's config.toml, or set inherit = false to start fresh.
Add password = "your-password" to any section's config.toml. The password check is server-side — protected content is never sent to the browser until authenticated. Auth tokens are stored in signed cookies (24h expiry).
LinkShare supports multiple languages. Set locale per-section in config.toml:
locale = "pt-BR"The locale is inherited by child sections. Available locales: ar, de, el, en, es, fr, he, hi, hy, it, ja, ka, ko, pt-BR, th, zh-Hans, zh-Hant.
| Variable | Default | Description |
|---|---|---|
PORT |
3000 |
Server port |
CONTENT_DIR |
./content |
Path to content directory |
THEMES_DIR |
./themes |
Path to themes directory |
LOCALES_DIR |
./locales |
Path to locales directory |
AUTH_SECRET |
Auto-generated | Secret for signing auth cookies. Set this in production for persistent sessions across restarts. |
NODE_ENV |
— | Set to production to cache content at startup |
A Docker image is published to GitHub Container Registry on every push to main. Pull it and bind-mount your content directory:
docker run -p 3000:3000 \
-v /path/to/your/content:/app/content \
-e AUTH_SECRET=your-secret-here \
ghcr.io/<owner>/linkshare:mainThe bind mount shadows the image's built-in /app/content, so the container only sees your mounted files. You can also mount custom themes or locales:
docker run -p 3000:3000 \
-v /path/to/content:/app/content \
-v /path/to/themes:/app/themes \
ghcr.io/<owner>/linkshare:maindocker build -t linkshare .
docker run -p 3000:3000 \
-v /path/to/your/content:/app/content \
linkshareLinkShare requires the Bun runtime on Vercel. Setup:
-
Link your project to Vercel:
vc link
-
Set a random secret for signing authentication cookies. Without this, sessions are invalidated on each cold start.
openssl rand -hex 32 | vc env add AUTH_SECRET production
(If the command above doesn't work for whatever reason, you can just manually add any random secret string to AUTH_SECRET)
-
Deploy:
vc deploy
Your content/, themes/, and locales/ directories are bundled into the deployment. Content changes require a redeploy.
fly launch
fly deployConnect your GitHub repo — both platforms auto-detect Bun and deploy.
The included workflow (.github/workflows/deploy.yml) builds and pushes a Docker image to GitHub Container Registry on every push to main.
bun devIn development mode, content is re-scanned on every request so you can edit config.toml files and see changes immediately.
- Bun — Runtime
- Elysia — Web framework
- Handlebars — Templating
- Tailwind CSS — Styling (Play CDN)
- highlight.js — Code syntax highlighting
- Google Fonts — Typography
- smol-toml — TOML parsing