Nordstjernen Browser 1.0.23 released!
Today, 8 August 2026, we are pleased to announce the release of Nordstjernen 1.0.23. The headline is that the browser prints: Ctrl+P lays the page out for paper and hands the sheets to the operating system’s own print dialog. Underneath it are the layout fixes that came out of getting there — correct offsetLeft and offsetTop, flexbox static positions, flex-wrap: wrap-reverse and CSS Scroll Snap — and a JavaScript engine moved up to quickjs-ng 0.16.1. Nordstjernen is a web browser, written from scratch in C, focused on supporting the HTML and CSS standards. It runs on Windows, macOS and Linux, with builds for Android, iOS, FreeBSD, NetBSD and the JVM. Nordstjernen is built in Norway.
Nordstjernen Browser version 1.0.23 is available now! Read the full release notes here, or jump straight to the downloads.
It ships alongside Northstar 1.0.7, the GPL-licensed single-process edition of the same engine.
about:start page — the Nordstjernen Navigator splash, over the night side of the earth. more screenshots »what’s new in 1.0.23
- The browser prints.
Ctrl+P, or Print… in the menu, lays the page out for paper and hands the sheets to the operating system’s own print dialog throughGtkPrintOperation— CUPS on Linux, the Win32 printer dialog on Windows, the Cocoa panel on macOS — so no printing code is written per platform and no dependency is added. The sheets are cairo recording surfaces, which cross no process boundary, so the print action needs the in-process renderer: it works under--single-process(orNS_SINGLE_PROCESS=1) and reports Nothing to print otherwise.--dump=print:FILErenders the same pagination to a multi-page PDF from any mode, and needs no printer. - The CSS a printer needs.
@media printnow matches — the media type was hardcoded toscreen, so a page’s print stylesheet was simply ignored.@pagesets the sheet size from a name (A4,letter,legal,ledger, the A and B series), from one or two lengths, or fromportrait/landscape, along with its margins.break-before,break-afterandbreak-inside— with the legacypage-break-*spellings mapping onto them andalwaysbecomingpage— decide where a sheet may end. A sheet is cut at a forced break when one falls before the page is full; otherwise the cut is pulled up above any box it would split, which is every leaf box, every line of a paragraph, and anything asking forbreak-inside: avoid. Printing restores the on-screen layout afterwards, so the page a reader is looking at does not reflow under them. offsetLeftandoffsetTopare measured from the offsetParent again. Both returned a document coordinate, built from the margin box rather than the border box, so an element inside any positioned ancestor reported where it sat on the page instead of where it sat in its parent. CSSOM View asks for the distance from the offsetParent’s padding edge, with a statically positionedbodyor root the exception every engine makes. A great many pages measure this way, and so does thecheckLayoutharness most of WPT’s layout tests are written against: in the sibling GPL edition, where this was measured, fixing it plus the flex change below tookcss/css-flexboxfrom 653 to 1437 of the same 3535 subtests.- Flexbox static positions and
wrap-reverse. An absolutely positioned child of a flex container landed at the container’s content-box origin whatever the container asked for; CSS Flexbox 4.1 gives it a static position fromjustify-contentand its ownalign-self, as though it were the only flex item, andflex-direction: *-reverse,flex-wrap: wrap-reverseanddirection: rtleach turn around the axis they govern. Andflex-wrap: wrap-reversenow puts the first line last: lines wrapped, but the cross axis was never turned around. Vertical writing modes are not covered — flex layout itself is horizontal-only here. - CSS Scroll Snap.
scroll-snap-typeon a scroll container, withscroll-snap-alignon the things inside it, moves the container onto the nearest snap position once a scroll lands — from the wheel, and fromscrollTop/scrollLeft.scroll-paddingon the container andscroll-marginon an item inset the snapport and outset the snap area, both as shorthands and per side;mandatoryalways snaps,proximityonly from within half a page. A wheel tick shorter than the gap between two snap positions still moves the reader forward rather than falling back to the one behind. This is scroll containers only: the document scroller belongs to the window, not to a box, soscroll-snap-typeonhtmlorbodydoes nothing yet. - JavaScript on quickjs-ng 0.16.1. A regular expression whose
v-flag class contains the empty string,/[\q{}]/v, no longer writes outside the string set it is building. The refresh carries that fix along with the iterator proposals —Iterator.concat,Iterator.prototype.joinandincludes, and the chunking proposal’schunksandwindows, withtakeanddropnow rejecting out-of-range limits — resizable externally managed ArrayBuffers, and a parser that no longer rescans the line to report an identifier’s column. - A processing instruction is parsed as one.
<?target data?>produced a comment that the engine then took apart again by hand, guessing where the target ended; the HTML parser now implements the specification’s own rules, so the node carries a real target and data, a target the specification disallows stays a comment, and serializing one writes<?target data>instead of dropping the target on the floor — which the XML parser’s processing instructions had been doing all along. Two URL fixes come with the same refresh: a caret in a path is percent-encoded, and a URL that has userinfo but no host is rejected. - Two paragraphs measuring the same words come out the same width. The text shaper cached a piece ending in a space together with the kerning the following word had induced on it, so “Type of” was laid out narrow after “Type A” had been drawn, and which paragraph came out wrong depended on what the process had already done. The shaper now asks HarfBuzz which pieces are safe to store.
- Licences and vendored sources. The bundled MP3 decoder and the WebGPU headers match their upstreams again — the headers move to wgpu-native v29.0.1.1, the release the build actually downloads. The third-party notices name every library in the binary: pl_mpeg and minimp3 are compiled into it and were listed nowhere, the wgpu-native headers were missing too, and lexbor’s
NOTICEfile, which Apache 2.0 requires be propagated, was recorded as not existing. - Packaging that builds on a clean machine. A distribution package built from a release tarball now declares the FFmpeg
libav*libraries it needs — meson has required them on Linux and Windows since inline WebM landed, but the Debian control file, the OBS and Fedora spec files, the Alpine APKBUILD and the source-RPM recipe all still described them as optional, so each of those builds failed at configure time. A package built where the build host has no network reaches the system Pango, since ns-pango is cloned by meson at setup time and an OBS worker, an sbuild chroot, a mock root and Alpine’s build phase all forbid that. The source RPM carries a version rpm accepts and installs everything it built, and the Debian tree has the changelogdpkg-buildpackageneeds. - Android, iOS and the JVM compile again. Each of those hosts builds its bridge against the engine’s headers with nothing on the include path but
src/, and printing had put<glib.h>andprint.hinto three of them. Every print entry point moves toprint.hbeside the pagination it drives, and the three headers are self-contained again. The Android bridge also attaches its in-process renderer again, after the callback that hands one over began returning a connection where Android still returned a status code. - Documentation and build instructions. The build instructions install what the build requires: the Debian/Ubuntu, Fedora and openSUSE package lines omitted FFmpeg, so following them exactly produced a failing configure. The documentation stops pointing at files that are not there, the threading model no longer describes a per-tab worker thread that the move to process-per-tab removed, and every link to the project’s own repository points at nordstjernen-web/nordstjernen-browser, its new home. The NetBSD build no longer rests on one package mirror.
about Nordstjernen
HTML Standard. Behaviour is measured against the spec text, section by section, not against another browser — 140 spec rows fully implemented, 31 partial, 0 absent across WHATWG HTML sections 1–16 as of July 2026. Against the Web Platform Tests, the full wpt-fast tree passes 88.4% of subtests overall — 91.7% of the HTML suite. See docs/HTML-compatibility.md.
Secure. Process-per-tab design — each tab's engine runs in its own sandboxed process (seccomp + Landlock on Linux), talking to the UI over IPC and shared-memory framebuffers · no JIT.
Minimalism. The core engine is about 185,000 lines of project C and headers (plus a thin GTK 4 shell), excluding the vendored libraries and generated assets — small enough for one person to read and audit end-to-end.
Private. Nordstjernen has no JIT so it is much more secure, and can still be fast enough. It ships no telemetry of any kind, and deliberately includes no AI assistant and no AI-style web APIs.
news
8 AUG 2026 ·
Nordstjernen 1.0.23 released — printing with @page and print stylesheets, correct offsetLeft/offsetTop, flexbox static positions, CSS Scroll Snap, and quickjs-ng 0.16.1.
Release notes »
8 AUG 2026 · Northstar 1.0.7 released — printing, a rebuilt about:start sky and earth, CSS Scroll Snap, frames that talk to their parent, and quickjs-ng 0.16.1. Announcement » · Release notes »
31 JUL 2026 · Nordstjernen 1.0.22 released — real-site layout fixes, a rebuilt grid, faster text through ns-pango, a reworked toolbar, and a much more capable Android app. Announcement » · Release notes »
31 JUL 2026 · Northstar 1.0.6 released — a rebuilt grid, an indexed CSS cascade, Web Audio that renders, and relative colour syntax. Announcement » · Release notes »
28 JUL 2026 · Nordstjernen 1.0.21 released — Media Queries Level 4, in-engine SVG, HLS and DASH streaming, a redesigned about:start, and honest client hints. Announcement » · Release notes »
22 JUL 2026 · Nordstjernen 1.0.20 released — WebGL on by default, a blinking caret, site-compatibility and memory-safety work. Announcement » · Release notes »
5 JUN 2026 · Nordstjernen 1.0.0 released — the first stable release. Announcement » · Release notes »
download
Latest tagged release: Nordstjernen 1.0.23 — released 8 August 2026. full release notes »
Nordstjernen is also available on the Microsoft Store and Google Play.
| Windows | nordstjernen-windows-x86_64.zip · Microsoft Store |
|---|---|
| macOS | nordstjernen-macos.dmg |
| Debian | nordstjernen-debian-amd64.deb |
| Ubuntu | nordstjernen-ubuntu-amd64.deb |
| openSUSE | nordstjernen-opensuse-x86_64.rpm |
| Linux (portable) | nordstjernen-linux-x86_64.zip |
| Alpine (musl) | nordstjernen-alpine-x86_64.apk |
| FreeBSD (portable) | nordstjernen-freebsd-x86_64.zip |
| NetBSD (portable) | nordstjernen-netbsd-x86_64.zip |
| Android | Google Play |
| Java API (JDK 21) | nordstjernen-java.jar · API docs |
| Source | 1.0.23.tar.gz · 1.0.23.zip |
| All releases | github.com/nordstjernen-web/nordstjernen-browser/releases |
Nightly builds are rebuilt from main each night and point at the
latest code — bleeding edge, expect rough edges. See
all nightly files and their
checksums.