Latest commit

History

192 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Threadlet

Threadlet is a feature-rich, QoL improvement packed, replacement for Discord Forums.

Features

  • More forum tags
  • Advanced markdown
  • Up to 4096 characters per message
  • Completely for free, no hidden fees, or ads

Usage

Currently limited to invited users. If you want to test Threadlet, feel free to message @j0code.

If you have access to the app, it should show up when you search for "Threadlet" in the "Apps & Commands" menu in Discord.

Hosting / Devlopment

Discord Application

  1. create a Discord Application through the Developer Portal
  2. add a redirect URI (OAuth2 tab); https://localhost/ is fine.
  3. set the root mapping in Activites > URL Mappings to a development domain (without https://).
  4. enable Activities in Acitvities > Settings
  5. optionally invite others to test the app in App Testers

Server

  1. cd into the server directory
  2. copy the content of server/config.example.yson into server/config.yson
  3. update the config with the OAuth secret and id from the OAuth2 tab
  4. run npm install
  5. run tsc
  6. run node . to start the server

Client

  1. copy the content of example.env into .env
  2. update the env with the client id of your app
  3. cd into the client directory
  4. create client/dev_config.yson (see client/vite.config.js for reference)
  5. run npm install
  6. run npm run dev to start vite

Note

In prod, skip (6.), run npm run build, and make sure your reverse proxy connects to the server directly. The server will serve from /client/dist (configurable in server/config.yson).

Development

When you want to help development, remember to run the typescript compiler in the server directory. Tip: run tsc in watch mode: tsc --watch

The api directory does not need compilation as the JSR does that automatically upon publishing a new version.

The client directory does not need it either since vite does that automatically.

API

See api/README.md

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

License

This project is licensed under the GPL-3-or-later License. See the LICENSE file for details.

About

Next-gen Matrix client

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

192 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Threadlet

Threadlet is a feature-rich, QoL improvement packed, replacement for Discord Forums.

Features

  • More forum tags
  • Advanced markdown
  • Up to 4096 characters per message
  • Completely for free, no hidden fees, or ads

Usage

Currently limited to invited users. If you want to test Threadlet, feel free to message @j0code.

If you have access to the app, it should show up when you search for "Threadlet" in the "Apps & Commands" menu in Discord.

Hosting / Devlopment

Discord Application

  1. create a Discord Application through the Developer Portal
  2. add a redirect URI (OAuth2 tab); https://localhost/ is fine.
  3. set the root mapping in Activites > URL Mappings to a development domain (without https://).
  4. enable Activities in Acitvities > Settings
  5. optionally invite others to test the app in App Testers

Server

  1. cd into the server directory
  2. copy the content of server/config.example.yson into server/config.yson
  3. update the config with the OAuth secret and id from the OAuth2 tab
  4. run npm install
  5. run tsc
  6. run node . to start the server

Client

  1. copy the content of example.env into .env
  2. update the env with the client id of your app
  3. cd into the client directory
  4. create client/dev_config.yson (see client/vite.config.js for reference)
  5. run npm install
  6. run npm run dev to start vite

Note

In prod, skip (6.), run npm run build, and make sure your reverse proxy connects to the server directly. The server will serve from /client/dist (configurable in server/config.yson).

Development

When you want to help development, remember to run the typescript compiler in the server directory. Tip: run tsc in watch mode: tsc --watch

The api directory does not need compilation as the JSR does that automatically upon publishing a new version.

The client directory does not need it either since vite does that automatically.

API

See api/README.md

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

License

This project is licensed under the GPL-3-or-later License. See the LICENSE file for details.

About

Next-gen Matrix client

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

192 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Threadlet

Threadlet is a feature-rich, QoL improvement packed, replacement for Discord Forums.

Features

  • More forum tags
  • Advanced markdown
  • Up to 4096 characters per message
  • Completely for free, no hidden fees, or ads

Usage

Currently limited to invited users. If you want to test Threadlet, feel free to message @j0code.

If you have access to the app, it should show up when you search for "Threadlet" in the "Apps & Commands" menu in Discord.

Hosting / Devlopment

Discord Application

  1. create a Discord Application through the Developer Portal
  2. add a redirect URI (OAuth2 tab); https://localhost/ is fine.
  3. set the root mapping in Activites > URL Mappings to a development domain (without https://).
  4. enable Activities in Acitvities > Settings
  5. optionally invite others to test the app in App Testers

Server

  1. cd into the server directory
  2. copy the content of server/config.example.yson into server/config.yson
  3. update the config with the OAuth secret and id from the OAuth2 tab
  4. run npm install
  5. run tsc
  6. run node . to start the server

Client

  1. copy the content of example.env into .env
  2. update the env with the client id of your app
  3. cd into the client directory
  4. create client/dev_config.yson (see client/vite.config.js for reference)
  5. run npm install
  6. run npm run dev to start vite

Note

In prod, skip (6.), run npm run build, and make sure your reverse proxy connects to the server directly. The server will serve from /client/dist (configurable in server/config.yson).

Development

When you want to help development, remember to run the typescript compiler in the server directory. Tip: run tsc in watch mode: tsc --watch

The api directory does not need compilation as the JSR does that automatically upon publishing a new version.

The client directory does not need it either since vite does that automatically.

API

See api/README.md

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

License

This project is licensed under the GPL-3-or-later License. See the LICENSE file for details.

About

Next-gen Matrix client

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

192 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Threadlet

Threadlet is a feature-rich, QoL improvement packed, replacement for Discord Forums.

Features

  • More forum tags
  • Advanced markdown
  • Up to 4096 characters per message
  • Completely for free, no hidden fees, or ads

Usage

Currently limited to invited users. If you want to test Threadlet, feel free to message @j0code.

If you have access to the app, it should show up when you search for "Threadlet" in the "Apps & Commands" menu in Discord.

Hosting / Devlopment

Discord Application

  1. create a Discord Application through the Developer Portal
  2. add a redirect URI (OAuth2 tab); https://localhost/ is fine.
  3. set the root mapping in Activites > URL Mappings to a development domain (without https://).
  4. enable Activities in Acitvities > Settings
  5. optionally invite others to test the app in App Testers

Server

  1. cd into the server directory
  2. copy the content of server/config.example.yson into server/config.yson
  3. update the config with the OAuth secret and id from the OAuth2 tab
  4. run npm install
  5. run tsc
  6. run node . to start the server

Client

  1. copy the content of example.env into .env
  2. update the env with the client id of your app
  3. cd into the client directory
  4. create client/dev_config.yson (see client/vite.config.js for reference)
  5. run npm install
  6. run npm run dev to start vite

Note

In prod, skip (6.), run npm run build, and make sure your reverse proxy connects to the server directly. The server will serve from /client/dist (configurable in server/config.yson).

Development

When you want to help development, remember to run the typescript compiler in the server directory. Tip: run tsc in watch mode: tsc --watch

The api directory does not need compilation as the JSR does that automatically upon publishing a new version.

The client directory does not need it either since vite does that automatically.

API

See api/README.md

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

License

This project is licensed under the GPL-3-or-later License. See the LICENSE file for details.

About

Next-gen Matrix client

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

192 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Threadlet

Threadlet is a feature-rich, QoL improvement packed, replacement for Discord Forums.

Features

  • More forum tags
  • Advanced markdown
  • Up to 4096 characters per message
  • Completely for free, no hidden fees, or ads

Usage

Currently limited to invited users. If you want to test Threadlet, feel free to message @j0code.

If you have access to the app, it should show up when you search for "Threadlet" in the "Apps & Commands" menu in Discord.

Hosting / Devlopment

Discord Application

  1. create a Discord Application through the Developer Portal
  2. add a redirect URI (OAuth2 tab); https://localhost/ is fine.
  3. set the root mapping in Activites > URL Mappings to a development domain (without https://).
  4. enable Activities in Acitvities > Settings
  5. optionally invite others to test the app in App Testers

Server

  1. cd into the server directory
  2. copy the content of server/config.example.yson into server/config.yson
  3. update the config with the OAuth secret and id from the OAuth2 tab
  4. run npm install
  5. run tsc
  6. run node . to start the server

Client

  1. copy the content of example.env into .env
  2. update the env with the client id of your app
  3. cd into the client directory
  4. create client/dev_config.yson (see client/vite.config.js for reference)
  5. run npm install
  6. run npm run dev to start vite

Note

In prod, skip (6.), run npm run build, and make sure your reverse proxy connects to the server directly. The server will serve from /client/dist (configurable in server/config.yson).

Development

When you want to help development, remember to run the typescript compiler in the server directory. Tip: run tsc in watch mode: tsc --watch

The api directory does not need compilation as the JSR does that automatically upon publishing a new version.

The client directory does not need it either since vite does that automatically.

API

See api/README.md

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

License

This project is licensed under the GPL-3-or-later License. See the LICENSE file for details.

About

Next-gen Matrix client

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

192 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Threadlet

Threadlet is a feature-rich, QoL improvement packed, replacement for Discord Forums.

Features

  • More forum tags
  • Advanced markdown
  • Up to 4096 characters per message
  • Completely for free, no hidden fees, or ads

Usage

Currently limited to invited users. If you want to test Threadlet, feel free to message @j0code.

If you have access to the app, it should show up when you search for "Threadlet" in the "Apps & Commands" menu in Discord.

Hosting / Devlopment

Discord Application

  1. create a Discord Application through the Developer Portal
  2. add a redirect URI (OAuth2 tab); https://localhost/ is fine.
  3. set the root mapping in Activites > URL Mappings to a development domain (without https://).
  4. enable Activities in Acitvities > Settings
  5. optionally invite others to test the app in App Testers

Server

  1. cd into the server directory
  2. copy the content of server/config.example.yson into server/config.yson
  3. update the config with the OAuth secret and id from the OAuth2 tab
  4. run npm install
  5. run tsc
  6. run node . to start the server

Client

  1. copy the content of example.env into .env
  2. update the env with the client id of your app
  3. cd into the client directory
  4. create client/dev_config.yson (see client/vite.config.js for reference)
  5. run npm install
  6. run npm run dev to start vite

Note

In prod, skip (6.), run npm run build, and make sure your reverse proxy connects to the server directly. The server will serve from /client/dist (configurable in server/config.yson).

Development

When you want to help development, remember to run the typescript compiler in the server directory. Tip: run tsc in watch mode: tsc --watch

The api directory does not need compilation as the JSR does that automatically upon publishing a new version.

The client directory does not need it either since vite does that automatically.

API

See api/README.md

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

License

This project is licensed under the GPL-3-or-later License. See the LICENSE file for details.

About

Next-gen Matrix client

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

192 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Threadlet

Threadlet is a feature-rich, QoL improvement packed, replacement for Discord Forums.

Features

  • More forum tags
  • Advanced markdown
  • Up to 4096 characters per message
  • Completely for free, no hidden fees, or ads

Usage

Currently limited to invited users. If you want to test Threadlet, feel free to message @j0code.

If you have access to the app, it should show up when you search for "Threadlet" in the "Apps & Commands" menu in Discord.

Hosting / Devlopment

Discord Application

  1. create a Discord Application through the Developer Portal
  2. add a redirect URI (OAuth2 tab); https://localhost/ is fine.
  3. set the root mapping in Activites > URL Mappings to a development domain (without https://).
  4. enable Activities in Acitvities > Settings
  5. optionally invite others to test the app in App Testers

Server

  1. cd into the server directory
  2. copy the content of server/config.example.yson into server/config.yson
  3. update the config with the OAuth secret and id from the OAuth2 tab
  4. run npm install
  5. run tsc
  6. run node . to start the server

Client

  1. copy the content of example.env into .env
  2. update the env with the client id of your app
  3. cd into the client directory
  4. create client/dev_config.yson (see client/vite.config.js for reference)
  5. run npm install
  6. run npm run dev to start vite

Note

In prod, skip (6.), run npm run build, and make sure your reverse proxy connects to the server directly. The server will serve from /client/dist (configurable in server/config.yson).

Development

When you want to help development, remember to run the typescript compiler in the server directory. Tip: run tsc in watch mode: tsc --watch

The api directory does not need compilation as the JSR does that automatically upon publishing a new version.

The client directory does not need it either since vite does that automatically.

API

See api/README.md

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

License

This project is licensed under the GPL-3-or-later License. See the LICENSE file for details.

About

Next-gen Matrix client

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

192 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Threadlet

Threadlet is a feature-rich, QoL improvement packed, replacement for Discord Forums.

Features

  • More forum tags
  • Advanced markdown
  • Up to 4096 characters per message
  • Completely for free, no hidden fees, or ads

Usage

Currently limited to invited users. If you want to test Threadlet, feel free to message @j0code.

If you have access to the app, it should show up when you search for "Threadlet" in the "Apps & Commands" menu in Discord.

Hosting / Devlopment

Discord Application

  1. create a Discord Application through the Developer Portal
  2. add a redirect URI (OAuth2 tab); https://localhost/ is fine.
  3. set the root mapping in Activites > URL Mappings to a development domain (without https://).
  4. enable Activities in Acitvities > Settings
  5. optionally invite others to test the app in App Testers

Server

  1. cd into the server directory
  2. copy the content of server/config.example.yson into server/config.yson
  3. update the config with the OAuth secret and id from the OAuth2 tab
  4. run npm install
  5. run tsc
  6. run node . to start the server

Client

  1. copy the content of example.env into .env
  2. update the env with the client id of your app
  3. cd into the client directory
  4. create client/dev_config.yson (see client/vite.config.js for reference)
  5. run npm install
  6. run npm run dev to start vite

Note

In prod, skip (6.), run npm run build, and make sure your reverse proxy connects to the server directly. The server will serve from /client/dist (configurable in server/config.yson).

Development

When you want to help development, remember to run the typescript compiler in the server directory. Tip: run tsc in watch mode: tsc --watch

The api directory does not need compilation as the JSR does that automatically upon publishing a new version.

The client directory does not need it either since vite does that automatically.

API

See api/README.md

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

License

This project is licensed under the GPL-3-or-later License. See the LICENSE file for details.

About

Next-gen Matrix client

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages