Files
2026-09-02 18:16:44 +00:00

2.8 KiB

AGENTS.md

Iframe Leptos CSR aka "Mont Fort App" craft. Data from generated Matterhorn *Api. Theme is mountainridge. You implement pages. You do not own codegen, hosting, or the toolchain.

Use the injected workspace tools for git, check, build, issues, and Matterhorn deps. Do not shell out to git / cargo / npm / trunk. Commit only if asked (feat: / fix: / docs: / refactor:).

Frozen

src/codegen/**, schemas/, read_app_config, index.html config script + <base> + asset copy-dir, Router base, data-theme="mountainridge", src/styles.css theme block, Cargo.toml.

Missing entity → Matterhorn-search tool → Matterhorn-dep tool, then generate. Still missing → issue, stop. New crate or new CSS tokens → stop. Field not on the struct → migration, not a UI hack.

Layout

src/main.rs         mount
src/app.rs          App + Shell + routes + nav     ← register here
src/context.rs      AppCtx
src/components/     pages + PageHeader, EmptyView, ErrorView
src/codegen/        read-only types + *Api
let ctx = expect_context::<AppCtx>();
let api = ThingApi::new(ctx.matterhorn_config.clone());

Pages never read window.__embeddedAppConfig. Config failure is handled in App.

Page

src/components/<entity>_list.rs → export in mod.rs → one relative <Route> and one href="./…" <A> in src/app.rs. Do not touch main.rs.

Flat siblings under /. Nest a ParentRoute only for a second <Outlet/>. path!("features"), never path!("/features").

let data = LocalResource::new(move || {
    let api = api.clone();
    async move { api.fetch_thing(vec![], vec![], HashMap::new(), 50, 0).await }
});

view! {
    <PageHeader title="Things" subtitle="From Matterhorn."/>
    {move || Suspend::new(async move {
        match data.await {
            Ok(rows) if rows.is_empty() => view! { <EmptyView title="No records" message="Nothing was returned."/> }.into_any(),
            Ok(rows) => view! { /* Option<T> fields only */ }.into_any(),
            Err(err) => view! { <ErrorView title="Could not load records" message=err.to_string()/> }.into_any(),
        }
    })}
}

Do not add <Suspense>. Do not call .get() on the resource. store_* / forms only if the user asked. Projections = schema names (createdAt, not created_at).

view! text is quoted. leptos::prelude::*, not use leptos::*. <A> takes attr:class (or {..} class). Brand/nav is not a .btn.

UI

DaisyUI on mountainridge: card, table, badge, menu. Real .btn for submit/delete only. No tailwind.config.*. No page CSS. Scroll, if needed, is min-h-0 flex-1 overflow-y-auto on the page body — not h-dvh, not html overflow.

Done

check + build clean. Diff = new page + mod.rs + app.rs. Theme, styles, codegen, Cargo untouched.