Its 2023 but lots of hostings still cant run nodejs.
After a not good hosting experience with Ionos (looks cheap at first, but requires add-on ££ packages) Im wondering what realistically is cheapest monthly hosting, that can run nodejs and Nodebb.
Many offer 70% discount for first 3-12 months, which then reverts to a higher price.
It is one advantage of PhP code that its more universal.
@phenomlab may I ask which host you use, and how much per month roughly to host Sudonix?
World
Topics from outside of this forum. Views and opinions represented here may not reflect those of this forum and its members.
A world of content at your fingertips…
Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.
While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.
Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.
Register Login-
-
The greed of both Apple and Meta never ceases to amaze me.
https://news.sky.com/story/apple-and-meta-fined-millions-by-eu-over-competition-law-13354190
and BOUM Personally, I don’t hate American companies. I use their products like everyone else, but I think their economic weight is such that they impose their own rules instead of respecting those of the countries where they do business. And here, for once, the DMA is putting the church back in the middle of the village (French Expression). -
Windows 10 goes End Of Life on the 14th of October, 2025.
With the hardware requirements for Windows 11 likely meaning that those with older PC’s need to fork out for newer hardware, I wanted to put a discussion together to see how I can help others who may be concerned their current PC is going to be vulnerable post this date.
Windows 10 will reach end of support on October 14, 2025. The current version, 22H2, will be the final version of Windows 10, and all editions will remain in support with monthly security update releases through that date. Existing LTSC releases will continue to receive updates beyond that date based on their specific lifecycles.
https://learn.microsoft.com/en-us/lifecycle/products/windows-10-home-and-pro
@phenomlab said in Windows 10 EOL by October 14, 2025: From memory, the commercial edition is RHEL. Yeah the RHEL is the commercial edition. I think I am going to stick with Arch and KDE desktop for that version. It seems like Arch is really versatile and compatible with almost anything. Pair that to the experience that I have had for the server side of things, and the USB boot version I have, it is hard to beat. -
Hi @phenomlab
I see a welcome Message at the right of your website

