Latest version: 0.9.4 · 31 August 2026

What's new.

Every version and what changed in it. Nothing Neuridion builds ever contacts us — your applications announce nothing, to anybody. The development environment does quietly ask for a newer version and offers it when there is one (the one call home it makes — see privacy); this page is the long form of that offer. Bookmark it, or look when you feel like it.

Releases

0.9.4

Latest release 31 August 2026

The release where time gets a shape: a calendar you drag appointments around in — and drag work into from a list beside it — three places a value can live instead of two, and a code editor that finally shows you everything it already knew about your data model.

  • A calendar, as a form object. Point it at a table, name the field an appointment starts in, and it draws them — month, week, day, agenda, or a board with one column per room. Drag one and it writes the new time; drag its lower edge and it lengthens; ⌥ ignores the grid. Draw across a free morning, or double-click an empty space, and the appointment’s own window opens with the times already in it — a rectangle says when, and the rest is what the form is for, so nothing is written until you have filled it in and nothing is lost if you close it. The whole loop — make, look at, move, delete — needs no script at all.
  • Drag a row out of a list and into the week. A list of what has no date yet beside the calendar — orders, repairs, customers — and you drag one into Tuesday morning. The calendar writes nothing itself: it hands your onDropped script the record, the time and the room, and four lines decide what it becomes, because which field means “when” is your data model’s question and not the object’s. Every list’s rows can be dragged out with nothing to switch on; a calendar with no such script refuses the drag outright, rather than accepting it and doing nothing.
  • “I’ll send you the appointment.” form.planner.calendarFile([appointment]).open() writes a real .ics and hands it to the Mac: whoever gets it presses it once and it is in their own calendar, whatever they use. Which field is the beginning, the end and the title comes from the calendar’s own settings, so there is nothing to say twice — and the format’s traps (line folding at seventy-five bytes, an escaped comma, UTC, an all-day end that is the day after) are ours, not yours.
  • The week, on paper. Print among the calendar’s buttons opens the report manager with exactly the appointments on screen — the same road a list takes, so your own report shapes are the ones offered.
  • Your own rule, shown the calendar’s way. markAsProblem(appointment, "Six people, and the bridge seats four") puts a red edge and that sentence on one appointment. The rule stays yours — Neuridion has no idea that a room has seats — and only the showing is the calendar’s, so every rule looks the same. And select(record) goes to an appointment, marks it and scrolls it into view: “show me this customer’s visit” in one line.
  • Office hours are drawn quieter. Narrow them inside the hours the calendar shows and everything outside — the weekend with it — steps back, so what is an ordinary working day is something you see rather than read. Left as they are, nothing changes.
  • The pointer says which gesture you are about to make. An open hand over an appointment, an up-down arrow over its lower edge, a closed hand while you have hold of it — so moving and lengthening are told apart before anything is dragged. ⌘ while dragging makes a copy at the new time, the way the Finder copies a file; right-click gives you Open · Duplicate · Delete, or a new appointment at the time under the pointer; ↑ and ↓ walk the appointments in time order, ↵ opens one and ⌫ deletes it. In the month, “+3” is a button: it opens that day.
  • And a script can ask the calendar what it is showing. form.planner.appointments hands back the records on screen in time order, range the stretch they are in, date and view are properties you can read and write, and freeSlots(60, "Room 2") answers the question a board of rooms raises. newAppointment(from, to) draws one from a script, down the same road the mouse takes. The editor completes all of them now, and the calendar has a chapter of its own in the manual.
  • And refusing a move belongs on the table, not on the calendar. Because the calendar writes through the same funnel as the form, the import and every script, a rule written once in onValidate applies to the mouse too: the chip springs back and shows the sentence you wrote. A second place to forbid a move would be one only the mouse knew about.
  • A colour on the appointment itself, beating the colour its kind would have got — a word (blue, teal…) or a hex code, in a field of your own. Nobody has to set anything: a kind that says nothing gets a colour picked from its own name, the same one after every restart.
  • Somebody else moves an appointment and you see it travel. In a Client/Server pair the calendar already re-reads when another desk writes — now it shows the journey rather than the result, with a ring that fades as it lands. It costs nothing on the connection: both pictures were already in memory. A move you made yourself is not animated, because you were there.
  • Every popup, segmented control and search field looks current. No hairline box, a rounder corner, and state carried by the fill rather than by an outline — the same shape the calendar’s own switcher wears. A text field keeps its paper, because a place you type into should read as paper.
  • Three places a value can live, instead of two. A script had its own let and the whole application had a declaration at the top of app.onStart.js — and nothing in between, so a window could remember nothing between two of its own events. People put an invisible text field on the form to hold the value. Now there is form.variable for this window and application.variable for this session. Two windows of one form remember two different things; closing a window forgets its own.
  • And they are declared, which is the point. Name, type, starting value and a note — under Application → Variables and in every form’s inspector. Completion offers your names with their type and note beside them, a misspelt one is pointed out before anything runs, so is a value of plainly the wrong shape, the starting value is there before onOpen does anything, and renaming one rewrites the scripts. Declaring buys help, not permission: a name you never declared still works, it simply gets none of that.
  • A live view of what every window remembers, beside the console: each open window with its values as a tree, the session below it, notes and all — without a breakpoint and without stopping anything. Values of a simple kind can be typed into while it runs. Under Debug, where the application runs inside the editor; Run deliberately starts the very bundle your customer would receive, in its own process, and nothing can look inside that.
  • A name that already means something is refused instead of quietly taken. Call an object on a form variable and form.variable answered with the window’s variables — the object was unreachable and nothing said so. The same for a table called transaction and a field called id. Existing projects are never refused: the to-do list reports them.
  • What a field is for, where you are typing its name. Every field and table has carried a note since the schema editor was built, and it was shown nowhere but in that editor. It is in the completion list now, and hovering a name in a script shows it — for tables, fields and the new variables alike.
  • The editor shows what it already knew. Tables, fields and this window’s own objects each get their own color while you type — painted from the very walk that underlines a misspelt name, so what is colored and what is complained about can never disagree. Red belongs to mistakes and to nothing else.
  • A comparison that can never come true is pointed out. A choice is two things at once: the word a person reads and the value a script compares — and translating moves only the first. Comparing against the label is underlined now, followed through a variable and through a switch. It is the mistake you make on the day you add your second language, and it fails silently.
  • A record out of a loop is a record. for (const customer of database.customers.all()) is the commonest line in the product, and neither the completion nor the checker used to follow it. Both do. In a table event, record on its own knows the table’s fields too — and form in a script that stands in no window is now a warning rather than a line that works from one place and throws from the next.
  • The server says how much memory it is using, minute by minute for the last half hour, on its Activity page — with the trend said in words, because “is it climbing?” is a direction rather than a number. A server is the one thing here that runs for weeks without being quit, so it is the one thing that can have the slow fault.
  • The server gives its sockets back. A finished connection used to leave its file descriptor behind — one per client that ever connected, until a server that had been running for weeks stopped admitting anybody and had to be restarted. Found by a load test that held 8,169 sockets against 8,200 connections; fixed, and guarded by a test that counts them.
  • A pairing request now brings the server’s window to the front page for it, with a sound. A badge in the sidebar is too quiet for the one person it is meant for — somebody standing at the server waiting for a device to appear — and a request nobody finds expires with a no. In the same breath: a client that meets a different server offers to pair at once instead of spending a minute deciding it is offline. It can tell the two apart now, before it opens a connection.
  • Applications built here run on other Macs again. The language files a built application shows its users were not being copied into it. On the machine that built it, nothing was wrong; anywhere else it stopped at launch — and only in countries where those files are read, so an English Mac never saw it. Both halves are repaired: the build refuses to finish without them, and a missing translation now costs the English word rather than the application.
  • The server says how busy it really is. The “lane utilisation” figure in the status window had been wrong since an earlier rebuild split the work across queues: it counted parallel work as if it were serial and sat pinned at 100 % under any real load. It is measured from inside the lane now, and there is a half-hour history beside it.
  • A list’s buttons can sit on any side of it. Under the list as before, above it, or down either edge — and down a side they are symbols only, with the word as a tooltip. That is the position’s definition rather than a squeeze: what a rail buys instead of words is room to separate the actions on a record from the actions on the whole set. It also solves the wrapping problem from the other direction: a list is often short of width and almost never short of height, so a dozen buttons of your own fit down the side when they no longer fit underneath.
  • A type change keeps its word. The migration warning has always said "values that do not fit become empty" — now the conversion actually does it. Text that is not a number becomes empty instead of a column of invented zeros; a date column takes only dates; a boolean takes 0, 1 and the two words. Between two number types the cast stays: 3.9 into an integer column is 3, and the warning names both halves now.
  • The development database says when it migrates. Add a field, save, and the console prints the plan — the same sentences your customer's dialog would show. It always migrated at save time; it just never said so, and a silent migration reads as one that never happened.
  • The retest loop for data fixes. Run Data Update Script Again in the project settings marks the development data as one version behind and runs app.onDatabaseMigration.js again — while you are writing a fix, you no longer have to bump your own gate to see it run twice. And the migration dialog tells your customer when your script will follow: "Afterwards, the application will update its records."
  • One update window. The start-up check and Check for Updates… share one face now, the check runs on every launch, and Later means later — the next start offers again. Never being asked again is its own button, Skip This Version.
  • Your captions and buttons, in your customer's language. Every table gets a Translations entry: one language at a time against your base language — tabs with flags above, each carrying the count of what is still open — typeable in place, and Fill lets the Mac translate what is empty, offline, on your machine. Adding a language translates the whole project in one go, and a missing language pack becomes macOS's own download offer, after which the fill continues by itself. The one rule the whole system stands on: what a human translated, the machine never touches again — change a base text later and your translation turns yellow and asks, instead of being silently replaced. Scripts mark their sentences with language.text("Saved!"), placeholders travel with the translation, and a translation that loses one is reported before it ships. One checkbox per language in the build, an honest count of what is missing, and the application follows the Mac in front of its user. The long form is a manual chapter of its own.
  • The manual says how long a command takes. Timing badges on the commands where a number means something — measured on a 7,500-invoice database, never guessed — with traffic-light colors: green never needs a thought, amber is felt in a loop, red takes real time. Reading a 50-row page is 2 ms; hashPassword is 110 ms on purpose.
  • Full words in the API, to the last three. avg, min and max were the one abbreviation that had slipped through — they are average, minimum and maximum now, in the editor's completion and the manual alike. Renames are free until 1.0; after it they are forbidden, which is why this happens now.
  • A progress bar with some color in it. The application's progress dialog draws a blue-to-pink gradient now, and whether it offers Cancel is the script's choice (cancelTitle — leave it out for none).
  • Two more languages: Polish and Turkish. Nine now, for everything Neuridion itself puts on a built application's screen — and both can be machine-filled for your own captions, because Apple Translation speaks them. Every language popup wears its flag.
  • Two machines translate, and the clever one stays on your Mac. Apple’s translation is fast and knows nothing about your windows; Apple Intelligence is told where every text stands — and both run without a network. Measured on twelve real captions: a save button went from sparen to Speichern, a column called Order from Anordnung to Bestellung. A hosted model joins the menu when you have one set up, and says out loud that your texts are sent to it.
  • One command marks a script’s sentences. Right-click in the code editor: every text a person will read — alerts, a field’s complaint, a label you write into — is wrapped in language.text(…) in a single edit, undone in one step. A text built with + is handed back to you, one clickable console line per place: it needs placeholder names, and a machine inventing {a} and {b} makes a translation worse than the English it replaced.
  • The fill button says how many. Fill 🇩🇪 Deutsch (1) after changing one caption — because that is what it will do. It translates what is missing and what has gone out of date, never what is already right and never a word you typed yourself. And a switch’s choices travel now too; a popup fed from a table does not, because those are your customer’s names.
  • A record refuses a field it has not got. record.unitPriceeeeeeeeeee = product.price used to run without a murmur and lose the price — it is refused now, and underlined while you type. The red triangle in the sidebar shows both kinds of fault, the last crash and what the checker can see from here, on windows, app scripts and table events alike; hovering names the file and line, and pressing it opens the to-do list.
  • A button that shows everything left to do. Faults, placeholders still to replace (com.example, an empty copyright), and what is simply not finished — untranslated languages, a table nothing shows, your own TODOs. Every row jumps to the place. An assistant can sort the list for you, and it is handed the list alone, never your project.
  • Server: pairing is a list, not a sheet. Devices asking to pair get their own page in the status window — one row per request, the code large because only the code is trustworthy, a badge in the sidebar instead of a modal dialog over everything. Three desks of a new office are three rows, answered in any order; a request nobody answers is refused after three minutes, so the person at the other end gets an answer instead of a wait. And the status window's sidebar speaks all seven languages now.
  • A data fix with a name of its own. event.once("1.1 — fill productStart", …). A one-off fix used to run only when the data model had changed, so a change that touches no table — prices into cents, a spelling corrected in ten thousand rows, a field somebody forgot to fill — could never run at all. The name is the identity now: it is written down inside the fix’s own transaction, so a half-run fix and a name that says “done” cannot coexist, and renaming one runs it again.
  • Documents follow their record everywhere. Three places they did not. Exporting a document field wrote the envelope instead of the document, and importing that file back stored the envelope as the content — a row that went out through CSV and came back carried nonsense, with nothing failing. Turning encryption on rekeyed the records and left the file store beside them alone, so the next start said the database was damaged. And deleting a document field left its bytes on the disk for ever, invisible and unreachable — for a project about scans, easily gigabytes. All three are fixed, and the sweep runs after the migration has committed, never inside it, because the safety copy carries no documents.
  • The buttons under a list keep their words. They wrap before they truncate, and when even that is not enough they become symbols with the word as a tooltip — but a measurement that put back only half of what it touched left them standing at symbol width with their words still in them, cut off until the window was resized. A measurement puts back everything it touched, or it is not a measurement.
  • The manual finds a subject, not just a chapter. Its search reads every heading now, which is what the front page had been promising for weeks while it indexed chapter titles — so a subject that is a section could not be found at all. Variables got a chapter of their own out of the same lesson: a subject somebody hunts for twice is a chapter, whatever the outline says.
  • Your own log lines stay visible. macOS’s own chatter is recognized, drawn quietly, and folded with a count when it repeats — twelve identical complaints about something in the system used to bury the one log() you were watching for. Never thrown away, though: a crash report arrives by the same road, and the line nobody expected is usually the interesting one.
  • The IDE, tidied where the hands are: the toolbar's build group is two buttons — hammer and package — and the Build and Run menus carry the same symbols as the bar, so the menu entry and the button read as one act. And Clear Development Data and Reset to Starting State ask first, with the record count in the question — read before write, here too.

0.9.3

27 August 2026

The release that stops assuming everyone is you: your customers get their own language, your first afternoon gets data to design against, and the days when something goes wrong on somebody else’s Mac get a great deal easier.

  • Your application speaks your customer's language. German, French, Spanish, Italian, Portuguese and Dutch, complete alongside English — the backup window, the standard dialogs, the find, sort, import and export windows, the report manager, and every error message a person can be shown. It follows the Mac it is running on, unless you name a language in the project. The client and the server come with it, being the same runtime with a different job. The development environment is never translated, in any version: it is English, and that is what it is. Two consequences worth knowing — inside Run you see what your customer will see, and log entries stay English, because a log is searched, quoted, and pasted to somebody who does not speak the language it was written in.
  • Fill with sample data. Draw a schema, press one button, and every table has rows in it — names that are names, addresses whose ZIP belongs to the city, amounts in a plausible range, invoices due a payment term after they were issued and paid if that day has passed. A field called email gets an address; one called city gets a real one. Parents are written before the children that point at them, so every invoice belongs to a customer that exists. The rows shown before you press the button are the rows that get written — same seed, same data. About four thousand rows a second, and Empty this table is right beside it. It lives in the development environment and nowhere else: a command that fills a database with invented people has no business travelling inside your finished application.
  • A project can carry its own files. Put pictures, text or anything else into the project's assets/ folder — subfolders as deep as you like — and reach them by path: files.asset("logos/harbour.png") hands back the same object a document field does, so .text and .textAs() work on it and the bytes are read only when asked for. They travel inside the built application; the picture object picks from them through a chooser that walks the folders.
  • Your customer can turn encryption on and off: database.encrypt(), database.decrypt() and database.isEncrypted. Encryption is still your setting and still the sensible default — but when one customer's IT will not have an unreadable file on their server, the answer is no longer "rebuild the application for them". The choice is remembered beside their data, so your next update does not quietly put it back, and the change is a restart: safety copy, convert, begin again.
  • A new project is actually new. It used to arrive with a people table, a list and a sheet, so that the first ▶︎ showed something. The Start window is bound to no table and opens without one, so all that gave you was four fields to delete before starting your own. One window now, and nothing to clear away — and the name and identifier you type are the ones you get, which two separate faults used to prevent.
  • Renaming a form takes its name with it. A form's name is written down in four places, and only one of them was being corrected. Now the five forms.* commands that take a name, the New and Duplicate buttons under every list, and menu items all follow — and the console says how many references changed rather than naming one kind of them.
  • Moving in from another program, tested against seventeen real files. Exports from other database programs with repeating fields and containers, semicolon CSVs with a comma inside an address, quoted fields with line breaks in them, Latin-1, a byte-order mark, JSON wrapped in an envelope. Two faults came out of it: XML that did not follow the layout we expected used to be read as text and come back as one column of nonsense, and a file named in capitals produced a table called cSVKontakte.
  • Your data is safer between versions. Databases written before record revisions arrived repair themselves instead of stopping at a dialog whose only button was Quit. And an older application will no longer open a newer database: it used to migrate the difference in both directions, so a column added by a newer version read as one you had deleted — and was dropped. It refuses now, and says so in words.
  • A migration shows itself before it runs. When an update changes how the data is stored, the application puts the plan on screen first — every step in words, the honest warning that older versions cannot open the data afterwards, and the safety copy named, because a warning that hides the escape hatch is theater. Update the Data or Quit, and a progress bar while it runs. Only where the data lives: the single-user application and the server; a declined update leaves the file untouched and asks again next time.
  • Your own data fixes, once per version. app.onDatabaseMigration.js runs after the data was brought to a newer data model — on the machine that owns the data, the development environment included, never on a client. event.fromVersion and event.toVersion bracket the jump, so a customer arriving three versions late gets one run and every fix guards itself with a version number — the starter code shows the pattern. The whole script is one transaction with its own bookkeeping: throw, and nothing of it is kept; the next start tries again from the same place.
  • A copy asks the disk first. Backups and the migration's safety copy check the free space before the first byte and refuse with both numbers — what the copy needs, what the disk has — instead of failing at the last byte after minutes of copying.
  • When something goes wrong on somebody else's Mac. Help ▸ Show Log in Finder, and Save Diagnostics to Desktop…, which writes one file with the machine, the licence state and the last log lines — the file you attach to an email. Licence keys survive being copied out of a screenshot, where invisible characters come along for the ride. And the notarization sheet now opens with the four steps to make an app-specific password, because nothing can suggest one: it does not exist until Apple makes it, and Apple shows it once.
  • Server: a client that has been unpaired says so and asks for a new code, instead of reconnecting for ever against a door that will not open again — and the address offered for pairing is chosen rather than guessed, with a VPN preferred when there is one. The pairing code is eight digits now, shown as 4+4 — one guess in a hundred million instead of one in a million, and just as easy to compare. Letters were considered and left out on purpose: a code carrying 0/O and 1/l gets compared approximately, and "looks the same, near enough" is the one thing this ceremony exists to prevent.
  • The assistant, on the model you choose. Which model writes your first project is a setting now, not a decision somebody else made — with your own key, as before.
  • Smaller hands, reached for daily: ⌘/ comments the selected lines out and back in, in the code editor and its right-click menu. Every script row in the navigator carries small glyphs saying where it runs — the development environment, the single-user application, the server, the client — so "does this run on the server?" is answered by looking. Generated form pairs open with their colored band at the very top by default (one switch to decline), and in the export window the preview's columns can be dragged — the field order follows, in both directions now.
  • American spelling throughout. Color, license, organization, gray, center — everything Neuridion puts on screen, the manual and this site. It was British for no better reason than that the first file was written that way. The JavaScript API is untouched: it turned out never to have had a British spelling in it, so no command changed its name. One project-format key did — a background's startColour is startColor — which is free to change before 1.0 and impossible after, so it happened now.

0.9.2

24 August 2026

A polish release: the windows got more modern, the help got closer, and long jobs got a progress bar with a Cancel that means it.

  • Header to the top. A window's colored header can now run to the very top, with the traffic-light buttons sitting on it — the modern Mac look, one checkbox per window. The example uses it everywhere, and the form designer draws the buttons on the band so you know which corner to keep clear.
  • The manual, one press away. The completion list and the parameter help both carry a book now: click it — or press ⌥↩ — and the manual opens at exactly that command, format and worked example included.
  • Import and export show progress — the application's own progress bar, with a Cancel that rolls a half-done import back to exactly nothing.
  • Record locking, by hand too: record.lock(), unlock() and lockedBy(), with their own manual chapter. On a server, locking stays automatic — taken at the first change, never on open.
  • The About window is yours: free text with working links, written in the application settings — bold, italic, or just a line of copyright.
  • Build output, your choice: just the app, a zip, or a designed disk image — icons, arrow, drag to Applications — now also for client-server builds, with all three products in a row.
  • Server room: the network path was separated from the write lane and dead connections are noticed in seconds, so many clients feel lighter; the requests-per-second figure now tells the truth; and the status window wears the application's color up into the title bar.
  • Client care: after a self-update the previous version goes to the Trash instead of standing beside the app, and the client's About shows its own icon.
  • The license has a window of its own, and a by-hand update check answers right where you are — neither drags the welcome window up any more.
The manual, open inside Neuridion at a command, with its tip and its worked example
The manual travels inside the IDE: search across commands, chapters and words — and every command carries a worked example that opens where you land.

0.9.1

23 August 2026

A big one, and all of it built and running — not a plan.

  • Client/Server is here. One server holds the data, a client on every desk — they find the server on the network, pair with a short numeric code, and every wire is end-to-end encrypted. Record locks say who is editing what and let go the moment they leave a field; the server carries its own client, so new desks and updates need no hand-copying. It ships as Neuridion PRO, on sale now.
  • A full manual — every command with a worked example, the form objects, and honest chapters on performance and limits. In the IDE behind the book button, and on this site.
  • The server watches itself: a status window with request and answer-time curves, the slowest queries, every connected desk live — and now a lane-utilisation gauge and a connections-over-time chart, so you can see at a glance whether the server is bored or at its limit.
  • A log for every product (IDE, single-user, client, server) with levels — errors and warnings always, the rest by a project setting. When something goes wrong at a customer's, that file is what they send you.
  • The IDE now checks for a newer version at start-up (a switch in Settings stops it). Nothing it builds ever does.
  • Restore works on a running server; the reconnect overlay, pairing and the build dialog all got their rough edges filed off.

We flooded our own server to find its edge — the honest numbers are on the Client/Server page.

0.9.0

20 August 2026 · first public beta

The first version anybody outside can download. Everything below is built and running — nothing in this list is a plan. What is still missing is on the roadmap, with reasons.

The two days before it left the building

The version was finished in a stretch, and these are the things that changed in it last. They are listed first because they are the ones most likely to surprise somebody who saw an earlier build.

  • Every list can do things to a row. Add · Duplicate · Remove are buttons the list brings with it — they open the right window, set the relationship, leave out the unique and computed fields when copying, ask before deleting and do it in one transaction. They also gray themselves out when nothing is selected. A fifth kind just runs a script of yours. Nobody writes those three lines again, and nobody forgets the reload afterwards.
  • Computed fields. A field whose value is a formula — total = quantity * price — stored as a real column and filled on the way in, so sorting and summing it is the database's job. Change the formula later and every existing row is worked out again on the next start, in dependency order.
  • Setting a list up happens at the list, in a sheet of its own: columns, row buttons and behavior, with the real list as a live preview and dragging to reorder. The inspector holds an object's properties; a sheet holds its collections.
  • The find, sort, import and export windows are on every list, not just one — and in a Data menu as well. They are windows your customer gets, in the application you ship, without you building any of it.
  • Sound joins the messages group. messages.beep() and messages.playSound(name) — your own files from the project assets or any of macOS's fourteen. Two in the same tenth of a second are one, so a loop over four thousand rows is not four thousand noises.
  • The example projects were rebuilt. Harbour Supply is now eleven windows, 89 scripts and seven reports and uses all 26 kinds of form object — it had been half a demonstration, with cards that opened whichever record happened to be first. The benchmark was rebuilt too: three cards that say in words what changed, and a chart that draws only what actually moved.

