Every morning goes the same way: open the RSS reader, then Hacker News, then a couple of subreddits, then the weather, then a quick look at whether the home server is still alive. Five tabs to answer one question: what's new?

Glance collapses all of that into one page. It's a self-hosted dashboard that pulls your feeds, news, videos, weather, markets and server status into a single, fast, good-looking start page. You describe the page in one YAML file and Glance does the rest. It runs as a single small binary or a Docker container, and it's quietly become one of the most popular self-hosted projects on GitHub, at over 35,000 stars.

What it is (and isn't)

Glance is a reading dashboard. Its job is to put the things you check every day in one place, laid out in columns, so one glance (hence the name) tells you what changed. It's written in Go, licensed AGPL-3.0, and the whole thing ships as a single binary under 20 MB with few dependencies.

It is not a live monitoring system. This is the single most important thing to understand before you set it up:

  • Glance fetches data when you load the page, then caches it. Nothing runs in the background.
  • The page doesn't update itself. A refresh pulls fresh data, once the cache for that widget has expired.
  • Clocks and relative timestamps ("3h ago") do tick on their own, but feeds and stats don't.

That design is why it's so light. There's no database, no worker process, no polling loop eating CPU at 3 a.m. If you want alerts at 3 a.m., pair it with something like Uptime Kuma. If you want a start page that loads in about a second, this is it.

The widgets

Everything on a Glance page is a widget. The built-in set covers most of what a self-hoster checks in a day:

FEEDS & NEWS
  rss              RSS and Atom feeds, several display styles
  hacker-news      Hacker News front page
  lobsters         Lobsters front page
  reddit           any subreddit, with optional thumbnails
  videos           latest uploads from YouTube channels
  twitch-channels  who's live
  releases         new releases from GitHub, GitLab, Docker Hub

HOMELAB
  monitor          is each service up, and how fast did it answer
  docker-containers  status of your containers
  server-stats     CPU, memory and disk usage
  dns-stats        AdGuard Home, Pi-hole or Technitium stats
  repository       stars, issues and PRs for a GitHub repo

EVERYDAY
  weather, calendar, clock, markets, bookmarks, search, to-do

BUILD YOUR OWN
  custom-api       fetch any JSON API and render it with a template
  extension        pull HTML from a URL you control
  html, iframe     drop in your own markup or embed a page

LAYOUT
  group            stack widgets as tabs
  split-column     put widgets side by side

Every widget accepts a title to rename it, and most accept a cache duration such as 30m, 12h or 1d. The exceptions are weather and calendar, which update hourly on a fixed schedule.

Install it with Docker

The fastest route is the official compose template, which sets up a sensible folder layout in one command:

mkdir glance && cd glance && curl -sL \
  https://github.com/glanceapp/docker-compose-template/archive/refs/heads/main.tar.gz \
  | tar -xzf - --strip-components 2

That gives you docker-compose.yml, config/glance.yml and config/home.yml. Edit them, then:

docker compose up -d

If you'd rather build it by hand, the compose file is tiny:

services:
  glance:
    container_name: glance
    image: glanceapp/glance
    restart: unless-stopped
    volumes:
      - ./config:/app/config
    ports:
      - 8080:8080

Grab the example config to start from, and bring it up:

mkdir config && wget -O config/glance.yml \
  https://raw.githubusercontent.com/glanceapp/glance/refs/heads/main/docs/glance.yml
docker compose up -d
# open http://localhost:8080

No Docker? There are precompiled binaries for Linux, Windows and macOS on x86, x86_64, ARM and ARM64. Drop the binary next to a glance.yml and run it. On Linux it's easy to wrap in a systemd service under /opt/glance/. It also builds from source with Go 1.23 or newer: go build -o build/glance .

How the config works

The whole dashboard is one YAML file, and the structure is three levels deep: pages contain columns, and columns contain widgets.

pages:
  - name: Home
    columns:
      - size: small
        widgets:
          - type: calendar
      - size: full
        widgets:
          - type: hacker-news
      - size: small
        widgets:
          - type: weather
            location: London, United Kingdom

Each page becomes a tab across the top, and you can have as many as you like: a Home page, a Homelab page, a Videos page. Columns follow a few strict rules worth knowing up front, because breaking them is the most common first-run error:

  • A page has at most three columns.
  • It must have one or two full columns.
  • small columns are a fixed 300px wide, and full columns share whatever's left.
  • Valid shapes: 1 full, 2 full, 1 full + 2 small, or 2 full + 1 small.

The classic layout is small / full / small: quick-glance stuff on the sides, the main reading feed in the middle.

Hot reload

Save the file and Glance picks up the change immediately, with no restart. If you save a broken config, it keeps running the last good one and logs the error. One catch: a reload clears the widget caches, so if you save twenty times in five minutes you can trip rate limits on sites like Reddit. Batch your edits.

Splitting the file, and keeping secrets out of it

Once the config grows, split it up with $include. That's what the compose template does with home.yml:

pages:
  - $include: home.yml
  - $include: homelab.yml

Anything sensitive, such as API keys and tokens, can come from environment variables instead of sitting in the file. Glance can also read Docker secrets:

token: ${GITHUB_TOKEN}
password: ${secret:dashboard_password}

A homelab page that earns its tab

Here's where Glance stops being a news reader and becomes genuinely useful for anyone running services at home. A second page, three widgets:

- name: Homelab
  columns:
    - size: full
      widgets:
        - type: monitor
          cache: 1m
          title: Services
          sites:
            - title: Jellyfin
              url: https://jellyfin.yourdomain.com
            - title: AdGuard Home
              url: https://adguard.yourdomain.com

        - type: docker-containers
          hide-by-default: false

    - size: small
      widgets:
        - type: server-stats
          servers:
            - type: local
              name: Services

monitor sends a GET request to each URL and shows whether it answered with a 200, plus how many milliseconds it took. server-stats shows CPU, memory and disk for the machine Glance runs on.

docker-containers needs access to the Docker socket, so add it to the Glance service's volumes:

    volumes:
      - ./config:/app/config
      - /var/run/docker.sock:/var/run/docker.sock

Then dress up each container with labels in its own compose file, so it shows a proper name, icon and link:

  jellyfin:
    image: jellyfin/jellyfin:latest
    labels:
      glance.name: Jellyfin
      glance.icon: si:jellyfin
      glance.url: https://jellyfin.yourdomain.com
      glance.description: Movies & shows

A word on that socket: mounting docker.sock gives the container control over Docker on the host, which is effectively root. Glance only reads from it, but if you'd rather not hand it the keys, point sock-path at a read-only proxy such as docker-socket-proxy instead.

Build your own widget in five lines

The custom-api widget is the secret weapon. Point it at any JSON endpoint and render the result with a Go template:

- type: custom-api
  title: Random Fact
  cache: 6h
  url: https://uselessfacts.jsph.pl/api/v2/facts/random
  template: |
    <p class="size-h4">{{ .JSON.String "text" }}</p>

Anything with a JSON API becomes a widget: your router, your Home Assistant, a game server, a package tracker. Before writing your own, check the community-widgets repo. There's a good chance someone already built it.

Theming

Glance themes are a handful of HSL values (hue, saturation, lightness, space-separated, no percent signs). Change three numbers and the whole dashboard follows. Naturally, here's one in this site's colors:

theme:
  background-color: 140 30 4
  primary-color: 135 100 60
  contrast-multiplier: 1.2
  presets:
    amber-crt:
      background-color: 30 30 4
      primary-color: 41 100 50
      contrast-multiplier: 1.2

Presets show up in a theme picker on the page, so you can switch between phosphor green and amber without touching the file. For deeper changes, custom-css-file loads your own stylesheet, and there's a light: true option if you're that kind of person. The repo's docs/themes.md has a gallery of ready-made themes to copy.

Locking it down

A dashboard that shows your containers and server stats shouldn't be open to the internet. Glance has built-in username and password auth. Generate a secret key and a password hash:

docker run --rm glanceapp/glance secret:make
docker run --rm glanceapp/glance password:hash mysecretpassword

Then add them to the top of glance.yml:

auth:
  secret-key: ${GLANCE_SECRET_KEY}
  users:
    admin:
      password-hash: ${GLANCE_ADMIN_HASH}

Even with auth on, the safest setup is to keep Glance on your LAN or behind a VPN like WireGuard or Tailscale. If you do expose it, put it behind a reverse proxy with HTTPS.

Tips from setting it up

  • Make it your browser's start page. That's where it pays off. Every new tab is the dashboard.
  • Set sensible caches. 1m for monitors, 1h or more for feeds, 1d for releases. Long caches keep page loads fast and keep you clear of rate limits.
  • Use group to save space. Hacker News and Lobsters in one tabbed widget, or three subreddits in another.
  • Feed it the small web. The rss widget is the heart of Glance. Personal blogs and project feeds are where it shines. This site has a feed too, if you want to give it a test.
  • Use the releases widget for update-watching. List the projects you self-host and you'll see new versions the morning they ship.

Verdict

Glance does one thing and does it well: it turns a morning of tab-hopping into a single page that loads in about a second. Setup is a compose file and a YAML file, the resource footprint is close to nothing, and the custom-api widget means it grows with whatever else you run. If you keep a homelab, or just read a lot of feeds, it's one of the easiest self-hosted wins there is.

Start with the GitHub repo and the configuration docs, which cover every widget option in depth. The image is in the downloads directory, and Glance is in the resource index.

End of transmission.