I have an HTML widget on ACP with this code :
<div class="getUsername">Bonjour, <a href="/me"><span class="username">MY USERNAME</span></a></div>And my CSS :
.getUsername { padding-top: 20px; padding-bottom: 5px; text-align: right; font-size: 90%; line-height: 2.4; font-weight: bold; }Everything is good except the main one, the display of the username.
I saw that you used the /me on aHref, that can be added in the URL (https://XXXXX.XX/me) to point to the user profile
But how do you display the name of it because my HTML code displays what I ask it to display. In other words “MY USERNAME”
In other words how do you display the name of the user? With JS?

Other things, At this time it is indicated “good evening”.
Quiz of when is the start of the day

-
A few users have commented on the new shiny logo that appears at the top of the navbar here
Want to know how I created that? Of course you do!
The logo itself makes use of a few techniques such as
webkit-background-clipand-webkit-text-stroketo make the font look like it has an outline only with no fill. This technique won’t appeal to everyone, so if you’re just looking for the shine code, you can skip this, and go straight to thejQuerycode andCSS.Firstly, I actually hide the
<img>so no actual logo is being displayed[component="brand/logo"] { display: none; }I then use a
jQueryfunction to create my own Brand Logo$(document).ready(function() { $('[component="brand/wrapper"]').append('<a component="siteTitle" href="/" title="Brand Logo"><h1 class="fs-6 fw-bold text-body mb-0 shine">sudonix</h1></a>'); });And then apply the below
CSSto achieve the style I want. Note, that the:rootvalues must be set on your site, or at the very least, alternatives if you are not using variables.:root { --bs-body-navbar: #E5E6E6; --bs-logo-bg: linear-gradient(45deg, #ff5733, #f73d45, #e54f6d, #c85e9e, #a874c0, #748bda, #4691f1, #0099f7); --bs-node-shine: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.5) 50%, rgba(255, 255, 255, 0) 100%); } @keyframes shine { 0% { left: -100%; opacity: 0; } 5% { opacity: 1; } 25% { left: 100%; opacity: 1; } 26% { opacity: 0; } 100% { left: 100%; opacity: 0; } } a[component=siteTitle] h1 { font-size: 2.2rem !important; top: -1px; position: fixed; font-family: "Bruno Ace SC"; font-weight: 600 !important; letter-spacing: 0.05rem; -webkit-background-clip: text !important; color: var(--bs-body-navbar) !important; -webkit-text-stroke: 4px transparent; background: var(--bs-logo-bg); width: 172px; padding-left: 5px; } .shine::before { content: ""; position: absolute; top: 10px; width: 60px; height: 25px; background: var(--bs-node-shine); transform: skewX(-45deg); animation: shine 10s linear infinite; pointer-events: none; mix-blend-mode: screen; z-index: 1; } .shine { position: relative; display: inline-block; color: transparent; background-clip: text; -webkit-background-clip: text; overflow: hidden; }I’ve also included a CodePen so you can see this working in realtime
@DownPW said in "Glass" (shine) effect on Sudonix logo: Perfect with White background theme but much less with black themes backgrounds (we see the edges of the shine effect) Yes, you will need to modify the CSS according. For example, on Sudonix, I use --bs-node-shine: linear-gradient(90deg, rgba(28, 38, 44, 0) 0%, rgba(74, 100, 116, 0.5) 50%, rgba(28, 38, 44, 0) 100%); Essentially, you choose the base background, the shine colour, and then the base background again. -
Well, unfortunately, I think I am going to have to revert back to using gmail again. I am unable to afford Proton Mail suite unfortunately. I had thought about maybe using my own email server, but if I ever need to shut that down then that won’t be a good option. I don’t plan on it, but things change. So it would be nice to get a good free one that is secure.
If anyone has any good suggestions, please let me know. I’m not sure what I should do. I am going to go with Bitwarden, and can do the 10 dollars a year for the premium, which it will be nice to have an authenticator built into that program.
So I will need to figure out the email and will probably go back to nordvpn for that part of it. If i remember right, it was fairly cheap per year.
-
This is certainly an interesting article I read this morning.
https://www.bbc.com/news/articles/cjewvpkw7weo
Whilst appealing from the unlimited solar power perspective, the main issues I can see are as I’ve highlighted below
- Do we really need more space junk? Think of all the abandoned satellites that are simply floating around in space because the cost of returning them is too high.
- Any critical failure in these data centres would probably mean a very costly repair mission.
- It takes data transmitted from earth to space around 1.5 seconds to arrive. Whilst this is not an issue for backups or longer term storage, real time applicatons and services would not work properly such as voice, video etc.
And who mans this infrastructure?
-
This is such a bad idea in terms of privacy and and security that the ICO has already begun an investigation. And clearly for very good reason.
Any nefarious actor with access to the target machine could easily gain access to these screenshots and use them to exploit a victim directly. This is literally like leaving the keys under the mat, and all your personal information in clear view ripe for picking.
This is nothing more than spyware in my view and should be stopped.
What’s your view?
-
And so, we “celebrate” 50 years of Micro$oft. Who’d have thought - a company started by a geeky 19 year old would be what and where it is today.
All those BSOD’s… and Windows ME, Vista…shudder…
https://www.npr.org/2025/04/04/nx-s1-5328683/microsoft-50-year-anniversary-computing-revolution
-
At work, we are transitioning from NodeBB for our Knowledge Base to Halo ITSM, which we require for SOC2 compliance amongst other things. Because I had 165 articles in NodeBB I didn’t want to have to re-type, or even copy and paste, I decided to write a Python script to walk the target category and create a file for each.
Here’s the script to complete that. There are a number of prerequisities here, which I’ve identified below
import os import re import time import requests import html2text from datetime import datetime # --- CONFIGURATION --- # Your Forum URL goes here BASE_URL = "https:/yourforum.com" #The category ID you want to target goes here CATEGORY_ID = 3 # In my case, I needed to define a new "home" for the exported files under `/public/uploads` as this contained all the images I needed to embed into the new flat files. Therefore, ASSET_DOMAIN is nothing more than a basic website where I can grab the images from afterwards. ASSET_DOMAIN = "https://assetlocation.com" # The below directories are created at the same level as the script. If they do not exist, you need to create them. They will contain both `HTML` and `markdown` copies of the posts. HTML_DIR = "nodebb_export_html" MD_DIR = "nodebb_export_markdown" os.makedirs(HTML_DIR, exist_ok=True) os.makedirs(MD_DIR, exist_ok=True) h = html2text.HTML2Text() h.ignore_links = False h.body_width = 0 page = 1 total_exported = 0 print(f"🔄 Starting export for category {CATEGORY_ID} from {BASE_URL}") while True: print(f"📄 Fetching page {page}...") url = f"{BASE_URL}/api/category/{CATEGORY_ID}?page={page}" res = requests.get(url, timeout=10) if res.status_code != 200: print(f"❌ Failed to fetch page {page}: {res.status_code}") break data = res.json() topics = data.get("topics", []) if not topics: print("✅ No more topics found. Export complete.") break for topic in topics: tid = topic['tid'] title = topic['title'] print(f"→ Exporting topic {tid}: {title}") topic_url = f"{BASE_URL}/api/topic/{tid}" topic_res = requests.get(topic_url, timeout=10) if topic_res.status_code != 200: print(f"⚠️ Failed to fetch topic {tid}") continue topic_data = topic_res.json() posts = topic_data.get("posts", []) tags = topic_data.get("topic", {}).get("tags", []) tag_list = ", ".join(tags) if tags else "" safe_title = title.replace(' ', '_').replace('/', '-') html_file = f"{HTML_DIR}/{tid}-{safe_title}.html" md_file = f"{MD_DIR}/{tid}-{safe_title}.md" # --- HTML EXPORT --- with open(html_file, "w", encoding="utf-8") as f_html: f_html.write(f"<html><head><title>{title}</title></head><body>\n") f_html.write(f"<h1>{title}</h1>\n") if tag_list: f_html.write(f"<p><strong>Tags:</strong> {tag_list}</p>\n") for post in posts: username = post['user']['username'] content_html = post['content'] timestamp = datetime.utcfromtimestamp(post['timestamp'] / 1000).strftime('%Y-%m-%d %H:%M:%S UTC') pid = post['pid'] # Rewrite asset paths in HTML content_html = re.sub( r'src=["\'](/assets/uploads/files/.*?)["\']', rf'src="{ASSET_DOMAIN}\1"', content_html ) content_html = re.sub( r'href=["\'](/assets/uploads/files/.*?)["\']', rf'href="{ASSET_DOMAIN}\1"', content_html ) f_html.write(f"<div class='post'>\n") f_html.write(f"<h3><strong>Original Author: {username}</strong></h3>\n") f_html.write(f"<p><em>Posted on: {timestamp} | Post ID: {pid}</em></p>\n") f_html.write(f"{content_html}\n") f_html.write("<hr/>\n</div>\n") f_html.write("</body></html>\n") # --- MARKDOWN EXPORT --- with open(md_file, "w", encoding="utf-8") as f_md: # Metadata block f_md.write(f"<!-- FAQLists: Knowledge Base -->\n") if tag_list: f_md.write(f"<!-- Tags: {tag_list} -->\n") f_md.write("\n") f_md.write(f"# {title}\n\n") for post in posts: username = post['user']['username'] content_html = post['content'] timestamp = datetime.utcfromtimestamp(post['timestamp'] / 1000).strftime('%Y-%m-%d %H:%M:%S UTC') pid = post['pid'] # Convert HTML to Markdown content_md = h.handle(content_html).strip() # Rewrite asset paths content_md = re.sub( r'(!\[.*?\])\((/assets/uploads/files/.*?)\)', rf'\1({ASSET_DOMAIN}\2)', content_md ) content_md = re.sub( r'(\[.*?\])\((/assets/uploads/files/.*?)\)', rf'\1({ASSET_DOMAIN}\2)', content_md ) f_md.write(f"**Original Author: {username}**\n\n") f_md.write(f"_Posted on: {timestamp} | Post ID: {pid}_\n\n") f_md.write(f"{content_md}\n\n---\n\n") total_exported += 1 print(f"✔ Saved: {html_file} & {md_file}") page += 1 time.sleep(1) print(f"\n🎉 Done! Exported {total_exported} topics to '{HTML_DIR}' and '{MD_DIR}'")Run the script using
python scriptname.py.If the script fails, it’s likely because you do not have the required modules installed in Python
import os import re import time import requests import html2textIn this case, you’d need to install them using (for example)
pip install html2textTo get them into an Excel file where they can all be bulk imported, we’d then use something like the below script
import os import re import pandas as pd from datetime import datetime import markdown # --- CONFIGURATION --- export_dir = "nodebb_export_markdown" output_file = "Halo_KB_Import_HTML.xlsx" # This value can be whatever suits your needs created_by = "Import" today = datetime.today().strftime('%Y-%m-%d') # --- BUILD DATAFRAME FOR HALO --- import_rows = [] for filename in sorted(os.listdir(export_dir)): if filename.endswith(".md"): filepath = os.path.join(export_dir, filename) with open(filepath, "r", encoding="utf-8") as f: lines = f.readlines() # Default values # Change "Knowledge Base" to reflect what you are using in Halo faqlists = "Knowledge Base" tags = "" # Parse metadata comments from top of file metadata_lines = [] while lines and lines[0].startswith("<!--"): metadata_lines.append(lines.pop(0).strip()) for line in metadata_lines: faq_match = re.match(r"<!-- FAQLists:\s*(.*?)\s*-->", line) tag_match = re.match(r"<!-- Tags:\s*(.*?)\s*-->", line) if faq_match: faqlists = faq_match.group(1) if tag_match: tags = tag_match.group(1) markdown_content = ''.join(lines) html_content = markdown.markdown(markdown_content) # Extract summary from filename summary = filename.split('-', 1)[1].rsplit('.md', 1)[0].replace('_', ' ') import_rows.append({ "Summary": summary, "Details": html_content, "Resolution": "", "DateAdded": today, "CreatedBy": created_by, "FAQLists": faqlists, "Tags": tags }) # --- EXPORT TO EXCEL --- df = pd.DataFrame(import_rows) df.to_excel(output_file, index=False) print(f"✅ Done! Halo HTML import file created: {output_file}")This then generates a file called
Halo_KB_Import_HTML.xlsxwhich you can then use to import each exported post into Halo.Cool eh? Huge time saver

-
Just seen this news article about a breach of security at GCHQ.
Given this is GCHQ, the information taken was classified as “Top Secret” and in the wrong hands could cause the UK significant harm, you have to ask yourself about the level of “security” in place here.
Surely, you’d have basic controls in place to prevent data leakage by at least locking down USB ports, and who on secondment has access to highly restricted areas??
Crazy.
-
As I have multiple email accounts to manage (wife, dad, parents-in-law, myself, Sudonix etc) I decided to use an email client - something I’ve not done for years on the personal front. However, flipping between online only accounts is never a great experience, so I wanted something with a bit more flexibility - and more importantly, a unified view for mail in terms of all inboxes.
My question here is basically, which email client do you prefer?
-
In a significant move towards modernization, Japan is finally phasing out the use of floppy disks in its governmental and administrative processes. This step is part of a broader effort to streamline and digitize operations, marking the end of an era for a technology that has long been outdated in most parts of the world.
Floppy disks, once a ubiquitous medium for data storage in the 1980s and 1990s, have been largely obsolete for years, replaced by more efficient and higher-capacity storage solutions like USB drives, cloud storage, and solid-state drives. However, Japan has continued to rely on these antiquated devices, especially within various government departments and public services.
This decision to eliminate floppy disks is driven by the need to enhance efficiency, security, and reliability in data management. Floppy disks are prone to physical damage and data degradation over time, making them a less secure option for storing important information. Additionally, the availability of devices capable of reading floppy disks has diminished, further complicating their continued use.
The push for digital transformation in Japan has been gaining momentum, particularly under the leadership of Digital Minister Taro Kono. Kono has been a vocal advocate for reducing bureaucratic red tape and accelerating the adoption of digital technologies across the government. His efforts aim to not only improve internal processes but also to make government services more accessible and user-friendly for the public.
The transition away from floppy disks is part of a broader initiative to overhaul Japan’s digital infrastructure. This includes promoting the use of online forms and digital signatures, which can significantly reduce paperwork and the time required to process documents. By embracing modern technology, Japan hopes to improve the efficiency of its public services and better serve its citizens in an increasingly digital world.
While the move to retire floppy disks might seem overdue to some, it reflects a larger trend of technological updates within government systems worldwide. Many countries are grappling with similar challenges as they work to modernize legacy systems that were once state-of-the-art but have since become inefficient and outdated.
Japan’s decision to bid farewell to the floppy disk is a symbolic and practical step forward. It underscores the nation’s commitment to digital innovation and sets the stage for further advancements in how the government interacts with and serves its people. As Japan continues to embrace new technologies, it is poised to enhance its administrative capabilities and pave the way for a more efficient and connected future.
-
Here’s a topic that caught my interest yesterday - I think the title says it all…
Now, here’s the thing. I understand the need for encryption to ensure the privacy of information supplied over what is effectively an open channel, and prone to eavesdropping. That’s the immediate response from the privacy advocate sewn through me like a stick of rock.
However, I also support the flip side in the sense that same level of privacy and encryption can also be afforded to criminals and other nefarious actors alike - not to mention paedophiles. The statement from Waugh below totally nails it
“Twenty years ago, someone like Gary Glitter had to go to the other side of the world to prey on children,” said Labour MP Paul Waugh to Chris Yiu, one of Meta’s directors of public policy.
"Someone like Jeffrey Epstein had to create his own private paedophile island.
“Now, these monsters, all they have to do is go on to set up a group on Facebook Messenger.”
Paul Waugh is 100% on point here, but to me, it’s a thin line that we are finding ourselves having to tread more often than not. On the one hand, we have a duty to protect our children, but on the other hand, we all want the privacy encryption affords.
I’m interested in a discussion around this topic, and I see both sides.
-
So, you’ve stumbled across Sudonix, love the themes, and wish you had them on your own NodeBB instance?

Well, very soon, you can
I’ll be uploading all of the themes plus the master CSS to a private Git repository - you’ll need to contact me for access to it, but that also means you’ll get the latest and greatest as I release fixes, updates, etc.In addition, I’ll be uploading the jQuery / JS code I’ve written that’s in use here also (for example, the dynamic category panel)
Because of the amount of work I’ve put into this over time, a donation is very much appreciated (but not mandatory as that would negate the very service this site sets out to provide), and a backlink from your site to mine (which is mandatory).
Interested? Let me know by posting here, or contact me via PM if preferred.
-
Hi @phenomlab ,
I am working on CSS codes to customize the link-preview plugin for some time, but I was unsuccessful
so, I wanted to consult you in case I am missing an important line…Unfortunately, normal previews of this plugin are too big for our taste, just like how iframely used to be…
I ended up something like this:
.post-container .content .card { display: contents !important; } .link-preview { .card-img-top { height:120px !important; width: auto !important; overflow: hidden !important; float: left !important; padding: 0 5px 0 0 !important; } .card-body { padding: 1px 1px 1px 1px !important; } .card-footer { position: relative !important; } }But this is nowhere near close to what I was aiming…
This is how it used to be with iframely and what we are aiming:

This is how ugly it looks right now


I hope you can help with this transformation

Thanks,