App mount
mount: is a property of the app block. It names the first path segment every page of
the application is served under.
app sports_club "Sampletown Sports Club" { mount: club}The page at route: /members/{id} is then served at /club/members/17.
mount: is optional. An application with no mount: is mounted at its own name, so
app sports_club without the declaration is served under /sports_club/.
What a mount decides, and what it does not
Section titled “What a mount decides, and what it does not”An organization can hold several applications. Two names come out of the app block, and they
change at different times.
| comes from | changes when | decides | |
|---|---|---|---|
| the mount | mount:, defaulting to the application’s name |
you re-mount the application | every address the application serves |
| the stored table name | the application’s name, always <app>__<table> |
never, after installation | what SQLite calls the table |
So table members in app sports_club is sports_club__members in the file,
whatever the application is mounted at. Re-mounting is free. Renaming the application is a
schema migration, because every table, foreign key and generated expression carries the name.
The short name is what you write and what you read. A ref(members), a
ctx.db.query("members", …), a compiler error and every line of .mtd all say
members.
A mount is one path segment: lower-case letters, digits, _ and -. It starts with a letter
and is at most 40 characters long.
mount: club // served at /club/…mount: club_2026 // served at /club_2026/…mount: "calendar-2026" // a hyphen needs quotation marksAn unquoted value ends at a hyphen, so mount: calendar-2026 is a parse error. Quote the value
to use a hyphen in an address.
mount: / serves the application at the root
Section titled “mount: / serves the application at the root”One application of an organization can declare the root. Its pages then keep unprefixed
addresses, and /members/17 is the member record.
app sports_club "Sampletown Sports Club" { mount: /}Use it for an organization that runs one application and wants no repeated segment in every address, bookmark and calendar subscription.
Three properties follow from the declaration:
- It is opt-in. No application is at the root unless it says so.
- An organization has at most one root application. A second one is refused.
/is that application’s own address, and there is no list of applications. An organization that already names its front door is not asked again. Other applications of that organization still answer at their own mounts, and no engine page links to them. A root application that declares no page atroute: /answers 404 there.
Refusals
Section titled “Refusals”The compiler refuses four mounts
Section titled “The compiler refuses four mounts”Each message carries the file, the line, the column and the repair.
| Declaration | Why it is refused |
|---|---|
mount: Club |
a mount is lower case. Two addresses that differ only in case are one address to some clients and two to others |
mount: club/events, mount: club.org |
a mount is one segment, not a path and not a host name |
mount: 1club |
a mount starts with a lower-case letter |
| a mount over 40 characters | somebody types it into a file and reads it out of an address bar |
The compiler refuses a mount the engine owns
Section titled “The compiler refuses a mount the engine owns”The engine owns 15 first path segments, listed in Reserved names. An application mounted at one of them would sit behind a door the engine answers first.
mount "login" is one of the 15 first path segments the engine owns (…) — they belong to thetenant rather than to any app, so an app mounted at one would never be reachedThis applies to a defaulted mount too. app feed with no mount: is refused. The message
tells you to declare a mount rather than to rename the application:
an app with no mount: is mounted at its own name, and mount "feed" is one of the 15 firstpath segments the engine owns (…) give the app an address of its own: app feed { mount: <segment> }The compiler refuses an application name inside mtd_
Section titled “The compiler refuses an application name inside mtd_”app mtd would store its tables as mtd__members, where the engine keeps the logins, the
sessions and the stored model. app mtd_shop is refused for the same reason.
The refusal is about the name, never the mount. An address may be spelled freely and storage may not.
Installation refuses three collisions
Section titled “Installation refuses three collisions”Whether an organization already has a mount is not a compile-time fact, because the compiler
never opens a tenant file. matterdata install checks it, and the engine checks it again when
it opens the organization.
| Collision | What the message says |
|---|---|
| two applications at one mount | apps "a" and "b" are both mounted at "club" — one of them would never answer |
two applications declaring mount: / |
a tenant has one root — give all but one of them a mount of their own |
| a mount that shadows a page of the root application | the mount wins, so that page would be unreachable. Mount "b" somewhere else, or take the root away from "a" |
The check runs before any table is written, so a refused installation changes nothing:
Nothing was written: the addresses are checked before the tables are. Change `mount:` in<directory> — an address may move freely, and it renames no tableRelated
Section titled “Related”- Add a second application to an organization for the task.
- An organization, its applications and one login for what the applications of one organization share.
- Reserved names for the 15 segments a mount may not take.