Starting a project

  • Three ways in. Empty; or from an example that arrives with its data, so the first thing you see is a working application whose copy is genuinely yours; or describe your business in a paragraph and let a model propose the data model.
  • The describing route asks back. Two to five multiple-choice questions rather than an open conversation, every one with a fallback so nothing blocks the button. Whatever comes back that does not hold up — a field type that does not exist, a relationship between tables nobody mentioned, a script that does not parse — is left out and named on screen before anything is created.
  • Names come back in the language you wrote in. Your tables, your words.
  • And that is the only place a model is involved. There is no assistant looking over your shoulder while you work, and there will not be one.

Building windows

  • The window assistant asks which fields, in what order and grouped how, with a live preview drawn by the same builder that makes the real thing. Groups become frames or tab pages and you decide which — with the height quoted, so a form taller than a laptop screen is something you read rather than discover.
  • The list is real AppKit — draggable columns, editing in the cell, no thousand-row ceiling, and a footer under each column that sums over the whole set rather than over what is on screen.
  • Named styles. Seven decisions under one name, with a default per kind of object; the object always wins as a visible exception, and a script can put a style on while the application runs.
  • Twenty-six kinds of object, charts and barcodes among them, and every one of them is used by the example that ships — which is how we know they all work.

Working with data

  • Choosing a record has four faces — menu, live search, a chooser sheet with your columns, or automatic by counting — and a button beside the field that opens the record you picked.
  • Find & sort, import and export are windows your customer gets too, not just you: several conditions with AND/OR, several sort fields, saved searches they name themselves, import profiles that remember the shape and never the path.
  • Backups that only happen when something was actually written, rotated, with an optional password of their own kept in the keychain. A backup is a plain SQLite file — readable in ten years by anything.
  • Money is a whole number of minor units, everywhere, with one place that converts it and a test nailing the awkward cases down.
  • The database migrates itself when your customer updates: columns and tables matched by identity rather than by name, so a rename stays a rename, and a safety copy taken before any of it runs.

