Resurrecting discourse.el

Hi all,

I’ve started bringing an old Emacs package project back to life: discourse.el.

It’s an Emacs interface for browsing and interacting with Discourse forums, and I’m currently using the System Crafters forum as the test bed while I rebuild it. Only for viewing. I have a test instance of discourse runninng locally for posting/replying. This is also being used to test forum switching.

Repo:

https://github.com/glenneth1/discourse.el

It’s still early days, but I now have the beginnings of the UI working, including:

  • a left-hand navigation pane / category tree
  • category and topic list views
  • topic display inside Emacs

Here are a few early screenshots.

Side pane / category tree

Categories and topics view

Reading a topic

The idea is to make it feel natural to browse forums from inside Emacs, especially in a keyboard-driven and terminal-friendly workflow.

There’s still plenty left to do, but I wanted to share it early and see what people think.

I’d love feedback on:

  • features you’d want in something like this
  • how topic/reply navigation should work
  • whether this is something you’d actually use

If people are interested, I can post updates as it grows.

Cheers,
glenneth :grinning_face:

4 Likes

Hey I recognize that dude in the screenshot! This looks cool.

1 Like

Recent Improvements: Read Tracking, Image Rendering, and UI Polish

Hey everyone,

I’ve been working on some significant improvements to [discourse.el]( GitHub - glenneth1/discourse.el · GitHub ) over the past couple of days and wanted to share what’s new.

## New/Unread Topic Tracking (Persistent Across Sessions)

This was the big missing piece. discourse.el now tracks which topics you’ve read **client-side**, persisted to `~/.emacs.d/discourse-read-state.el`. This means:

- **`[NEW]`** tag and blue bold text for topics you’ve never opened

- **`(N new)`** count for topics with new posts since you last read them

- **`●`** blue dot indicator in the first column for unread topics

- Read topics are dimmed with shadow face for clear visual contrast

- State is **preserved across Emacs restarts** — no more guessing what’s new

The tracking merges with Discourse’s server-side tracking when available, falling back to the local state otherwise.

### Per-Category Counts in the Sidebar

Categories now show new/unread topic counts right next to their names, so you can immediately see where the activity is without clicking into each one.

## Image Rendering Fixes

Images from Discourse forums now render correctly in `shr`. Previously, many images appeared as gray placeholder boxes because Discourse wraps them with `srcset`, `data-*`, and `loading=“lazy”` attributes that confused Emacs’s HTML renderer. These are now stripped before rendering. Relative image URLs (e.g. `/uploads/…`) are also properly resolved against the site URL.

## Auto-Refresh on Navigation

When you read a topic and press `q` to go back, the topic list and sidebar **immediately update** — the `[NEW]` tag disappears and category counts decrease without needing to manually refresh with `g`.

## Other Fixes

- **Title extraction** in the compose buffer is more tolerant of whitespace variations

- **URL port handling** fixed for non-standard ports (e.g. `http://localhost:3000`)

- **`q` in topic list** no longer creates a duplicate sidebar window

- **README** updated with current sidebar UI docs, keybindings, and example `use-package` config

## What’s Next

- **Image/file attachments** in posts and replies (not yet supported)

- Continued testing of replies and comment threads

If you’re using discourse.el, pull the latest from `main` and give it a spin. Feedback greatly appreciated.

Thanks.

1 Like

@highchurch That was especially taken just for you. Enjoy :slight_smile:

1 Like

I just installed it and it is looking really nice. I used the following snippet:

(use-package discourse
  :vc (:url "https://github.com/glenneth1/discourse.el.git")
  :commands (discourse discourse-connect discourse-switch-site)
  :custom
  (discourse-default-url "https://forum.systemcrafters.net")
  (discourse-api-auth-method 'auto)
  (discourse-site-configs
   '(("https://forum.systemcrafters.net" :auth-method session))))

This even works transparently with my password-store setup using the auth-source-pass integration, provided the secret is name forum.systemcrafters.net in the top-level and has the user and port fields filled in.

like:

************
user: foo@somewhere.com
port: 443
login: foo@somewhere.com
url: https://forum.systemcrafters.net
icon: 0
autotype_enabled: True
Email: foo@somewhere.com

(only the first 2 are relevant, the rest is fluff for browser integration)