MoreRSS

site iconThe Practical DeveloperModify

A constructive and inclusive social network for software developers.
Please copy the RSS to your reader, or quickly subscribe to:

Inoreader Feedly Follow Feedbin Local Reader

Rss preview of Blog of The Practical Developer

How dev.to became my comfortable corner of the internet (and my New Year resolution)

2026-02-10 06:40:35

It has been a little over 10 years since I deleted my Facebook account.

No long post. No explanation. I just logged out and never went back.

I never joined Instagram either. Or Twitter. Or Snapchat. Or any other social networking platform. That always surprises people, but honestly, it never felt like something I needed.

And after all these years, I can confidently say this

I do not miss it at all.

The peace that came with logging out

Back then, Facebook just felt loud. Everyone was sharing everything. Opinions, achievements, arguments, perfectly happy lives. I would scroll and somehow feel worse than when I started.

Deleting it gave me something I did not even know I was craving. Quiet.

No constant comparison. No endless updates from people I barely spoke to. No pressure to react, like, comment, or keep up.

Once that noise was gone, I never felt the urge to go back.

Yes, I do have LinkedIn

I do have LinkedIn, but my usage is very limited.

Mostly because even there, comparison sneaks in. You see people announcing promotions, new roles, startup wins, big milestones. And even if you are happy for them, a tiny part of your brain goes

Should I be doing more?
Am I behind?

That jealousy is human. I feel it too. So I keep my time there minimal and intentional.

How I found dev.to

I enjoy technical writing. I always have.

For a long time, I would write technical articles and share them on LinkedIn. That was the only place I knew. Around that time (close to six years ago), a friend of mine suggested I try dev.to instead.

Their reasoning was simple

If you enjoy tech, share it where it helps the community

Let others learn from your experience and you will learn from theirs too

That idea stuck with me.

Why dev.to feels different

dev.to feels like a completely different space.

It does not feel like a highlight reel. It feels like a shared journey.

People celebrate each other when things work. And when things break, people are genuinely heartbroken together. Builds fail, ideas flop, bugs refuse to die and everyone learns from it.

There is honesty here. You see what worked and what absolutely did not. And that makes success feel real, not staged.

It feels less like performing and more like sharing.

A small New Year resolution

This year, my New Year resolution was simple

Be more socially active on dev.to

Comment more. Engage more. Participate in conversations instead of just reading quietly.

At the same time, I promised myself I would keep an eye on my well being. If it ever starts feeling heavy or competitive or draining, I step back.

So far, so good.

No anxiety. No doomscrolling. Just learning, conversations, and the reminder that everyone is figuring things out as they go.

Final thoughts

I do not miss Facebook.

I do not miss Instagram.

I do not miss being everywhere.

What I value now are smaller, intentional spaces where people show up as humans, not brands.

And dev.to feels like one of those rare corners of the internet where that still exists.

If that ever changes, I know I can log out again. And that is a pretty comforting thought.

[SUI] Alertas

2026-02-10 06:27:54

Se puede usar una alerta para pedir confirmación de parte del usuario.

  • alert(_:isPresented:actions:message:). title es el título de la alerta. message es un ViewBuilder que devuelve el mensaje de la alerta. actions es un ViewBuilder que devuelve las acciones de la alerta.
struct ContentView: View {
  @State var isPresented: Bool = false
  var body: some View {
    VStack {
      Text("Hola mundo")
      Button("Abrir alerta") {
        isPresented = true
      }
    }
    .alert("Error", isPresented: $isPresented) {
      Button("OK") {
        // ⚠️ Al presionar cualquier acción, automáticamente 
        // se cierra la alerta
      }
    } message: {
      HStack {
        Toggle("Toggle", isOn: .constant(true))
        Text("El mensaje debe ser solo texto. El toggle no aparece. Además, solo se muestra la primera vista: o sea, Toggle")
        Label("Hola", systemImage: "pencil")
      }
    }
  }
}

El rol es importante dentro de la alerta. Notar que si solo pongo una acción de tipo "destructiva", entonces "por arte de magia" aparece una acción para cancelar.

struct ContentView: View {
  @State var isPresented: Bool = false
  var body: some View {
    VStack {
      Text("Hola mundo")
      Button("Abrir alerta") {
        isPresented = true
      }
    }
    .alert("Error", isPresented: $isPresented) {
      Button("OK", role: .destructive) {

      }
    } message: {
      HStack {
        Toggle("Toggle", isOn: .constant(true))
        Text("El mensaje debe ser solo texto. El toggle no aparece. Además, solo se muestra la primera vista: o sea, Toggle")
        Label("Hola", systemImage: "pencil")
      }
    }
  }
}