Writing the parts that are yours

  • The editor knows your schema: a mistyped table name gets a dotted underline and a suggestion, ⌘-click opens what you clicked, and help appears when the pointer rests — the field's type, whether it is required, and the note you left in the designer.
  • A debugger worth using: conditions and hit counts on breakpoints, step over and out, values you can open, a post-mortem after a throw, and a query log that makes an N+1 loop visible at a glance.
  • The whole API is synchronous and grouped. database, form, record, event and log are the only free names; everything else lives in a group — including the newest, system, for questions about the machine and the person at it.
  • On-device intelligence. Detect a language, translate, pull fields out of a paragraph — on the customer's own Mac, with no key, no network and no cost. Or point it at a provider of your choosing.

Shipping

  • Build to a signed, notarised .app or DMG. Every application gets a real icon from one picture, drawn into the shape macOS icons wear — and a default one if you supply nothing, rather than the gray placeholder.
  • Starting data: ship the lookup tables (postcodes, VAT rates, the first administrator) and nothing else, chosen by table and remembered by identity.
  • Several projects open at once, one window each.
  • Nothing you build ever asks anybody for a license. No key, no expiry, no network call — see how licensing works.

Known limits, said out loud

  • The project format can still change before 1.0 and there are deliberately no compatibility shims. A project made today may not open in a later version.
  • 0.9.0 never tells you a new version exists. Look at this page when you want to know. From 0.9.1 the IDE asks this site once at start-up — nothing sent along, and a switch in Settings to stop even that. Applications you build never ask us anything, at any time, in any version.
  • Neuridion's own windows inside a built application are English only for now: the backup window and the standard dialogs, in front of a German customer's customers. Translating them is on the 1.0 list.
  • Multi-user is in the beta: the Client/Server build — one server holding the database, a client on every desk, record locking, pairing over the local network. It ships with 1.0 as Neuridion PRO.
  • The beta IDE has no expiry. Applications you shipped are unaffected.

Older versions will be listed here as they are replaced. 0.9.0 is the first one that left the building.