linse-app logo

linse-app

Self-hosted photo sharing for events.

Developer ToolsSelf-HostedTypeScriptAGPL-3.0 23 0Health 63
GitHub

What is it?

What it is

Linse is a self‑hosted photo sharing platform designed for events. Guests scan a QR code, choose a display name, and can upload, browse, filter, like, and comment on photos in real time. The host creates events, defines tags, moderates uploads, and manages guests through a simple admin panel, all without requiring user accounts or passwords.

Why it exists

Linse exists to provide a privacy‑first, zero‑account photo sharing solution for events, allowing instant sharing and moderation while keeping data under the host’s control. It eliminates the need for third‑party services and gives event organizers full ownership of photos and metadata.

Who should use it

Event organizers, photographers, and small teams who want a quick, self‑hosted photo sharing solution without managing user accounts or complex infrastructure.

Who should avoid it

Large enterprises needing enterprise‑grade authentication, compliance, or advanced analytics; users uncomfortable with Docker or AGPL licensing requirements.

How it works

A quick walkthrough in plain English

How linse-app works

Step 1 of 3

You interact with it

Open linse-app, send a request, or connect it to your stack.

Features

Self-hosted photo sharing for events
Guest upload via QR code – no account or password required
Guest can browse, filter by tag, like, comment
Live updates – new photos appear without page refresh
Host admin panel to create events, define tags, moderate uploads, manage guests
Export originals to a host folder
Docker Compose deployment (app + Postgres) with persistent volumes
HTTPS/reverse proxy support (Caddy overlay provided)
TypeScript/Next.js 16 (App Router) stack with Prisma, Tailwind v4, shadcn/ui
Guest sessions via HttpOnly signed cookies; EXIF stripping on upload
Per-event query isolation, CSRF protection, rate limiting
Multi-arch Docker image (amd64 + arm64) published to GHCR

Advantages

  • Simple one‑command Docker Compose setup
  • Data stays on your own infrastructure – full privacy and control
  • No guest registration lowers barrier to participation
  • Real‑time photo stream enhances event experience
  • Open‑source (AGPL‑3.0) allows inspection and self‑hosting
  • Built with modern web tech – fast, responsive UI
  • Supports both amd64 and arm64 devices
  • Export feature lets hosts keep original files locally
  • Extensive documentation and runbook for backups, upgrades, etc.

Disadvantages

  • Requires Docker and basic CLI familiarity
  • Self‑hosted means you must maintain the server and backups
  • AGPL‑3.0 license may be restrictive for some commercial uses
  • No native mobile app – guests use a browser
  • Limited to event‑scale usage; not designed for massive photo libraries
  • Initial setup involves generating secrets and editing .env file

Installation

compose

cp .env.example .env
docker compose -f compose.yml -f compose.dev.yml up -d --build

# First boot — run migrations and seed the host user:
docker compose -f compose.yml -f compose.dev.yml exec app pnpm prisma migrate deploy
docker compose -f compose.yml -f compose.dev.yml exec app pnpm prisma db seed

# Browse http://localhost:3010

# Type-check and lint:
docker compose -f compose.yml -f compose.dev.yml exec app pnpm typecheck
docker compose -f compose.yml -f compose.dev.yml exec app pnpm lint

FAQ

How do I install Linse using Docker Compose without cloning the repository?

Create a new directory, download the compose file, set up a .env file with the required secrets, then run `docker compose up -d`. The first boot will automatically run migrations and create the host admin account. Example: ```bash mkdir linse && cd linse curl -fsSL https://raw.githubusercontent.com/jmsz1996/linse-app/main/compose.yml -o compose.yml cat > .env <<'EOF' POSTGRES_PASSWORD=replace-with-a-long-random-string AUTH_SECRET=replace-with-openssl-rand-base64-32 LINSE_SECRET=replace-with-another-openssl-rand-base64-32 HOST_ADMIN_EMAIL=you@example.com HOST_ADMIN_PASSWORD=replace-with-a-strong-password LINSE_PORT=3000 EOF docker compose up -d ```

Which environment variables are mandatory for Linse to run?

The following variables must be set: - `POSTGRES_PASSWORD` – password for the PostgreSQL database. - `AUTH_SECRET` – ≥32‑character secret used for host login sessions. - `LINSE_SECRET` – ≥32‑character secret used for guest sessions. - `HOST_ADMIN_EMAIL` – email address for the admin account. - `HOST_ADMIN_PASSWORD` – password for the admin account (reset on every boot).

How can I export the original photos uploaded during an event?

Use the "Export originals" action from the admin panel. The originals are written to the host folder specified by the `EXPORT_DIR` environment variable (default `./exports`). This is a bind mount, so the files remain on the host even if the Docker volumes are removed.

What is needed to run Linse behind a reverse proxy like Caddy or Nginx?

Point the proxy to the internal service `linse-app:3000`. A ready‑made Caddy overlay is provided: ```bash docker compose -f compose.yml -f compose.caddy.yml up -d # Caddyfile: linse.example.com { reverse_proxy linse-app:3000 } ``` For other proxies, simply reverse‑proxy to that internal address and port.

How do I set up the development environment for Linse?

After cloning the repo, bind‑mount the source and run Next.js in hot‑reload mode: ```bash cp .env.example .env docker compose -f compose.yml -f compose.dev.yml up -d --build # Run migrations and seed the host user docker compose -f compose.yml -f compose.dev.yml exec app pnpm prisma migrate deploy docker compose -f compose.yml -f compose.dev.yml exec app pnpm prisma db seed # Browse at http://localhost:3010 ```

Loading documentation…
View on GitHub

Featured in Videos

YouTube tutorials and walkthroughs for linse-app

Alternatives

Similar projects ranked by category, topics, and text overlap.

Compare
linse-app | MushyBook