Bases Interface Gaps Report
Bases Interface Gaps Report
Scope: QA validation of _catalog.base (15 views) and _browse.md (15 inline base blocks) against all 59 entries in entries/, using _audit.md as reference. All verification was done by parsing the files and simulating the Bases filter logic in Python (see Render warnings). Round 2 (2026-09-14) implemented 9 additional views from the candidate list below. Round 3 (2026-09-14) converted _browse.md from .base file embeds to inline base blocks after the first live Flowershow publish failed â see Render warnings.
Views that could not be expressed in current Bases syntax
- No cross-facet interactive filtering. A reader cannot combine facets ad hoc (e.g. Beginner + Free + China) â every combination must be pre-baked as a named view. Since round 3,
_browse.mdcarries each view as a self-contained inline base block (filters + single view) rather than embedding_catalog.base, because Flowershow does not support.basefile embeds;_catalog.baseremains the canonical catalog for Obsidian-native use and the two must be kept in sync (the validator enforces name and count parity). - No "warning" or badge semantics. There is no way to surface a status warning (e.g. visually flagging Dormant entries) inside a view; Dormant entries simply appear in the lists with a status column.
- No derived/fallback values. Views cannot synthesize a value (e.g. a type-based icon as a card image fallback for the missing
mediaproperty â audit finding c), so the Cards view ships with no image slot at all. - No "unknown-inclusive" toggle. The 13 entries with
unknownskill_level and/or cost fall out of any value-filtered view (audit finding a). A view must choose to either filter on concrete values or include everything; there is no per-reader toggle.
Implemented in round 2 (2026-09-14)
All counts verified by re-running qa_validate.py against live frontmatter within the 56-entry non-Archived base set; every view matched its expected count.
| View | Filter (Bases syntax) | Entries |
|---|---|---|
| Region â USA | region.contains("USA") | 10 |
| Region â EU | region.contains("EU") | 5 |
| Region â Global | region.contains("Global") | 23 |
| Region â Africa | region.contains("Africa") | 4 |
| Language â Chinese Sources | language.contains("zh") | 11 |
| Curricula â Free | type == "Curriculum" + cost == "Free" | 8 |
| Outcome â 3D Printing | learning_outcomes.contains("3D Printing") | 17 |
| Space â Classroom | space.contains("Classroom") | 34 |
| Beginner + Free â Programs | skill_level == "Beginner" + cost == "Free" + type == "Program" | 6 |
Notes on implementation choices:
- Region â Africa: all 4 Africa-tagged entries also carry
South Africain their region list, so the single-valueregion.contains("Africa")filter is sufficient; the previously suggestedor region.contains("South Africa")is redundant today (documented in a comment in_catalog.base). - Beginner + Free â Programs (6) was added as the only Beginner + Free sub-slice judged substantial enough for browsing.
Deliberately deferred (thin slices)
Verified non-empty but too small to justify a named view â revisit if the vault grows:
| Candidate view | Filter (Bases syntax) | Entries |
|---|---|---|
| Region â Latin America | region.contains("Latin America") | 2 |
| Language â Spanish sources | language.contains("es") | 3 |
| Beginner + Free â Hardware/Components | skill_level == "Beginner" + cost == "Free" + type == "Hardware" or "Component" | 3 |
| Beginner + Free â Curricula | same + type == "Curriculum" (largely covered by Curricula â Free) | 4 |
| Beginner + Free â China | same + region.contains("China") | 2 |
| translation_available == true | translation_available == true | 6 |
Populated fields not yet exposed as filters
Strong candidates (well populated, clean enums, per _audit.md):
maintenanceâ 51 of 59 known (Low 28 / Moderate 21 / High 2). Strong filter; useful for builders budgeting effort. Currently only a display column.spaceâ 52 of 59 populated (7 empty lists, mostly software/policy). Partially exposed in round 2 viaSpace â Classroom(34); Greenhouse (24) is a plausible future slice.climateâ 52 of 59 populated (7 empty lists incl. 1unknown). Strong but skewed: Versatile 43 dominates; Temperate 6 / Tropical 4 / Arid 3 / Cold 1.learning_outcomesâ 57 of 59 known, rich 14-value enum. Partially exposed viaOutcome â 3D Printing(17); no other outcome value is large enough to stand alone today.languageâ 57 of 59 known. Exposed for zh (11); es (3) deferred as thin.statusâ fully populated (Active 45 / Dormant 11 / Archived 3). Strong, but currently only used as a global exclusion; a dedicated "Dormant" surfacing view (11 entries) or a status column on every view (already present on table views) covers it.audienceâ 58 of 59 known, but heavily skewed (Educators 51). Moderate: works as a column, weak as a browse facet.translation_availableâ boolean on 56 of 59 (3 are the stringunknown). Moderate; a strict== truefilter is safe (6 entries); now also shown as a column inLanguage â Chinese Sources.
Weak candidates (too sparse to facet â keep for entry-detail display only, per audit): builds_on (4 populated), prerequisite_for (5), contrasts_with (14), prerequisites (0 â dead field), aligned_with (1), archive_url (null everywhere), source_type (free list, ~52 singleton/doubleton values â usable for search/grouping, not faceting without normalization).
Render warnings / errors
- FIXED (2026-09-14):
.mdxextension incompatible with Obsidian indexing. Obsidian only indexes.mdnotes, so_browse.mdxwas invisible in the app and unavailable to the Flowershow publish plugin. The page was renamed to_browse.md; MDX parsing is preserved via thesyntaxMode: mdxfrontmatter flag, which Flowershow supports as an alternative to the file extension. Lesson recorded: always use.md+ frontmattersyntaxMode: mdx, never the.mdxextension, for pages that must be visible inside Obsidian. - FIXED (2026-09-14): Flowershow does not support
.basefile embeds. The first live publish of_browse.mdfailed withError parsing MDX âĶ Cannot handle unknown node 'raw'. Root cause: the page embedded views via![[_catalog.base#View Name]]inside ```base blocks â valid in Obsidian, but Flowershow's Bases (Beta) only renders inline base YAML blocks and explicitly does not support base-file embeds yet (flowershow/flowershow#861). Fix: all 15 sections of_browse.mdnow carry self-contained inline base blocks (filters + single view each);_catalog.baseis unchanged in view semantics and remains the Obsidian-side catalog. Afile.inFolder("entries")guard was added to every block (and to_catalog.base) as the primary scoping filter. Validator updated to parse and simulate the inline blocks; all 15 pass with their expected counts. - Live rendering after round 3 is UNVERIFIED. The human's final check must be: (1) republish
_browse.mdvia the Flowershow plugin and confirm each ```base block renders as an interactive view rather than erroring; (2) open_catalog.basein Obsidian and confirm all 15 views render. - Embed format now matches Flowershow's documented inline pattern (```base fenced block containing filters + views YAML) â all 15 blocks parse as YAML, hold exactly one view each, and reproduce the expected entry counts under simulation, including the em dash (U+2014) in all
Region â,Language â,Outcome â,Space â,Curricula â, andBeginner + Free ânames. - Byte-level checks clean:
_catalog.basehas no BOM, no tabs, no CRLF, no smart quotes;_browse.mdlikewise (LF endings, no smart quotes,syntaxMode: mdxpresent in frontmatter). - Obsidian-version caveat:
file.hasProperty(...)andlist.contains(...)in filter expressions require a recent Obsidian Bases build; on older versions these expressions may silently fail to parse. Not verifiable here. - Cards view has no image by design (no
mediaproperty exists on any entry â audit finding c). If a future schema change addsmedia, the Cards view should gain an image binding.
Verification results summary
Filter simulation (Python, global filters + view filters, against all 59 real entry files, 2026-09-14):
| View | Expected | Actual | Result |
|---|---|---|---|
| All Resources â Table | 56 | 56 | PASS |
| All Resources â Cards | 56 | 56 | PASS |
| Beginner + Free | 14 | 14 | PASS |
| Beginner + Free â Programs | 6 | 6 | PASS |
| Curricula | 16 | 16 | PASS |
| Curricula â Free | 8 | 8 | PASS |
| Hardware & Components | 12 | 12 | PASS |
| Outcome â 3D Printing | 17 | 17 | PASS |
| Space â Classroom | 34 | 34 | PASS |
| Language â Chinese Sources | 11 | 11 | PASS |
| Region â Global | 23 | 23 | PASS |
| Region â USA | 10 | 10 | PASS |
| Region â China | 12 | 12 | PASS |
| Region â EU | 5 | 5 | PASS |
| Region â Africa | 4 | 4 | PASS |
- Every view has âĨ 1 entry (empty-state check passes).
- Beginner + Free membership verified by hand: all 14 matched entries (guam-cbas, malama-hawaii, menominee-nation-aquaponics, nanning-youth-3d-printing, openstax-additive-manufacturing-essentials, parametric-net-pot-net-cup, printables-hydroponics, prusa-education, purdue-aquaponics-farming-fish, stl-finder, tamu-healthier-living-hydroponics, thingiverse-hydroponics, wikibooks-3d-printing, zhangjiajie-rural-teacher-3d-printing) are genuinely
skill_level: BeginnerANDcost: FreeANDstatus: Activeâ matching the audit's list exactly. - YAML/structure:
_catalog.baseparses cleanly; top-levelfilters+viewslist; all 15 views have validtype(table/cards/list) and unique exactname; every filter expression follows plausible Bases syntax (!=,==,file.hasProperty(),.contains()). - Embed integrity: exactly 15
```baseembeds in_browse.md, each matching a view name character-for-character (em dashes included); no missing or extra views. - Link integrity:
[[Contribute Here]]âmocs/Contribute Here.mdexists;[[Start Here]]âmocs/Start Here.mdexists. - Fixes made during QA: none â no defects found in
_catalog.baseor_browse.md. - Open for human verification: live Obsidian Bases editor rendering; live Flowershow build output.