← Corpus / astro-knots / other
Team Pages Specification
Agency-wide specification defining how astro-knots sites should implement data-driven team pages with role-based grouping, shared data models, and brand theming.
- Path
- sitemap/pages/team/Team-Pages-Specification.md
- Authors
- Michael Staton
- Tags
- Team-Pages · Components · Data-Model · Responsive-Design
Team Pages – Agency-Wide Specification
Overview
This specification defines how astro-knots sites should implement team pages for all client projects. It generalizes the “team spans” pattern used in hypernova-site and twf_site into a reusable, data-driven design that:
- Groups people by role into visually distinct spans (role header + cards)
- Uses a shared data model for people (
TeamMember) and roles (TeamRole) - Keeps layout and styling consistent across clients while allowing brand theming
- Supports editorial flexibility (featured members, multiple classifiers, re-ordering)
- Ensures accessibility and responsiveness across devices
This spec covers:
- Content model and data source
- Role classification and grouping
- Page layout and spans
- Person card design
- Theming and customization per client
- Performance and accessibility requirements
Content Model
TeamMember Type
All team pages must use a common TeamMember shape, compatible with the existing team.ts definitions used in hypernova-site and twf_site.
Minimum fields:
- name:
string– person’s full name - role:
string– short label describing their role/title as shown to users - classifiers:
string | string[]– tags used to group members into spans - image:
string– URL/path to profile image - bio:
string– short biography or description - socialLinks:
Array<{ name: string; href: string; icon?: string }>– optional, can be empty
Optional fields:
- id:
string– internal identifier - featured:
boolean– can be used to highlight someone visually - slug:
string– used for anchors or dedicated profile pages (future)
Implementation guidance:
- For JSON-backed content (as in
hypernova-siteandtwf_site), store team insrc/content/people/team.jsonor a similarly named file. - For MDX/content collections, ensure frontmatter maps cleanly into the
TeamMembershape.
TeamRole and Role Labels
Define a TeamRole union and a mapping from classifier strings to display labels, similar to TEAM_ROLES in twf_site:
- TeamRole: a finite set of role classifier values (e.g.
"Managing Partner","Trustee") - TEAM_ROLES:
Record<TeamRole, string>mapping classifier → pluralized display label (e.g."Managing Partner" → "Managing Partners")
Agencies should:
- Keep
TeamRolefocused on semantic groupings that appear as spans on the page (e.g., Managing Partners, Vertical Partners, Trustees, Advisory Board, Founding Team, Active Fellows, Philanthropies). - Allow client-specific extension of
TeamRole, but all roles must flow through the same classification + grouping pipeline.
Classifiers Usage
classifiersmay be a string or array of strings.- A mapping function (see below) interprets classifiers and assigns each member to exactly one primary span for display on the main team page.
- Derived/secondary roles (e.g.,
"Founding Trustee","Founding Advisor","Founding Principal") should map to a base span (Trustees,Advisory Board,Founding Team).
Grouping Logic
Each team page must:
- Read the full list of
TeamMemberobjects - Group them into role-based spans using a deterministic, reusable
groupByRolehelper
groupByRole Helper
Required characteristics:
- Accepts
TeamMember[] - Returns an object keyed by span identifiers (e.g.
managingPartners,verticalPartners,trustees, etc.) - Handles
classifiersas string or string[] - Uses a
classifierMapfrom classifier text to span key - For each member:
- Finds the first matching classifier in the map
- Assigns the member to the corresponding span array
- Ignores members without recognized classifiers (or optionally collects them into an
otherspan)
Agency guidance:
- Place
groupByRolein a shared utility module (e.g.src/lib/team/groupByRole.ts) so multiple pages/layouts can reuse it. - Make the classifier map configurable per client (e.g. via a local config file) but keep the algorithm consistent.
Page Layout and Spans
High-Level Structure
Team pages should follow a consistent layout pattern:
- Route:
/teamor/the-people(client-specific but consistent within site) - Layout: a
TeamLayoutthat wraps the page with:- Base theme layout (navigation, footer, background, etc.)
- A main content container with a responsive grid for spans
Example high-level Astro structure:
<BaseThemeLayout>
<BaseGridLayout>
<!-- Role spans inserted here -->
<ManagingPartnersSpan members={groupedTeamData.managingPartners} />
<VerticalPartnersSpan members={groupedTeamData.verticalPartners} />
<!-- Other spans... -->
</BaseGridLayout>
</BaseThemeLayout>
TeamLayout Component
Implement a TeamLayout.astro per site that:
- Sets page
<title>and<meta>description - Provides a max-width container for the content
- Uses a responsive grid for child spans, e.g.:
- 1 column on mobile
- 2 columns on small screens
- 3 columns (or more) on large screens
- Slots in the span components.
This layout must be brand-themable but structurally consistent:
- Grid gap, padding, and breakpoints are standardized in a base design system or Tailwind config.
- Individual spans do not manage their own outer layout; they rely on the grid provided by
TeamLayout/BaseGridLayout.
Span Components
For each top-level role group, define a span component in src/components/team/, e.g.:
ManagingPartnersSpan.astroVerticalPartnersSpan.astroTrusteesSpan.astroAdvisoryBoardSpan.astroFoundingTeamSpan.astroActiveFellowsSpan.astroPhilanthropiesSpan.astro
Each span component must:
- Accept
members: TeamMember[]via props - Render a role header (
<h1>or<h2>withrole-headerclass) - Render its children using
PersonCardcomponents inside a.person-cardscontainer - Import and rely on shared
team-spans.css(or equivalent) for span styling
Span structure should be semantically valid and consistent across sites (prefer <div class="team-span"> over nested <span>s for block content).
Span Layout Behavior
- Contiguous spans: Each span keeps all of its
PersonCardchildren grouped under its role header. - Flow: Spans flow left-to-right, top-to-bottom according to the grid layout.
- Responsive: Span width adapts to available columns; they should not hard-code column spans unless a specific design calls for a hero member.
- No awkward gaps: Use grid or flex patterns that minimize white space while preserving grouping.
Person Card Design
Component: PersonCard.astro
A shared PersonCard component must be used across spans. It should:
- Accept
PersonPropsmatching theTeamMemberfields (plus presentation options)name,role,image,bio,socialLinks?, and optional layout props likeclass/className,maxWords,showBio.
- Render:
- An image (square or aspect-ratio constrained, lazy-loaded)
- Name and role text
- A truncated bio (with a
Read moreaffordance if truncated) - Optional social icons row when social links are present
Visual requirements:
- Cards should have a consistent visual language across clients (rounded corners, shadow, hover state), with color tokens pulled from the site theme.
- Cards must be height-managed to avoid extreme vertical stretching; bios are truncated with sensible defaults and line clamping where supported.
Accessibility requirements:
alttext for images in the form:"Portrait of {name}"or similar.- Semantic heading levels (
<h3>inside the card), not skipping heading hierarchy on the page. - Focusable controls for “Read more” with appropriate aria attributes if content expands/collapses.
Shared Styles and Theming
team-spans.css (or Equivalent)
Maintain a shared stylesheet for span-level styles, similar to the existing team-spans.css:
-
.team-span- Full-width block container
break-inside: avoidto prevent spans from splitting across columns or page breaks- Consistent bottom margin
-
.role-header- Prominent typography (size, weight) with optional gradient or brand color
- Margin and padding tuned for readability
- Can include decorative underline or accent line
-
.person-cards- Uses
display: contentsor a simple grid/flex container to let the outer layout handle card placement.
- Uses
Brand Customization
Per client/site, allow customization of:
- Color tokens (typography, gradients, borders)
- Spacing scale (within design system bounds)
- Optional hero treatment for a featured member (e.g., first card spans two columns)
These customizations should be controlled via:
- Theme variables (CSS custom properties, Tailwind config) rather than per-component overrides.
Data and Editorial Workflows
Adding or Editing Team Members
- Editors update a single source of truth (e.g.
team.jsonor a CMS collection) using theTeamMembershape. - Role assignment is handled primarily through
classifiers(not by hardcoding lists in span components). - Team pages automatically reflect updates on the next deploy/build.
Reordering Spans and Members
- The order of spans on the page should be configurable (e.g. managing partners first, then vertical partners, etc.).
- Implement via a
SPAN_ORDERconfig array or similar.
- Implement via a
- Within a span, default ordering is by input order or by a defined sort key (e.g.
featuredfirst, then alphabetical by name).
Future-Proofing
- Keep
TeamMemberextensible so new fields (locations, pronouns, focus areas) can be added without breaking existing spans. - Support optional deep-linking to individuals (e.g.
/team/{slug}) in a later iteration without changing the core page structure.
Performance
- Use
loading="lazy"for all images on the team page. - Serve appropriately sized images (e.g. via
srcsetor a media pipeline) to avoid oversized downloads on mobile. - Minimize layout shift by specifying
widthandheight(or aspect ratio) on images. - Avoid heavy client-side JavaScript; interactivity should be progressive (e.g.
Read moretoggles only where needed).
Accessibility
- Ensure proper heading hierarchy from page title down through role headers and card headings.
- Maintain sufficient color contrast for text and important UI elements.
- Make any interactive elements (e.g.
Read morebuttons) keyboard accessible and screen-reader friendly. - Do not rely solely on color to convey hierarchy; use typographic scale and spacing.
Acceptance Criteria (Agency Checklist)
-
Data Model
-
TeamMembertype implemented and used as the single source of truth -
TeamRoleand classifier → span mapping defined per client
-
-
Grouping & Layout
-
groupByRole(or equivalent) used to group members into spans - Team page renders all configured spans in the intended order
- Each member appears in exactly one primary span on the main team page
-
-
Visual & UX
- Spans show a clear role header and associated cards
- Layout is responsive across mobile, tablet, and desktop
- Person cards are visually consistent and do not become unreasonably large/tall
-
Theming
- Span and card styles respect the client’s brand theme
- Shared CSS (e.g.
team-spans.css) or design system tokens are used
-
Performance & Accessibility
- Images are lazy-loaded and sized appropriately
- Page passes basic accessibility checks (headings, alt text, contrast, keyboard nav)
This specification should be used as the default blueprint for all new client team pages, with client-specific role taxonomies and theming layered on top without changing the underlying structure or data model.