Build your first app
This page builds a small members application from nothing and serves it. Finish Run the demo first, so that you have a working checkout.
An application is a directory. The compiler reads the whole directory as one application, so the file names are for you rather than for the compiler.
my-club/ app.mtd schema.mtd pages/ members.mtd member.mtd1. Declare the application
Section titled “1. Declare the application”app.mtd holds the identity, the roles, the login method, and the menu.
app my_club "My Club" { locale: en mount: / timezone: Europe/Berlin
roles { board "Board" member "Member" }
auth { methods: [password] }
nav main "Club" { members }}Every page names the roles that can open it. Anything a page does not name is denied.
timezone: is the time zone this application is written in. A form reads a time in it, and a
page shows a time in it. The default is UTC, so declare the zone you mean. See
Set the time zone.
mount: is the first path segment the application is served under. mount: / puts this
application at the root of its organization, so route: /members is served at /members. An
application that does not declare a mount is served under its own name, at /my_club/members.
An organization can hold several applications, and at most one of them can be the root. See
App mount.
The menu lists page names. An entry that the reader cannot open is left out automatically, so you never write a second rule to hide it.
2. Declare the data
Section titled “2. Declare the data”schema.mtd holds the tables. The column type decides storage, the form control, and the
checks that run before a write.
table members "Members" { display: last_name, first_name
first_name text required "First name" last_name text required "Last name" email email unique "Email address" joined_on date required "Joined on" { default: today } active bool "Active" { default: true }}display: names the columns that identify a row. Any other table that references this one
shows those columns in its select and in its reports.
The engine adds the primary key and the four audit columns created_at, created_by,
updated_at, and updated_by. A request can never write one of them.
3. Add a list page
Section titled “3. Add a list page”page members "Members" { route: /members access: board
report of members "All members" { columns: last_name, first_name, email, joined_on search: last_name, first_name, email sort: last_name page_size: 25 empty: "No members yet."
row -> member }}row -> member makes each row open the member page, which you write next.
4. Add a form page
Section titled “4. Add a form page”page member "Member" { route: /members/{id} new_route: /members/new access: board
form of members { fields: first_name, last_name, email, joined_on, active actions: save, delete success: "Member saved." }}One page serves two addresses. /members/new renders an empty form that inserts.
/members/42 renders a filled form that updates.
5. Install it
Section titled “5. Install it”go run ./engine/cmd/matterdata install \ -dir .local/tenants \ -tenant my-club \ -app path/to/my-club \ -email admin@example.org \ -password 'choose-a-development-password' \ -role boardThe command compiles the model, creates the tenant database, applies the schema, and creates the first account.
If the model has an error, the command prints the file, the line, the column, and a repair, and writes nothing.
6. Open it
Section titled “6. Open it”Start the engine:
make engineThen open http://my-club.localhost:8080/login and sign in with the address and password you
passed to install.
Sign-in returns you to /, and this application declares no page there, so open
http://my-club.localhost:8080/members. Give a page route: / when you want a home page.
The subdomain is the tenant name. One engine serves every tenant, and each one has its own
database file. Because this application declares mount: /, its pages keep the addresses you
wrote. Remove the mount: line and the same page moves to /my_club/members.
What to read next
Section titled “What to read next”- Show data on a page for filters, records, and dashboards.
- Create and edit records for validation and refusing a save.
- Control who sees what for row rules and per-role columns.
- Column types for every type you can declare.
- How MatterData works for what the compiler does and what happens in one request.