Skip to content

8. Batch G — Public pages (PublicLayout / PublicDetailLayout)

All public pages drop their hand-built headers for the shared PublicShell (PLAN §3.4): space brand left; nav (Catalogue, Machines, Events, Bookings, Stats, as enabled); “Sign in” right; theme toggle and the “space works” credit in the footer. The “Staff login” buttons in public headers go away (staff use /admin; keep a footer link “Staff sign-in”).

G1. Landing directory (central mode) — /

Section titled “G1. Landing directory (central mode) — /”
  • Component features/LandingPage.tsx. Reference: org1 (cards), att1 hero tone.
  • Layout: PublicLayout (deployment-level PublicShell: Space Works logo, “About”, “Sign in”).
    • hero: eyebrow “Space Works” · one Unbounded accent line “Find a space. Borrow the tool.” · intro “Public catalogues from community workshops, labs and makerspaces.” · big search field “Search by name, code or place” + result count.
    • content: space cards (cover image, colour not greyscale; avatar tile; name; location link; code; “Open catalogue →”; whole card clickable).
    • The left aside with “Public spaces / Live / Status access” tiles is removed (it duplicated the count and “Live” was not data).
  • States: loading: skeleton cards · empty: “No public spaces yet. They appear here once a space turns on its catalogue.” · no match: “No spaces match ‘{q}’.” + “Clear search” · error: “Couldn’t load spaces. Try again.”
  • Component features/AboutPage.tsx. Layout: PublicLayout, narrow reading column.
    • hero: eyebrow “About” · title “Open-source makerspace management” · 2 short paragraphs (existing copy, tightened) · licence line.
    • content: two link cards “Browse spaces →” and “Staff sign-in →” (org1 card style).

G3. Public machines — /machines, /m/:slug/machines

Section titled “G3. Public machines — /machines, /m/:slug/machines”
  • Component inventory/PublicMachinesPage.tsx (+ MachineIntakeForm). Reference: org2 list → card grid, att1 tone.
  • Layout: PublicLayout.
    • hero: eyebrow “Machines” · title “What you can use at {space}” · intro.
    • toolbar: kind chips (one per group, replacing collapsible sections) + “Training required” filter chip.
    • content: card grid. Card = image (or icon tile) · name · status pill (Available / In use / Down) · meta “{h} h logged” · “Training required” pill · queue line “3 jobs queued · about 2 h”. Primary on the card: “Request a job” when structured intake is on (opens MachineIntakeForm in a dialog, not inline in the card).
  • States: “No machines listed yet.” · not enabled: “Machines aren’t public at {space}.” · throttled: “You’re going a bit fast. Wait a moment and try again.” · not found: F6-style public card.

G4. Public bookings — /bookings, /m/:slug/bookings

Section titled “G4. Public bookings — /bookings, /m/:slug/bookings”
  • Component bookings/PublicBookingsPage.tsx, PublicBookingForm.tsx, SpaceDiscoveryCalendar.tsx, discovery/*. Reference: att1 (detail + sticky action card).
  • Layout: PublicLayout (list of spaces) → selecting a space opens PublicDetailLayout in place (?space={token}, no new route).
    • List: hero “Book a space at {space}” · toolbar = DiscoveryControls (search, kind chips, list/calendar toggle) · cards (image, name, location, kind pill, Capacity, “Instant” vs “Needs approval” pill, “Choose a time”).
    • Detail: hero image + name + kind + location · main description, availability calendar, rules · aside sticky booking card (date/time pickers, PublicBookingForm fields, primary “Request booking” or “Book now” per approval mode, helper “Staff confirm requests within a day” / “Confirmed instantly if free”).
    • Header nav “My bookings” → member Bookings tab (H2).
  • States: “No bookable spaces yet.” · “No spaces match these filters.” · not enabled / throttled as G3.

G5. Public events list — /events, /m/:slug/events (only if ux-spec.md leaves it out)

Section titled “G5. Public events list — /events, /m/:slug/events (only if ux-spec.md leaves it out)”
  • Component inventory/PublicEventsPage.tsx. Reference: org2 rows from the attendee side.
  • Layout: PublicLayout: hero “What’s on at {space}” · toolbar discovery controls (list / calendar) · date-chip rows (title, time · place, price, availability pill “6 spots left” / “Waitlist”) → event page (core).
  • States: “No upcoming events. Check back soon.”

G6. Print request — /print, /m/:slug/print

Section titled “G6. Print request — /print, /m/:slug/print”
  • Component printing/PublicPrintRequestPage.tsx, PublicPrintRequestForm.tsx, PublicPrintRequestParts.tsx (StatusResult stepper), PublicPrintRequestPanels.tsx.
  • Job: send a 3D-print job with files, then track it.
  • Reference: att1 (main + sticky card), att9 (confirmation).
  • Layout: PublicDetailLayout.
    • hero: eyebrow “3D printing” · title “Send a print job to {space}”.
    • main: the form in three titled groups. Your print (Title, Project brief) · Material (filament pool select grouped by material, or Material + Colour, Quantity, Estimated grams) · Files (model files drop zone, print-time screenshots drop zone, Source link). Submit at the bottom: “Send print request”.
    • aside sticky: “Track your job” card. Before submit: “After you send it, you’ll get a link to follow progress here.” After submit / with ?token=: the status stepper (Requested → Accepted → Printing → Ready to collect → Collected) with the current step highlighted, plus “Copy tracking link”.
    • On success the page scrolls to the aside, and a success callout “Request sent. We’ll update this page as it moves.” replaces the form.
  • States: loading service: skeleton · unavailable: “3D printing isn’t open for requests right now.” + the tracker if a token exists + “Back to catalogue” · load error: “Couldn’t reach the print service. Try again in a moment.” · upload progress: inline “Uploading 2 of 3 files…”.

G7. Public stats — /stats, /m/:slug/stats

Section titled “G7. Public stats — /stats, /m/:slug/stats”
  • Component stats/PublicStatsPage.tsx, StatsSections.tsx, StatsParts.tsx. Reference: org2 stat cards.
  • Layout: PublicLayout with a DashboardLayout-style body: hero eyebrow “Live stats” · title “{space} in numbers” · “Updated live from the public catalogue.” · sections Printing (stat cards: busiest printer, queue; bar chart by brand; filament trend; per-printer table) · Lending (most popular, tools out, recently added as cards) · Out right now (current loans list, no personal data beyond what the API already returns).
  • States: off/missing: “Stats aren’t public for this space.” · empty: “Nothing to show yet. Stats fill in as people borrow and print.”

G8. Public organization — /o/:organizationSlug

Section titled “G8. Public organization — /o/:organizationSlug”
  • Component organizations/PublicOrganizationPage.tsx. Reference: org3 preview card → full page; att1.
  • Layout: PublicLayout: hero avatar tile · org name · description · “Visit website ↗” (outline) · content “Upcoming events across spaces”: date-chip rows (title, “{host space} · time · place”, price, availability pill, inline “Register at {host}”). This replaces large image cards; images become a small thumbnail.
  • States: “This organization doesn’t have a public page.” · “No upcoming events.” · events error with Try again.

G9. Event feedback — /events/:token/feedback

Section titled “G9. Event feedback — /events/:token/feedback”
  • Component inventory/PublicEventFeedbackPage.tsx (+ forms/CustomFormFields). Reference: auth3 (centred, focused), att9.
  • Layout: PublicLayout, narrow single column (form) → CenteredCardLayout for the end states.
    • hero: eyebrow = event title · title = survey title · helper: anonymous “We don’t store who sent this.” / certificate “Certificates go to people marked as attended.”
    • Needs sign-in: info callout “Sign in to get your certificate.” → “Sign in”.
    • Form card + primary “Send feedback”.
    • Thank you card: check tile · “Thank you” · server thank-you text · certificate download button if one is returned.
    • Unavailable card: “Feedback is closed for this event.”

G10. Self-checkout — /checkout, /m/:slug/checkout

Section titled “G10. Self-checkout — /checkout, /m/:slug/checkout”
  • Component inventory/PublicSelfCheckoutPage.tsx, PublicEvidenceUpload.tsx, PublicToolScanPanel.tsx, PublicToolResultCard.tsx, KitChecklist.
  • Job: on a phone at the shelf: borrow or return a QR-tagged tool with photo proof.
  • Reference: att11 (scan + big result), auth3 (one thing per screen).
  • Layout: PublicLayout (minimal PublicShell), with a FlowLayout body that is mobile-first.
    • Top: segmented control Borrow · Return (replaces “Use (check out)” / “Return” tabs).
    • Borrow steps: 1 Photo (“Take a photo of the tool” camera/upload tile, preview) → 2 Scan (camera frame, “Hold the tool’s QR inside the frame”) → 3 Check the kit (only if it has parts) → 4 Confirm (result card: tool name, due date, “Borrow it”).
    • Return steps: 1 Photo → 2 Condition notes (required) → 3 Scan → 4 Confirm (“Return it”).
    • Done: big success panel (att11 green) “You’ve got it. Due back {date}.” / “Returned. Thanks!”
      • “Borrow another”.
    • Hard rules unchanged: a scan and uploaded evidence stay required. The step order only makes the requirement visible.
  • States: not enabled: “Self-checkout isn’t on at {space}.” + “Back to catalogue” · scan/loan error: inline danger callout on the Confirm step with the server message.

G11. Archived payments — /member/archived

Section titled “G11. Archived payments — /member/archived”
  • Component members/ArchivedPayments.tsx. Reference: auth6 calm list.
  • Layout: PublicLayout (deployment-level shell) narrow column: hero eyebrow “Closed spaces” · “Payments and receipts” · per-space sections (space name header, charge rows with amount + status pill
    • receipt download).
  • States: “No archived payments. Nothing is owed to spaces that have closed.” · not signed in / not found → F6.