MojoPad

Database Views

Your pages already carry structure — tags, types, and your own typed properties (Status, Rating, Author, a due date…). A database view turns that structure into a live table you can filter, sort, and group — a spreadsheet whose rows are your pages. Build one once and it stays current: add a page that fits, change a property, and the view updates itself.

Act on what a view found

A view is a question, and the answer is a set of pages — so it offers ⌖ Select these N, which hands its rows straight to the Pages palette with its bulk bar open. From there any stamp or bulk edit applies to exactly the pages the view found. Describe the set, select it, act on it.

Make one

Run New Database View… from the command palette (⇧⌘P), or View ▸ Database Views… and choose + New. Give it a name and a table opens showing every page, with a few starter columns. From there you shape it with the toolbar across the top — every change saves as you go, and the view is yours to reopen any time from Database Views….

Who is answering

The status bar carries a small mark saying where questions go: ☂ On this Mac or the name of a local model, ⌘ Your own agent, or and the name you gave a provider you set up. It is quiet while the work stays on this Mac and plain when it leaves, it is gone entirely when AI is switched off, and clicking it opens the pane where you change it.

It names what answers by default. A property that pins its own model still uses that one — and the value it writes carries its , which on hover says which model wrote it and when. The mark is the standing state; the ✦ is the record.

Asking a question with brackets

The row of chips under the title is the question the view is asking, and it reads left to right. It begins with a word — All of or Any of — and that word is a button: click it and the view switches between wanting every condition and wanting any one of them.

Brackets let you have both. Press ( ) and a bracket appears with its own All of/Any of word and its own for adding conditions inside it. So papers from 2025 or 2026 that I have not read is: All of — Status is not Read — and a bracket saying Any of — Year is 2025, Year is 2026. A new bracket starts on the opposite word to the one it sits in, because a bracket that repeats its parent asks the same question with more punctuation.

Brackets nest a few deep, which is as far as a question stays readable; past that, the answer is usually a second view rather than more brackets. A bracket you have made but not filled in yet asks nothing at all, so the table holds still while you build it.

Shape it

  • Filter+ Filter, pick a column, a condition (is, contains, greater than, is empty…), and a value. Each shows as a chip you can remove with its , and the All of / Any of words above say how they combine. “Books I’m still reading” is Type/tag is Book plus Status is Reading.
  • Sort — click any column header to sort by it; click again to reverse. (The Sort toolbar button does the same and shows the current order.)
  • Group — the Group button clusters rows under a heading for any column, each with a count: group your books by Status and see how many are Reading, Finished, To read.
  • Columns — the Columns button adds or removes columns. Choose from built-ins (Type, Tags, Created, Modified, word count, open/total tasks) or any of your properties.

The first column is Page, and it is the one you click to open a row. It is called that rather than Title because Title is also a property — the work's own title, which a source lookup fills — and the two would otherwise sit side by side under the same heading meaning different things. Where a page is named by a citation identifier, this column shows the title anyway, and sorting and grouping follow what you can see rather than the identifier underneath.

Click any row to open that page. Close the view with — it’s saved, and reopening it shows the current state of your wiki, not a snapshot.

Computed columns — a formula of your own

In the Columns picker, choose ƒ New computed column… to add a column whose value is calculated from the others. Reference any column by its name in [brackets]:

  • daysBetween([Modified], today()) — how long since each page was touched.
  • [Rating] * 2 — arithmetic on a number property ( + − × ÷ all work).
  • if([Rating] > 4, 'great', 'fine') — conditions; also [Rating] > 4 ? 'great' : 'fine'.
  • if(empty([Rating]), 'unrated', concat([Rating], ' stars')) — handle blanks, build text.

The functions: today(), daysBetween(a, b), if(cond, a, b), round(x, digits), concat(…), contains(text, part), empty(x), and len(text). Formulas are checked as you create them — a typo is caught with a message, and a formula that references a column that doesn't exist shows a small #ref in just that cell, never breaking the row. Computed columns sort, group, and filter like any other (numbers as numbers), and they wear an ƒ in their header. A formula can't reference another formula, so they can never chase each other in circles.

Two ways to draw it: Table and Gallery

The switcher in the toolbar redraws the same view two ways:

  • Table — the spreadsheet: sortable columns, group headers, everything above.
  • Gallery — a wall of cards, one per page: the page's cover image when it has one, its icon and name, a slice of what's written on it, and its first few column values as small chips. Clicking a card opens it over the wall to read, exactly as in The Gallery. Grouping applies here too, so “my books, grouped by status” reads as shelves.

Looking for lanes you can drag between? That is the Kanban Board — a page type of its own, with its own chapter — and for pages that move through stages, the Tasks board groups by area, project, label or status and re-files what you drag. A view is for reading a set of pages many ways; those two are for moving things along.

The layout is saved with the view — a board stays a board next time you open it.

Put a view inside a page

A view doesn’t have to live in its own window. Type / on any page and choose Database view — the view you pick lands in the page as a compact live table. It shows the first dozen rows (with an …and N more link when there are more), refreshes every time the page renders, and clicking its title opens the full view for filtering and shaping. On Markdown pages it round-trips as plain text — ![[view:Reading list]] — the same syntax page embeds use, so you can also just type it. A project page that opens with its own live task table, a reading page headed by your shelf: the page becomes a dashboard.

Format, Page type, Kind — which is which

Three columns can be read as “type”, and reaching for the wrong one is the commonest way a view comes back empty. They answer three different questions:

  • Format — what the page is: Formatted text, Markdown, Canvas, File. You never set it; the page has it by being what it is.
  • Page type — the colored label you assign yourself, from the type pill.
  • Kind — the shape a page belongs to, and the only one of the three that carries properties. If the thing you are thinking of has fields on it, it is a Kind.

So a Kind called Summary with three properties on it is found by Kind contains Summary, and by neither of the others. If you do pick the wrong one, the view says so rather than showing you an empty table: a filter on a column no page in the wiki fills can never match anything, and the view tells you that — and where what you typed is a Kind, it names the column that would have worked.

What the columns can show

Beyond your own properties, every view can show a page’s tags, its Page type (the colored category from the type pill — drawn as its colored chip, and the natural way to build “all my Books”), its Kind — the shape it belongs to, which is usually the one a view wants, since a kind is what makes a set of pages answer the same questions (a page inside a chain of kinds shows the nearest one) — its Format, when it was created or last modified, its word count, and its task counts (open and total, counted from the page’s checkboxes). A word count counts languages the way they are written: scripts that put spaces between words are counted in words, and scripts that do not — Japanese, Chinese, Korean — are counted in characters, with the two added together. That is also the arithmetic those languages’ own publishers use, where a length limit is quoted in characters rather than in words. Numeric columns — ratings, counts — sort and compare as numbers, so greater than and less than filters do what you’d expect; pages missing a value sort to the end rather than pretending to be zero.

Date columns — Created, Modified, and any property you made a date — take a date or a period, written the same way the search bar takes them: 2026-01-01, july, 2026-q3, week, today. They compare as periods rather than as instants, which is what makes them read the way you say them: greater than 2026 means 2027 onward, not “after the first of January”, and is july means any day in July. If a value can’t be read as a date it is refused when you type it, and any older filter that can’t be read says so on its chip rather than quietly matching nothing.