El número de acciones influye en la disposición de los botones. En el siguiente ejemplo notar que la acción 4 se agregó después de la acción 1, pero en el simulador se muestra al final:

.alert("Error", isPresented: $isPresented) {
  Button("Acción 1", role: .confirm) {

  }

  Button("Acción 4", role: .cancel) {

  }

  Button("Acción 2", role: .close) {

  }

  Button("Acción 3", role: .destructive) {

  }
} message: {
  Text("El mensaje debe ser solo texto. El toggle no aparece. Además, solo se muestra la primera vista: o sea, Toggle")
}

Bibliografía

AI News Roundup: Ads in ChatGPT, Discord age checks, and GitHub agentic workflows

2026-02-10 06:19:17

Today’s AI roundup is less about shiny benchmarks and more about the stuff that actually changes developer reality: monetization, identity/age assurance, and workflow automation.

1) OpenAI starts testing ads in ChatGPT (US)

Source: https://openai.com/index/testing-ads-in-chatgpt/

OpenAI is running an ad test for logged-in adult users in the US on the Free + Go tiers.

Key implementation details worth noting:

  • Ads are explicitly separated from answers and labeled as sponsored.
  • Ads don’t influence the model’s answers (claim), but ad selection can use: conversation topic, past chats, and past ad interactions.
  • Privacy posture: advertisers get aggregate reporting only; no raw chats, chat history, memories, or personal details.
  • Sensitive-topic restrictions: no ads near health / mental health / politics, and no ads for users under 18 (including “predicted under 18”).
  • “Pay to remove ads” has a new twist: Free users can opt out of ads in exchange for fewer daily messages.

BuildrLab take: if you’re building an AI product, you’re watching a big pattern solidify:
(1) paywall, (2) usage caps, (3) ads. Expect customers to ask you for the same knobs (and regulators to ask for the same disclosures).

2) Discord rolls out global age verification (face scan, ID, and inference)

Source: https://www.theverge.com/tech/875309/discord-age-verification-global-roll-out

Discord is moving to “teen-by-default” accounts globally next month unless a user can be verified as an adult.

What’s interesting here (for builders) is the multi-signal approach:

  • Face-based age estimation via video selfie (Discord claims it runs on-device and the video doesn’t leave the device).
  • ID verification via third-party vendor (Discord says images are deleted quickly, often immediately after confirmation).
  • An age inference model using metadata + behavioral signals (games played, activity patterns, signs of working hours, time spent on Discord) to bypass explicit verification when confidence is high.

BuildrLab take: this is the modern “trust stack” for consumer platforms:

  • you’ll need progressive verification (inference → frictionless checks → high-friction checks),
  • strong data minimization (store the result, not the artifact),
  • and vendor risk management (they’ve already had a vendor breach).

3) GitHub publishes “Agentic Workflows”

Source: https://github.github.io/gh-aw/

GitHub has a public write-up on agentic workflows — essentially, patterns for delegating work to coding agents safely and repeatably.

The high-signal angle isn’t “agents write code” — it’s how you operationalize them:

  • deterministic environments (containers/devcontainers),
  • constrained permissions (least-privilege tokens),
  • reproducible review gates (PRs as the unit of change),
  • and explicit context (repo docs that act like a contract).

BuildrLab take: if your team’s agent output is inconsistent, it’s usually not the model — it’s that your workflow is under-specified. Treat your repo as a product: tight CI, clear contribution rules, and reviewable diffs.

4) Worth a read: “Experts have world models. LLMs have word models”

Source: https://www.latent.space/p/adversarial-reasoning

A useful framing piece: humans compress the world into causal models; LLMs compress text into statistical structure. It’s a reminder to build systems that measure and verify rather than simply “trust the vibe” of a good completion.

If you’re building something in this space and want a pragmatic architecture review (cost, safety, guardrails, evals), BuildrLab lives in this stuff. Drop us a line at https://buildrlab.com.

I built a self-hosted Docker platform in Go

2026-02-10 06:13:46

usulnet — Self-hosted Docker management platform

I've been building usulnet, a self-hosted platform for managing Docker
infrastructure. It's a single Go binary that handles containers, images,
volumes, networks, stacks, security scanning, backups, monitoring,
reverse proxy, SSH/RDP/database connections, and multi-node deployments
— all from one web UI.

