Skip to content

Repository files navigation

DevForum Plus

A browser extension for devforum.roblox.com — Luau-aware code intelligence, faster navigation, and a full restyle. Chrome, Brave, Edge and Firefox 128+.

Every feature below can be turned off individually, and the redesign can be switched off while keeping the features.


Features

Code

Luau code intelligence. The forum highlights Luau using highlight.js's Lua grammar. Type annotations, :: casts, continue, generics, compound assignment and string interpolation all render wrong. DFP re-highlights with a tokenizer written for Luau.

It also marks deprecated APIs — the ones that make old answers actively harmful. A 2019 reply recommending wait() and BodyVelocity still ranks on Google and still reads as authoritative. Hovering a mark tells you what to use instead, sourced from Roblox's own API dump.

Hover any class, method, property or enum for its signature, parameters and a link to Creator Docs. All of it is bundled at build time — no request leaves your browser when you hover.

Code block controls add a language label, a soft-wrap toggle, copy-without-comments, and collapse for long blocks.

Finding things

⌘K / Ctrl+K opens a palette: search topics, jump to any category, and apply Discourse's search filters as one-click chips instead of remembering status:solved and min_posts:10.

Search results get age marks. Anything two years or older is flagged, because search is the one place you meet an old answer with no warning at all — on a sample query, 32 of 50 results were 2+ years old. Solved threads get a legible tick; stock renders it in the same grey as the lock icon.

Hover prefetch fetches a topic while you hover its link, so opening it is instant, and replays the real request in the background so your read state still records. A warm cache keeps recently-read bodies on disk.

Reading

  • Topic lists mark solved, busy, closed and long-dormant threads
  • Replies over two years old that recommend replaced APIs carry a quiet caution
  • Thread view indents replies by depth, keeping chronological order so permalinks still work
  • Quiet replies folds runs of "thanks", "+1" and "bump" into one line you can expand — never the opening post, an accepted answer, a reply someone answered, or anything with code
  • Pin the opening post keeps it in a column beside the replies, scrolling on its own — off by default, on windows 1280px and wider
  • Gated categories say so before you write the post, not at submit time
  • Group chips — every group a member belongs to, with flair — on profiles, user cards and bylines
  • Long "liked this" lists fold to twelve faces behind a +N others toggle
  • Asset previews turn rbxassetid:// references and catalog links into real links, with a thumbnail fetched only when you hover one
  • Topic previews: hovering a link to another thread shows its title, whether it was solved and how old it is, from the same request DFP already makes to open a topic
  • Creator Docs links get the hover card that API names in code already have. Reference pages (classes, datatypes, enums, libraries, globals) come from the bundled index with no request; a guide or tutorial page's title is read once, on hover, through the service worker — see Scope
  • Chart theming repaints Discourse's own charts to match the theme
  • Profile layout rebuilds the profile hero, stats and activity pages

Writing

  • Similar topics surface as you type a title, so duplicates get caught
  • A local draft vault survives a closed tab or a crash
  • A Luau code-block button that tags the fence correctly

Design

Five themes — dark, dim, black (OLED), light, off — times three densities times three corner radii. Every colour derives from one OKLCH ramp, and every contrast and separation pair is asserted at build time — over a thousand at the last generation; the exact count is written into the header of tokens.generated.css each time it is built. A regression fails the build rather than shipping.


Install

Requires Node ≥ 20.11 (import.meta.dirname; 20.9 fails with a confusing paths[0] error). A .nvmrc is checked in.

nvm use && npm install && npm run build

Then load it:

From a release

Download DevForumPlus-Chrome.zip or DevForumPlus-Firefox.zip from the latest release and extract it. The asset names never change, so updating is: extract over the same folder, then press reload in the browser. Keep the folder path stable — Chrome derives the extension id from it, and a new folder is a new extension, which resets settings, drafts and the topic cache.

From source

Chromium — open chrome://extensions (or brave://extensions), enable Developer mode, Load unpacked, select .output/chrome-mv3.

Firefox — run npx wxt build -b firefox, open about:debuggingThis FirefoxLoad Temporary Add-on…, select .output/firefox-mv3/manifest.json. Firefox 128 is the floor: world: "MAIN" content scripts landed there, and without one the extension cannot reach Discourse's module loader at all. Firefox also treats host permissions as opt-in, so grant access to devforum.roblox.com when prompted or nothing runs (create.roblox.com is asked for too; it only feeds the Creator Docs hover cards, and everything else works without it).

Then open https://devforum.roblox.com.

The toolbar popup reports which boot rung engaged — the first thing to check if something looks off.

Command What it does
npm run build Tokens → style checks → both targets to .output/ → gzip budgets
npm run dev WXT dev server with hot reload
npm run check Typecheck, style guardrails, unit tests
npm run tokens Regenerate colours; fails the build on a contrast regression
npm run harness Build .output/harness.html, the visual regression page

How it works

It integrates with Discourse rather than scraping it. DevForum runs Discourse 3.5.0.beta3-dev and exposes withPluginApi (PLUGIN_API_VERSION 2.1.1), so DFP registers like a theme component — value transformers, Glimmer outlets, decorateCookedElement.

The site's CSP (script-src 'nonce-…' 'strict-dynamic') forces two content scripts. An isolated script cannot inject one into this page, so main-world.content.ts reaches Discourse's module loader with no chrome.* access, and isolated.content.ts owns chrome.* and stamps <html> before first paint. They talk over a MessageChannel; the isolated side treats the main world as untrusted. There is no style-src, which is why the visual layer survives even if the JS integration breaks.

Boot self-heals across three rungs — trapping window.define before the app boots, polling for the plugin API after it, and finally CSS-only. A watchdog verifies rung 1 actually ran rather than assuming it did.

Failures are contained. Every module install is wrapped and budgeted; one that runs over budget three routes running disables itself and says so in the popup. Nothing throws into Discourse.

The highest-leverage file is base.css, which retargets Discourse's own custom properties at DFP tokens — one assignment restyles hundreds of rules across stylesheets we never wrote a selector for. DFP's CSS is deliberately unlayered: Discourse's is too, and an @layer always loses to unlayered rules regardless of specificity. npm run check:styles enforces that, quarantines !important, and caps it.


Scope

No forum action is ever automated — no auto-like, reply, flag or vote, not behind a flag. Nothing is scraped into an external index. No analytics, no telemetry. Consent and age-verification scripts are never blocked, even optionally.

The palette's recent-topics list is the one record DFP keeps of what you read: the last twelve topics this browser opened, in chrome.storage.local on this device only, never sent anywhere, and cleared the moment the recent-topics module — or the palette, or DevForum Plus itself — is switched off.

host_permissions is two origins, and the second is narrow. https://devforum.roblox.com/* is where everything runs. https://create.roblox.com/* exists for one feature: a Creator Docs link in a post gets a hover card naming the page, and that page sends no CORS headers, so only the service worker can read it. The worker fetches nothing but /docs/… paths on that origin — the path is checked against a fixed pattern and the URL rebuilt from a hardcoded origin, so a crafted link in someone's post cannot point it anywhere else — with credentials: "omit", and only when you hover the link. No tabs, cookies, webRequest, or <all_urls>.

About

A faster, cleaner, more capable devforum.roblox.com.

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages