//! The team page at `/team`, described. //! //! The first described document this server serves to a reader who may or may //! not hold a session, which is the question `b5cbb646` left open and //! [`super::Audience`] answers. It replaces `templates/pages/team.html`, //! `TeamTemplate` and `landing::team_page`. //! //! # Why this is the screen that answers the signed-out question //! //! The gated documents (`/feed`, `/dashboard/export`) resolve a session and //! refuse without one. `/pricing` resolves nothing and takes a state built once //! at startup, which is why it carries no site header: with no per-request //! session there is nobody for a header to greet. //! //! Every remaining `pages/` template is neither. They are public, they carry //! the header, and the header reads differently once a reader signs in -- //! `crate::shell::site_header` puts Library, Dashboard and the cart behind //! `Some(user)`. A screen like that needs a per-request viewer whose user is //! optional, and `/team` is the smallest of them: static content, no writes, no //! reads, so the only thing being proved is the mount. //! //! # One behaviour this changes, and it is a fix //! //! `team_page` resolved its user through `MaybeUserUnverified`, which reads the //! session and short-circuits a legacy one but never validates the tracking row. //! [`super::viewer_factory`] calls `crate::auth::authenticate`, which does: //! a revoked or suspended session renders as signed out here where it would have //! kept rendering as signed in. That is the posture `auth`'s own doc recommends //! ("prefer this anywhere the identity actually gates"), and the cost is one //! cached session touch on a page that made no database call at all before. //! //! # The card is a row, and the bio is a disclosure //! //! `
` is the exact disclosure shape the wiki note //! records (`mnw-server-conversion-plan`, 2026-08-26): a selective region //! showing at most one, holding exactly one labelled sub-region. The near miss //! -- label on the outer slot -- renders as a carousel with Prev/Next buttons //! and compiles fine, so [`the_bio_is_a_disclosure_and_not_a_stepper`] asserts //! the rendering rather than the text. //! //! [`the_bio_is_a_disclosure_and_not_a_stepper`]: tests::the_bio_is_a_disclosure_and_not_a_stepper use makeover_layout as layout; use quasi_declare::declare; use quasi_router::{Document, Request, Response, RouteError}; use quasi_webview::Webview; /// The address, registered whole. See [`super::public_document_mount`]. pub const PATH: &str = "/team"; /// The page's own region, and what the skip link points at. pub const PAGE_REGION: &str = "team"; /// The disclosure that holds the founder's bio. const BIO: &str = "founder-bio"; /// The one labelled frame inside it, which is what makes it a disclosure rather /// than a one-slide carousel. const BIO_BODY: &str = "founder-bio-body"; const MEASURE: layout::Measure = layout::Measure::Wide; /// The page, which reads nothing and so takes no round trip. pub fn screen(_viewer: &super::Viewer, _request: Request) -> Result { Ok(page_screen().into()) } declare! { /// The whole document: the title, the measure, the body. pub(crate) shape page_screen() -> Screen; screen single "Team - Makenotwork" { measured MEASURE; documented Document::default().classed(crate::shell::body_class(MEASURE, &["team-page"])); summarised "Small by design: who builds Makenotwork, and what they did before."; include page_region(); } } declare! { /// The page's one region, split out so it can be staged. /// /// The split is where the request stops mattering, which on this page is /// immediately: nothing below this line reads anything. See /// `policy::page_region` for why the document cannot come with it. #[staged] pub(crate) shape page_region() -> Slot; region PAGE_REGION as Pane { page "Team"; text "Small by design. The base platform was designed by the founder, who intends \ to stay as the technical lead through the project's growth."; section "Founder"; // A row rather than a grid of one: `use-case-grid-2col` held a single // article, so the grid was describing an intention rather than a // layout. When there is a second person the list grows a second row and // the design system decides how two rows sit, which is the arrangement // question answered once for every screen instead of in this page's own // CSS. // // Written here rather than in a `founder()` shape of its own, and that // is a staging constraint rather than a preference. `list [founder()]` // is a bracket list, which is the one place the grammar calls a shape // without an `include`, and the `#[constant]` fold does not reach it: a // bracket also holds plain constructors (`stats [Figure::new(..)]`), so // folding every all-literal call in one would demand a // `Figure::new_constant` that cannot exist. One row is not worth a // production, so it moved. list { row "Max" { secondary "CEO & Tech Lead"; meta "Designed and built the platform."; act "@max" to get "/u/max" navigating; } } include bio(); } } declare! { /// The bio, closed until asked for. /// /// `showing_at_most_one None` is closed; `Some(0)` would be `
`. /// /// `#[constant]`: it reads nothing, so a staged `include` of it folds to /// the disclosure's markup instead of opening a scope per request. The /// words are in `content/team.toml` and read at macro time, so the loop is /// unrolled before any AST exists and nothing here survives to a request. #[constant] shape bio() -> Node; region BIO as Group { showing_at_most_one None; region BIO_BODY as Pane { label "Bio"; for part in copy "content/team.toml" as bio { text part.body; } } } } /// The document this screen is drawn in. /// /// The head, the tail and the token meta come off /// [`super::Viewer::document_shell`]. What is added is what every public page on /// this site opens with: the skip link, and the site header, which reads the /// viewer's user through an `Option` because on this mount there may not be one. #[must_use] pub fn renderer(viewer: &super::Viewer) -> Webview { Webview::new().with_shell(viewer.document_shell().with_body_first(format!( "{}{}", crate::shell::skip_link(PAGE_REGION), crate::shell::site_header(viewer.user.as_ref()), ))) } #[cfg(test)] mod tests { use super::*; fn html() -> String { use quasi_axum::Serves as _; Webview::new().screen(&page_screen()) } /// `2790e5c4` for this screen. The template wrote the measure on the body /// and `team-page` on a container div inside it; a described document has no /// container, so both land on the body and the CSS measure moved onto /// `.team-page main` the way `/feed`'s did. Same two classes, one element. #[test] fn the_document_carries_the_classes_the_template_carried() { let screen = page_screen(); assert_eq!( screen.document.body_class.as_deref(), Some("padded-page team-page") ); assert!(html().contains("padded-page team-page"), "{}", html()); } /// The disclosure shape, asserted by what it renders rather than by what it /// says: a label on the outer slot instead of the inner one is a legal /// carousel, so the text is identical and the markup is not. #[test] fn the_bio_is_a_disclosure_and_not_a_stepper() { let html = html(); assert!(html.contains(r#"aria-expanded="false""#), "{html}"); assert!(!html.contains(r#"data-shows="next""#), "{html}"); assert!(html.contains("University of Chicago"), "{html}"); } /// The founder's row says who, what, and where to read more. #[test] fn the_founder_row_links_to_the_profile() { let html = html(); assert!(html.contains("CEO & Tech Lead"), "{html}"); assert!(html.contains(r#"href="/u/max""#), "{html}"); } /// The bio the content file holds is the bio on the page. /// /// Reads `content/team.toml` rather than holding a second copy of the /// prose, for `policy`'s reason: the test asks the content file what the /// page should say, so an edit to the words is an edit and not a failure, /// and words that stop being rendered are. #[test] fn the_bio_is_the_prose_the_content_file_holds() { let copy: toml::Table = include_str!("../../content/team.toml") .parse() .expect("the team copy is TOML"); let bio = copy["bio"].as_array().expect("a list of one bio"); assert_eq!(bio.len(), 1, "the page shows one founder"); let body = bio[0]["body"].as_str().expect("a body"); assert!( html().contains(&crate::helpers::escape_html(body)), "{body}" ); } /// `736f45a5`: this screen's markup carries none of the four spellings. #[test] fn the_page_spells_no_spinner() { let html = html(); for spelling in ["htmx-indicator", "spinner", "loading-text", "loading-state"] { assert!(!html.contains(spelling), "{spelling} survives in {html}"); } } }