Key highlights:
• Single binary (~50 MB), no Node.js or Python dependencies
• Trivy security scanning with CVE detection and scoring
• Multi-node master/agent architecture with NATS + mTLS
• Built-in terminal (xterm.js), code editor (Monaco), Neovim in browser
• 11 notification channels (Slack, Discord, Telegram, PagerDuty, etc.)
• RBAC with 44+ permissions, 2FA, LDAP/OIDC
• Backup & restore to S3/local with cron scheduling
• Reverse proxy management (Caddy + Nginx Proxy Manager)
• Full REST API with OpenAPI 3.0 docs

Tech stack: Go, Chi, Templ, Tailwind CSS, Alpine.js, HTMX, PostgreSQL,
Redis, NATS.

Fast deploy (60 seconds, auto-generated secrets):
curl -fsSL https://raw.githubusercontent.com/fr4nsys/usulnet/main/deploy/install.sh | bash

GitHub: https://github.com/fr4nsys/usulnet
License: AGPL-3.0

This is the first public beta (v26.2.0). It's functional and used in
production, but there may be rough edges. Bug reports and feedback are
very welcome — please open an issue on GitHub.

CVE-2026-25498: Crafting Chaos: RCE in Craft CMS via Yii2 Behavior Injection

2026-02-10 06:10:06

Crafting Chaos: RCE in Craft CMS via Yii2 Behavior Injection

Vulnerability ID: CVE-2026-25498
CVSS Score: 8.6
Published: 2026-02-09

A high-severity Remote Code Execution (RCE) vulnerability exists in Craft CMS versions 4 and 5, specifically within the assembleLayoutFromPost method. The flaw stems from the unsafe usage of the Yii2 framework's dependency injection container, allowing authenticated administrators to inject malicious configuration arrays. By leveraging Yii2 'Behaviors,' attackers can achieve arbitrary code execution during object instantiation, effectively turning the CMS against its host server.

TL;DR

Authenticated RCE in Craft CMS (v4/v5). The fieldLayout parameter allows attackers to inject Yii2 Behaviors into object creation. By attaching AttributeTypecastBehavior, an attacker can trigger shell commands during server-side validation. Patch immediately to v5.8.22 or v4.16.18.

⚠️ Exploit Status: POC

Technical Details

  • CVE ID: CVE-2026-25498
  • CVSS v4.0: 8.6 (High)
  • CWE: CWE-470 (Unsafe Reflection)
  • Attack Vector: Network (Authenticated)
  • Impact: Remote Code Execution (RCE)
  • Vulnerable Component: src/services/Fields.php
  • Exploit Status: PoC Available

Affected Systems

  • Craft CMS 4.x (< 4.16.18)
  • Craft CMS 5.x (< 5.8.22)
  • Craft CMS: >= 4.0.0-RC1, < 4.16.18 (Fixed in: 4.16.18)
  • Craft CMS: >= 5.0.0-RC1, < 5.8.22 (Fixed in: 5.8.22)

Code Analysis

Commit: 395c64f

Fixed behavior injection vulnerability in Fields service

--- a/src/services/Fields.php
+++ b/src/services/Fields.php
@@ -1,4 +1,4 @@
- $config = Json::decode(Craft::$app->getRequest()->getBodyParam($paramPrefix . 'fieldLayout'));
+ $config = ComponentHelper::cleanseConfig(Json::decode(Craft::$app->getRequest()->getBodyParam($paramPrefix . 'fieldLayout')));

Exploit Details

Mitigation Strategies

  • Update Craft CMS to the latest patched version immediately.
  • Restrict access to the Craft CMS Control Panel to trusted IP addresses only.
  • Implement WAF rules to detect as or on keys in JSON payloads sent to administrative endpoints.

Remediation Steps:

  1. Log in to your server via SSH.
  2. Navigate to your Craft CMS project root.
  3. Run composer update craftcms/cms.
  4. Verify the installed version is >= 4.16.18 or >= 5.8.22.
  5. Check composer.lock to ensure the package is pinned to the secure version.

References

Read the full report for CVE-2026-25498 on our website for more details including interactive diagrams and full exploit analysis.

drop_down_menu.js Module in WebForms Core

2026-02-10 06:09:56

What is WebForms Core?

