Files
reddit-tweaks-ffe/docs/superpowers/specs/2026-08-26-reddit-badge-tweaks-design.md
cottongin bbe3aa0b50 Add design spec for Reddit badge tweaks Firefox extension
Spec covers badge repositioning (subreddit + comment count),
light/dark mode support, user-configurable colors, per-subreddit
overrides, and extension popup settings UI.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-26 14:22:33 -04:00

192 lines
8.6 KiB
Markdown

# Firefox Reddit Tweaks — Design Spec
**Date:** 2026-08-26
**Status:** Approved
## Overview
A Firefox extension that reskins old Reddit post listings by relocating the subreddit name and comment count into styled badge elements positioned above each post title. The original elements are hidden and replaced by clickable badge links.
**Target:** old.reddit.com only (including www.reddit.com when the user's preference renders old Reddit).
**Scope:** All pages where posts appear with subreddit and comment metadata — front page, subreddit listings, user profiles, search results, multi-reddits, and comment pages.
## Architecture
### Approach
Pure CSS + vanilla JS content script. No frameworks, no build step. The extension popup uses plain HTML/CSS/JS for the settings UI.
**Rationale:** Old Reddit has a stable, well-known DOM structure. The scope is small enough that a framework or build tooling would add unnecessary complexity. The modular file layout supports adding new tweaks later.
### File Layout
```
firefox-reddit-tweaks/
├── manifest.json
├── content/
│ ├── main.js # Entry point, orchestrates tweaks
│ ├── tweaks/
│ │ └── badges.js # Subreddit + comment badge tweak
│ └── styles/
│ └── badges.css # Badge styling
├── popup/
│ ├── popup.html # Settings UI
│ ├── popup.js # Settings logic
│ └── popup.css # Settings styling
├── icons/
│ ├── icon-48.png
│ └── icon-96.png
└── lib/
└── settings.js # Shared settings read/write (browser.storage.sync)
```
### Manifest
- Manifest V2 (Firefox fully supports V2).
- `content_scripts` matched to `*://old.reddit.com/*` and `*://www.reddit.com/*`. On `www.reddit.com`, the script naturally handles the old-vs-new ambiguity because it targets `div.thing` elements, which only exist when old Reddit is rendered.
- Permissions: `storage` (for user settings), `activeTab`.
- `browser_action` for the popup.
### Modularity
Each tweak is an individual file under `content/tweaks/`, responsible for one self-contained modification. `main.js` loads settings and calls each enabled tweak. Adding a new tweak means: drop a file in `tweaks/`, wire it in `main.js`.
## Badge Tweak — DOM Manipulation
### Source Elements
Old Reddit renders each post as a `div.thing`. Relevant children:
- **Subreddit name:** `a.subreddit` inside `p.tagline`
- **Comment count:** `a.comments` inside `ul.flat-list.buttons`
### Process
1. Query all `div.thing` elements on the page.
2. For each post, extract the subreddit link's `href`/text and the comments link's `href`/text (parsing the number from the text).
3. Create two badge elements (styled `<a>` tags) and insert them into a new container `div.reddit-tweaks-badges`, placed as the first child of the post's `div.entry` (above the title).
4. Hide the original subreddit element in the tagline and the comments link in the flat-list via CSS (`display: none`).
5. Mark each processed post with `data-rt-processed` to prevent double-processing.
### Badge HTML Structure
```html
<div class="reddit-tweaks-badges">
<a class="rt-badge rt-badge--subreddit" href="/r/example/">r/example</a>
<a class="rt-badge rt-badge--comments" href="/r/example/comments/abc123/">12 comments</a>
</div>
```
All injected elements use an `rt-` prefix to avoid class name collisions with Reddit.
### Dynamic Content
A `MutationObserver` on `div#siteTable` (the post container) watches for new `div.thing` children, covering RES infinite scroll and Reddit's own pagination. New posts are processed on insertion.
## Badge Styling
### Default Colors
| Property | Light Mode | Dark Mode |
|---|---|---|
| **Subreddit** background | `transparent` | `transparent` |
| **Subreddit** border | `#c84a20` | `#ff6b3d` |
| **Subreddit** text | `#c84a20` | `#ff6b3d` |
| **Comments** background | `#e0e0e0` | `#3a3a3a` |
| **Comments** border | `#4a4a4a` | `#888888` |
| **Comments** text | `#4a4a4a` | `#cccccc` |
### Shared Badge Properties
- `display: inline-block`
- `border: 1px solid` (color from settings)
- `border-radius: 3px`
- `padding: 2px 6px`
- `font-size: 11px`
- `font-weight: bold`
- `text-decoration: none`
- `vertical-align: middle`
- `margin-right: 6px`
- Hover: slight opacity reduction to signal clickability
- Container (`div.reddit-tweaks-badges`): `margin-bottom: 4px`
### Dark Mode Detection
The content script checks for RES night mode via the `.res-nightmode` class on `<body>` and applies the dark palette via a CSS class toggle (`rt-dark`). Users can also force a mode in settings (Auto / Light / Dark).
### CSS Custom Properties
Colors are applied via CSS custom properties (`--rt-sub-bg`, `--rt-sub-border`, `--rt-sub-text`, `--rt-com-bg`, `--rt-com-border`, `--rt-com-text`) set on the badge container. The stylesheet references them with fallbacks to light mode defaults.
For per-subreddit overrides, inline styles are set on individual badges when a matching entry exists in the settings.
## Settings
### Storage
All settings stored in `browser.storage.sync` for cross-device sync.
### Configurable Properties
| Setting Key | Type | Default | Description |
|---|---|---|---|
| `enabled` | boolean | `true` | Master toggle |
| `darkMode` | string | `"auto"` | `"auto"` / `"light"` / `"dark"` |
| `light.subredditBgColor` | string | `transparent` | Light mode subreddit badge background |
| `light.subredditBorderColor` | string | `#c84a20` | Light mode subreddit badge border |
| `light.subredditTextColor` | string | `#c84a20` | Light mode subreddit badge text |
| `light.commentsBgColor` | string | `#e0e0e0` | Light mode comments badge background |
| `light.commentsBorderColor` | string | `#4a4a4a` | Light mode comments badge border |
| `light.commentsTextColor` | string | `#4a4a4a` | Light mode comments badge text |
| `dark.subredditBgColor` | string | `transparent` | Dark mode subreddit badge background |
| `dark.subredditBorderColor` | string | `#ff6b3d` | Dark mode subreddit badge border |
| `dark.subredditTextColor` | string | `#ff6b3d` | Dark mode subreddit badge text |
| `dark.commentsBgColor` | string | `#3a3a3a` | Dark mode comments badge background |
| `dark.commentsBorderColor` | string | `#888888` | Dark mode comments badge border |
| `dark.commentsTextColor` | string | `#cccccc` | Dark mode comments badge text |
| `subredditColors` | object | `{}` | Map of subreddit name → `{bg, border, text}` |
### Live Updates
The content script listens for `browser.storage.onChanged` to apply settings changes without requiring a page reload.
## Settings UI (Popup)
1. **Master toggle** — enable/disable the extension.
2. **Badge Colors** section with Light Mode and Dark Mode sub-sections, each showing:
- Subreddit badge: background, border, text color pickers
- Comments badge: background, border, text color pickers
- "Reset to defaults" button per mode
3. **Dark mode detection** dropdown: Auto (detect RES) / Force Light / Force Dark.
4. **Per-subreddit overrides** — add/remove list. Each entry: subreddit name text input + three color pickers for the subreddit badge.
5. **Reset all settings** button at the bottom.
Settings save immediately on change. Clean, minimal styling following Firefox extension popup conventions.
## Error Handling & Edge Cases
- **Missing elements:** If a post lacks a subreddit link (e.g., on a subreddit page where it's implicit) or comments link, that badge is skipped. No errors thrown.
- **Already processed:** `data-rt-processed` attribute prevents double-processing.
- **RES infinite scroll:** MutationObserver catches dynamically added posts.
- **Subreddit pages:** Subreddit badge is skipped when the subreddit name isn't present in the post tagline (it's implied by the page context).
- **Comment pages:** The main post at the top is a `div.thing` and gets badges. Comment entries lack subreddit/comment-count structure and are naturally skipped.
- **Extension disabled:** When `enabled` is `false`, the content script does nothing and any previously injected badges/styles are removed.
## Testing Strategy
Manual testing via `about:debugging` (temporary add-on). No automated test framework for v1.
### Test Checklist
1. Badges appear on front page posts
2. Badges appear on subreddit listing pages (subreddit badge omitted when redundant)
3. Badges appear on user profile pages
4. Badges are clickable links to correct destinations
5. Original subreddit/comment elements are hidden
6. RES infinite scroll loads get badged
7. Dark mode detection works with RES night mode
8. Settings changes apply live without page reload
9. Per-subreddit color overrides work
10. Reset to defaults works