# Objo Studio v26.9.1 Release - Build Web Apps!

**URL:** <https://ifnotnil.com/t/objo-studio-v26-9-1-release-build-web-apps/4840>\
**Category:** Objo\
**Created:** [8 September 2026 14:12 UTC](https://ifnotnil.com/t/objo-studio-v26-9-1-release-build-web-apps/4840 "2026-09-08T14:12:19Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Garry](https://ifnotnil.com/user_avatar/ifnotnil.com/garry/32/2_2.png) [@Garry](https://ifnotnil.com/u/Garry)\
**Post date:** [8 September 2026 14:12 UTC](https://ifnotnil.com/t/objo-studio-v26-9-1-release-build-web-apps/4840/1 "2026-09-08T14:12:19Z")

</div>

Objo Studio 26.9.1 is now available, and this really is a big one.

As is the Objo way, we’ve fixed all reported bugs assigned to this release (44 in total) and added 22 new features and improvements.

You can read about everything in the [full changelog](https://objo.dev/changelog/version-26-9-1), but I’d like to focus on three of the biggest additions.

## Build Web apps visually

Objo Studio can now create Web projects.

This is one of the largest additions we’ve made to Studio so far. You can design responsive browser applications visually, write their behaviour in Objo, run and debug them from Studio, and publish them as self-contained applications.

Web pages use responsive grid layouts with Compact, Medium and Wide breakpoints. This lets you arrange the same controls differently for phones, tablets and larger desktop browsers without maintaining separate pages.

 ![web-designer-compact](https://ifnotnil.com/uploads/default/original/2X/1/1089d0febc18b2ddf9f75ca0a42a4e04d621343f.jpeg)

 ![web-designer-medium](https://ifnotnil.com/uploads/default/original/2X/4/4dd7cebd7aaed1b165416a0e2340db4bfd15cc30.jpeg)

The initial release already includes 22 Web controls, including `Button`, `TextField`, `TextArea`, `ListBox`, `ComboBox`, `Chart`, `Canvas`, `TabPanel`, `ImageViewer`, date and time pickers, and several others. They use native browser behaviour wherever possible and include support for keyboard navigation and accessible labelling.

A Web project can contain multiple pages making it straightforward to build applications with several screens.

Debugging starts a private development server and opens the app in your browser. Breakpoints in page and control event handlers work through Studio’s normal debugger, so you can step through Web application code and inspect variables just as you would in a desktop project.

When the app is ready, Publish produces a self-contained native executable for the selected platform. The destination computer **does not** need Objo Studio or a separate .NET installation.

Web Projects are launching as a **public beta**. They’re already capable of building substantial applications, but I expect the workflow and browser presentation to keep improving as people begin using them in the real world.

There’s far too much to cover properly here, so a dedicated Web Projects post will follow shortly.

## Exact decimal arithmetic

Objo now has a first-class `Decimal` number type.

`Double` is fast and remains the right choice for many calculations, but its binary representation cannot store every decimal fraction exactly. That can be inconvenient when working with money, measurements and database values.

`Decimal` provides exact base-10 values with 28–29 significant digits. Decimal literals use a `d` suffix:

```objo
Var unitPrice As Decimal = 19.95d
Var taxRate As Decimal = 0.2d
Var total As Decimal = unitPrice + (unitPrice * taxRate)

Print(total.ToString()) # 23.94

```

The new type supports arithmetic, comparisons, rounding, parsing, locale-aware formatting and explicit conversion to and from other numeric types.

It also integrates with Objo’s database APIs. Decimal values can be bound directly to prepared statements and retrieved from database columns without first passing through a `Double`.

This is the sort of foundational language addition that may not look flashy in a screenshot, but it makes Objo much more useful for business, financial and data-oriented applications.

## A new TagField control

Desktop projects gain a new `TagField` control for entering and displaying collections of tags.

 ![tagfield](https://ifnotnil.com/uploads/default/original/2X/8/81a3e198c26dd5ea2b3493a8f2a0b6bc59e7913b.png)

The user can type a value and press Return or comma to turn it into a rounded, removable tag. Pasting comma-separated text can create several tags at once, while built-in validation can reject duplicates or limit how many tags are accepted.

Tags can stay on a single horizontally scrolling line or wrap across multiple lines. The control also supports static and dynamically generated autocomplete suggestions, read-only presentation, custom colours and application data attached to individual tags.

Events let your app validate proposed tags, supply suggestions, and respond when tags are added, removed or pressed.

`TagField` is fully integrated into Studio’s visual designer and Inspector, so it can be added and configured in exactly the same way as the other desktop controls.

## Plenty more

Those are the three headline additions, but 26.9.1 contains plenty of other useful improvements:

- `Crypto` can now encrypt and decrypt text or binary data using authenticated AES-256-GCM encryption, including password-based encryption.
- `ListBox` gains cell hit testing, scroll-position controls and the ability to disable column reordering.
- Windows can now be minimised, maximised and restored from code, with new events for completed moves and resizes.
- `DateTime` gains explicit tick precision and a broader collection of truncation helpers.
- `HTMLViewer` now exposes keyboard events.
- Solution search has a convenient inline clear button.
- The Debugger panel can optionally display its own execution controls.
- Autocomplete has been improved for string literals, generated designer properties and contextual shorthand values.

There’s also been a substantial round of fixes across the compiler, debugger, visual designer, controls and editor. These include better handling of nested enumerations, safer asynchronous scheduling, more reliable menu and toolbar editing, and a collection of platform-specific layout and interaction fixes.

Objo Studio 26.9.1 is available now from the [download page](https://objo.dev/download).

I hope you enjoy this release. I’m really looking forward to seeing what people build with Web Projects.

---

<div class="post-metadata">

**Author:** ![DirtyM](https://ifnotnil.com/letter_avatar_proxy/v4/letter/d/73ab20/32.png) [@DirtyM](https://ifnotnil.com/u/DirtyM)\
**Post date:** [13 September 2026 11:05 UTC](https://ifnotnil.com/t/objo-studio-v26-9-1-release-build-web-apps/4840/2 "2026-09-13T11:05:39Z")

</div>

Great update, the addition of web projects is big step up.

What is the memory footprint of hello world web app?

Does it keep an active connection for each opened session?

Can it handle 1000 concurrent connections in 1 minute on a low-medium sized server (4GB Ram + 2 vCPU)?

---

<div class="post-metadata">

**Author:** ![Garry](https://ifnotnil.com/user_avatar/ifnotnil.com/garry/32/2_2.png) [@Garry](https://ifnotnil.com/u/Garry)\
**Post date:** [13 September 2026 15:47 UTC](https://ifnotnil.com/t/objo-studio-v26-9-1-release-build-web-apps/4840/3 "2026-09-13T15:47:02Z")

</div>

Thanks @DirtyM. These are good questions.

A connected browser tab keeps a WebSocket open. Behind it is an isolated logical session with its own VM, `App` instance, pages, controls and state. An idle connection does not poll or consume scheduler turns. If the WebSocket drops, the session is retained for five minutes by default so the tab can reconnect; a connected session that remains idle expires after 30 minutes.

I’ve just rerun the 26.9.1 release with a simple example app to get a concrete figure. Its deliberately small - just a `Button` / `Label` application measured about 3.76 MB of additional managed memory per connected session across 50 sessions. That is not the total resident memory of a literal Hello World host: the .NET runtime, native allocations, WebSocket buffers and base process sit on top, and a real application’s state may increase it.

The host’s default ceiling is 1,000 logical sessions, but that is a safety limit rather than a claim that every application can serve 1,000 users on any machine. The 26.9.1 gate qualifies 50 connected sessions, with 20 driven concurrently for three rounds.

If by 1,000 concurrent connections in one minute you mean 1,000 sessions held open simultaneously, I would not claim that for a 4 GB/2-vCPU server. The measured incremental managed memory alone extrapolates to about 3.76 GB, before accounting for the host, operating system and application data, so there would be no sensible production margin. CPU requirements also depend far more on how many sessions are actively doing work and what their event handlers do than on the number of idle sockets.

So the honest answer is: persistent connection, yes; an exact total Hello World footprint still needs a separate measurement; and 1,000 sessions on 4 GB/2 vCPU has not been qualified and is unlikely to be a sensible target with the current per-session footprint.

---

<div class="post-metadata">

**Author:** ![Stretch327](https://ifnotnil.com/user_avatar/ifnotnil.com/stretch327/32/5162_2.png) [@Stretch327](https://ifnotnil.com/u/Stretch327)\
**Post date:** [13 September 2026 17:23 UTC](https://ifnotnil.com/t/objo-studio-v26-9-1-release-build-web-apps/4840/4 "2026-09-13T17:23:15Z")

</div>

Garry, since you’re using websockets, how are you dealing with the circumstance of a load balancer or just nginx or apache sitting in front of the app?

---

<div class="post-metadata">

**Author:** ![Garry](https://ifnotnil.com/user_avatar/ifnotnil.com/garry/32/2_2.png) [@Garry](https://ifnotnil.com/u/Garry)\
**Post date:** [13 September 2026 17:47 UTC](https://ifnotnil.com/t/objo-studio-v26-9-1-release-build-web-apps/4840/5 "2026-09-13T17:47:03Z")

</div>

@Stretch327 That is the intended production setup. The published application contains a Kestrel host, but for an Internet deployment I expect nginx, Apache, IIS, Caddy or a cloud load balancer to sit in front of it and terminate TLS.

Objo separates the internal listening address from the public origin. For example:

```bash
./MyWebApp \
  --urls http://127.0.0.1:8080 \
  --public-url https://app.example.com

```

The proxy forwards ordinary HTTP requests and the `/ws` WebSocket upgrade. It must preserve the public `Host` and browser `Origin` values. Objo deliberately doesn’t trust arbitrary `Forwarded` or `X-Forwarded-*` headers to manufacture the public origin.

With one Objo process behind nginx or Apache, that is essentially all that is required. The host sends a WebSocket keepalive every 30 seconds, although the proxy’s timeout still needs to permit long-lived connections.

There is an important qualification when load balancing across multiple Objo processes. Each logical session currently lives in the memory of one process. A connected WebSocket naturally remains attached to that instance, but a reconnect must return to the same instance. The load balancer therefore needs session affinity, normally using its own affinity cookie.

Without affinity, a reconnect could reach another process which does not possess that session or recognise its reconnect ticket. There is currently no distributed session store or live migration between hosts, so losing an instance also loses its active sessions. Durable shared application data should live in a database or another external service.