WebForms Core is a modern technology from Elanat, introduced in 2024, that is actually a new multi-paradigm in web development. This technology is a two-way protocol that establishes automatic communication between a server-side class called WebForms (available for various programming languages ​​such as C#, PHP, Python, and Java) and a client-side JavaScript library called WebFormsJS. Its main goal is to manage HTML elements and manipulate the DOM directly from the server, in a way that largely eliminates the need for extensive front-end development and writing complex client-side code. In this model, instead of sending large amounts of data or the entire HTML structure, the server sends concise commands in the form of INI format to the client for precise and targeted updates, which leads to reduced bandwidth consumption, near-zero latency, and high server scalability. This approach addresses the common challenges of front-end framework complexity, high dependencies, and large node_modules, and encourages developers to focus more on server-side logic.

How to use WebForms Core technology?

Two steps are required:
1- On the client side: Add the WebFormsJS script to your HTML page.

<script type="module" src="/script/web-forms.js"></script>

Get the WebFormsJS script from the following link:
https://github.com/webforms-core/Web_forms/blob/elanat_framework/web-forms.js

2- On the server side: Import the WebForms class for your programming language.
Get the WebForms class associated with the server programming language from the following link:
https://github.com/webforms-core/Web_forms_classes

Server-side JavaScript Module Loading Feature

One of the standout features of WebForms Core is the ability to dynamically load JavaScript modules from the server. This feature revolutionizes the way client code is managed and executed and offers several benefits:

Benefits of server-side JS module loading:

  1. Intelligent Lazy Loading: JavaScript modules are loaded only when needed
  2. Better memory management: Prevents unnecessary code loading in the browser
  3. Increased performance: Reduces initial page load time
  4. Higher security: Better control over code executed on the client side
  5. Maintainability: Centralized module management on the server

How it works:

WebForms Core loads JavaScript files from the specified path using the LoadModule() method and then makes specific functions of that module available. This mechanism allows for dynamic interaction between the server and the client.

Introducing the example: DropDown Menu module

Exploring the drop_down_menu.js module

The dropdown menu module is a practical example of WebForms Core capabilities that demonstrates how complex UI components can be created by working together on the server and client. This module is available at the following GitHub address:

Module address: https://github.com/webforms-core/Web_forms/blob/elanat_framework/module/menu/drop_down_menu.js

Main methods of this module:

  1. ddm_AddItem(text, url, level): To add new items to the menu
  • The level parameter specifies the hierarchical structure of the menu
  1. ddm_ResetMenu(): To clear all menu items and reset it

  2. ddm_Render(className, appendMenuCSS): To render the menu and generate HTML

  • Automatically injects the required CSS
  1. ddm_GetMenuCSS(className): To get the menu CSS styles

  2. ddm_InjectMenuCSS(className): To inject styles into the head section Page

Example of use in server (C#):

This example was created using the Elanat team's backend framework, CodeBehind. You can use WebForms Core technology in all popular web programming languages.

Note: WebForms Core technology and the CodeBehind framework are similar in naming to Microsoft's former WebForms; however, they are both powerful, modern systems that offer advanced functionality and operate differently from Microsoft's WebForms.

Project Root

├── WebForms.cs          // WebForms Class in Server
├── Controller.cs
├── wwwroot
│   ├── page.aspx
│   └── script
│       ├── web-forms.js // WebFormsJS in Client
│       └── module
│           └── drop_down_menu.js

View (page.aspx)

@page
@controller ModuleDropDownMenuController
<!DOCTYPE html>
<html>
<head>
    <title>DropDown Menu Module</title>
    <script type="module" src="/script/web-forms.js"></script>
</head>
<body>
    <h1>WebForms Core - DropDown Menu Module</h1>
    <button id="Button1">Click me!</button>
    <p id="pTag">
    </p>
</body>
</html> 

Server Response (Controller.cs)

using CodeBehind;

public partial class ModuleDropDownMenuController : CodeBehindController
{
    public void PageLoad(HttpContext context)
    {       
        if (context.Request.Query.ContainsKey("action"))
        {
            Button1_OnClick(context);
            return;
        }

        WebForms form = new WebForms();

        form.SetGetEvent("Button1", HtmlEvent.OnClick, "?action");

        Control(form);
    }

    private void Button1_OnClick(HttpContext context)
    {
        WebForms form = new WebForms();

        form.LoadModule("/script/module/drop_down_menu.js", ["ddm_AddItem", "ddm_Render"]);

        form.CallModuleMethod("ddm_AddItem", ["Home", "/"]);
        form.CallModuleMethod("ddm_AddItem", ["Product", "#"]);
        form.CallModuleMethod("ddm_AddItem", ["Laptop", "/laptops", "-"]);
        form.CallModuleMethod("ddm_AddItem", ["Gaming", "/laptops/gaming", "--"]);
        form.CallModuleMethod("ddm_AddItem", ["Office", "/laptops/office", "--"]);
        form.CallModuleMethod("ddm_AddItem", ["Mobile", "/mobiles", "-"]);
        form.CallModuleMethod("ddm_AddItem", ["Budget", "/mobiles/budget", "--"]);
        form.CallModuleMethod("ddm_AddItem", ["Midrange", "/mobiles/midrange", "--"]);
        form.CallModuleMethod("ddm_AddItem", ["Flagship", "/mobiles/flagship", "--"]);
        form.CallModuleMethod("ddm_AddItem", ["Contact", "/contact"]);
        form.CallModuleMethod("ddm_AddItem", ["About", "/about"]);

        form.SetText("pTag", Fetch.ModuleMethod("ddm_Render"));

        Control(form, true);
    }
}

Page request

When the "page.aspx" page is requested by the user's browser, a new instance of the controller named "ModuleDropDownMenuController" is created and the PageLoad method is called.

In this method, the presence of the "action" query in the request is first checked, if it is present, the "Button1_OnClick" method is executed.

Next, a new instance of the WebForms class is created and a click event is requested from the server for the HTML button with id "Button1" and the query "?action" is assigned.

Calling the Control method causes the following HTML comment (containing the WebForms commands) to be added to the "page.aspx" page.

...
</body>
</html>
<!--[web-forms]
EgButton1=onclick|?load-->

Button1_OnClick method

Purpose of the function

This function handles the click event on the Button1 button and creates a drop-down menu and displays it on the screen.

Steps to execute the function:

1. Create a WebForms object

WebForms form = new WebForms();

A new instance of the WebForms class is created that handles the communication with the client side.

2. Load the JavaScript module

form.LoadModule("/script/module/drop_down_menu.js", ["ddm_AddItem", "ddm_Render"]);

This command does two things:

  • Loads the drop_down_menu.js file from the specified path on the client side
  • Makes the two functions ddm_AddItem and ddm_Render available from this module

3. Adding menu items

form.CallModuleMethod("ddm_AddItem", ["Home", "/"]);
form.CallModuleMethod("ddm_AddItem", ["Product", "#"]);
// and more...

Each of these commands adds an item to the menu. Parameters in order:

  1. Item text (e.g. "Home")
  2. Link address (e.g. "/")
  3. Level in hierarchy (optional)

How ​​to display hierarchy:

  • No parameter: Main item
  • "-": Level 1 submenu
  • "--": Level 2 submenu
  • "---": Level 3 submenu and so on

4. Rendering and displaying the menu

form.SetText("pTag", Fetch.ModuleMethod("ddm_Render"));

This command:

  1. Calls the ddm_Render module function
  2. Gets the HTML output of the menu
  3. Replaces the content of the element with id="pTag" with the HTML code of the menu

5. Sending commands to the client

Control(form, true);

Note: Setting the value "true" as the second argument to the 'Control' function will prevent View and Layout from being re-sent in the response.

Sends all WebForms commands set so far to the client as an INI-formatted response.

Final output in browser:

After clicking the button, the following commands are automatically sent from the server to the client in INI format.

Action Controls

[web-forms]
Ml=/script/module/drop_down_menu.js|ddm_AddItem|ddm_Render
lM=ddm_AddItem|Home|/
lM=ddm_AddItem|Product|#
lM=ddm_AddItem|Laptop|/laptops|-
lM=ddm_AddItem|Gaming|/laptops/gaming|--
lM=ddm_AddItem|Office|/laptops/office|--
lM=ddm_AddItem|Mobile|/mobiles|-
lM=ddm_AddItem|Budget|/mobiles/budget|--
lM=ddm_AddItem|Midrange|/mobiles/midrange|--
lM=ddm_AddItem|Flagship|/mobiles/flagship|--
lM=ddm_AddItem|Contact|/contact
lM=ddm_AddItem|About|/about
stpTag=@cMddm_Render

Created hierarchical structure

Home
Product
  - Laptop
    - Gaming
    - Office
  - Mobile
    - Budget
    - Midrange
    - Flagship
Contact
About

Screenshot

The following screenshot shows the rendered dropdown menu after clicking the button.

DropDown Menu

Summary

WebForms Core offers a new approach to web application development by providing the ability to dynamically load JavaScript modules from the server. The example of the drop-down menu module is a good example of how this feature can be used to create interactive and dynamic components.

This architecture not only increases the performance of applications, but also simplifies their maintenance and development. By separating business logic on the server and intelligently managing client resources, WebForms Core provides an ideal solution for modern web projects.

The complete drop-down menu module, along with server and client code, is available from the GitHub repository and can be used as a template for developing other custom modules.