1. 1. Content Management
When an authorised content editor navigates to the /admin path of the NATO CEDI website, the system shall present the Payload CMS v3 administration interface, allowing the editor to create, edit, publish, and delete content across all defined collections without requiring developer intervention.
When an editor creates or edits a page in Payload CMS, the system shall provide a block-based page builder offering at minimum the following block types: Hero, Rich Text, Call to Action, Image with Caption, Cards Grid, and Embed. Blocks shall be reorderable via drag-and-drop within the admin interface.
All content items (pages, news articles, events, media) shall support three lifecycle states: Draft, Published, and Archived. Only items in the Published state shall be visible to unauthenticated public visitors. Transitioning between states shall be recorded with a UTC timestamp and the identity of the actor performing the transition.
When an editor sets a future publish date on a content item, the system shall automatically transition that item from Draft to Published at the specified UTC time without requiring manual action at the time of publication.
All user-facing text fields in Payload CMS collections shall be defined with the localisation option enabled so that future language variants can be added without schema migration. The default and only active locale at launch shall be English (en).
2. 2. News & Blog
When an editor creates a news article in the CMS, the system shall capture the following required fields: title, slug (auto-generated from title, editable), author name, publication date, cover image, body (rich text), summary (plain text, max 300 characters), and one or more tags. The article shall not be publicly visible until its lifecycle state is set to Published.
The website shall provide a /news listing page that displays all Published news articles in reverse chronological order, showing for each article the cover image, title, summary, publication date, and tag list. The listing shall paginate at 12 articles per page and provide previous/next navigation.
The news listing page shall provide a tag filter control that, when a visitor selects one or more tags, updates the listing to display only articles that carry all selected tags. The active filter state shall be reflected in the URL query parameters to allow sharing of filtered views.
Each published news article shall be accessible at a canonical URL of the form /news/[slug]. The page shall display the article title, author name, publication date, cover image, full rich text body, and tag list. The page shall include structured data (Schema.org NewsArticle) in JSON-LD format for search engine indexing.
3. 3. Events
When an editor creates an event in the CMS, the system shall capture the following fields: title, slug, event type (Conference, Workshop, Hackathon, Webinar, Exercise — single choice), start date-time (UTC), end date-time (UTC), location (venue name and/or online meeting link), cover image, description (rich text), and an optional external registration URL.
The website shall provide an /events listing page that displays all Published events sorted by start date ascending (upcoming first). Past events shall appear in a separate "Past Events" section sorted by start date descending. Each card shall show the event title, type badge, start date, location summary, and cover image.
The events listing page shall provide filter controls for event type and date range. When a visitor applies filters, the listing shall update to show only events matching all active filter criteria. Filter state shall be reflected in URL query parameters.
Each published event shall be accessible at /events/[slug]. The page shall display the full event description, date/time (formatted in the visitor's local timezone), location, and, when an external registration URL is present, a clearly labelled "Register" call-to-action button that opens the external URL in a new tab. The page shall include Schema.org Event structured data in JSON-LD format.
4. 4. Media Library
The Payload CMS media library shall accept uploads of the following file types: PDF (research papers, reports) and MP4/MOV (video recordings). Accepted file size limits shall be 50 MB for PDFs and 2 GB for video files. The system shall reject uploads that exceed these limits with a descriptive error message.
When an editor uploads a media item, the system shall prompt for and store the following metadata fields: title (required), authors (repeating text field, at least one required), abstract (rich text, required for PDFs, optional for video), media type (Research Paper, Report, Video Recording, Presentation — single choice, required), and published date (required). All metadata shall be editable after upload.
The website shall provide a /media listing page displaying all Published media items. The page shall offer filter controls for media type and year of publication. Each listing card shall show the title, type badge, authors, published date, and a download or external link button. Results shall be sortable by published date (newest first by default) and by title (A–Z).
For media items stored as file uploads, the media detail page shall provide a direct download link using the Content-Disposition: attachment header. For media items with an external URL (e.g. a journal article behind a publisher's DOI), the system shall display an "Access via publisher" link that opens in a new tab. Both link types shall be mutually exclusive per media record.
5. 5. Hackathon Hub
The website shall support multiple hackathon editions, each accessible at /hackathon/[edition-slug]. Each landing page shall display the hackathon name, edition year, dates, theme, description (rich text), key dates timeline, sponsors section, and links to the active registration, call for speakers, and project submission forms. The active forms shall be driven by CMS-controlled open/closed flags per form type per edition.
When the participant registration form is open for a hackathon edition, the website shall present a form collecting: full name (required), email address (required, validated), organisation (required), and role (required, free text). On submission the system shall store the response in the PostgreSQL database and send a confirmation email to the provided address. The form shall display a success message on completion and shall not require account creation.
When the call for speakers form is open for a hackathon edition, the website shall present a form collecting: speaker full name (required), email address (required, validated), proposed talk title (required, max 150 characters), abstract (required, min 100 characters, max 1000 characters), and short bio (required, max 500 characters). On submission the system shall store the response and send a confirmation email. Duplicate submissions from the same email address for the same edition shall be rejected with a descriptive error message.
When the project submission form is open for a hackathon edition, the website shall present a form collecting: team name (required), contact email (required, validated), project title (required, max 100 characters), project description (required, min 150 characters, max 2000 characters), repository URL (optional, must be a valid HTTPS URL when provided), and demo URL (optional, must be a valid HTTPS URL when provided). On submission the system shall store the response and send a confirmation email. The form shall enforce a one-submission-per-email-per-edition policy.
Each of the three hackathon forms (participant registration, call for speakers, project submission) shall have an independently configurable open/closed state managed in Payload CMS per hackathon edition. When a form is closed, the website shall display an informational message in place of the form, stating whether registration is not yet open or has closed, and shall not accept any new submissions.
After a hackathon edition concludes, the website shall display a results showcase section on the edition landing page listing all participating projects ranked by their final placement. Each entry shall show the team name, project title, project description summary, and any award badges (e.g. "1st Place", "Best Innovation", "Audience Choice"). Award badges shall be configurable in Payload CMS per project entry.
6. 6. Non-Functional Requirements
All public-facing pages of the NATO CEDI website shall achieve a Largest Contentful Paint (LCP) of 2.5 seconds or less when measured on a simulated mid-range mobile device (Moto G4 equivalent) with a Slow 4G network profile in Google Lighthouse. This target shall be validated in the CI pipeline on every production build.
All public-facing pages shall achieve a Cumulative Layout Shift (CLS) score of 0.1 or less and an Interaction to Next Paint (INP) of 200 milliseconds or less, as measured by Google Lighthouse on the same simulated device profile defined in WD-NFR-001.
All public-facing pages and interactive components of the NATO CEDI website shall conform to WCAG 2.1 Level AA success criteria. This includes but is not limited to: sufficient colour contrast ratios (4.5:1 for normal text, 3:1 for large text), keyboard navigability of all interactive elements, visible focus indicators, descriptive alt text on all non-decorative images, and ARIA roles on all custom interactive widgets.
The CI pipeline shall run an automated accessibility audit using axe-core (or equivalent) on a representative set of rendered pages on every pull request. Any WCAG 2.1 AA violation classified as "critical" or "serious" by axe-core shall cause the pipeline to fail and block merge.
Every public-facing page shall render a unique <title> element (max 60 characters), a <meta name="description"> element (max 160 characters), and canonical <link rel="canonical"> element. CMS-managed content pages (news articles, events, media items) shall derive these values from the item's title, summary/abstract, and slug fields. Default fallback values shall be defined for pages without CMS-authored metadata.
Every public-facing page shall render OpenGraph meta tags (og:title, og:description, og:image, og:url, og:type) and Twitter Card meta tags (twitter:card, twitter:title, twitter:description, twitter:image). CMS-managed content shall use the cover image as the og:image value. Pages without a specific cover image shall use a designated NATO CEDI default OpenGraph image.
The website shall automatically generate a sitemap.xml at /sitemap.xml listing all public Published pages, news articles, events, and media items with their canonical URLs and last-modified dates. A robots.txt file at /robots.txt shall allow indexing of all public pages and shall disallow indexing of /admin and any other non-public paths. Both files shall be regenerated on every production deployment.
The website repository shall not contain any secret values (API keys, database connection strings, JWT secrets, email provider credentials) in source-controlled files. All secrets shall be managed via environment variables injected at build and runtime. A .gitignore rule and a pre-commit hook (e.g. git-secrets or trufflehog) shall be configured to block accidental commit of .env files or known secret patterns.
The Next.js application shall serve a Content-Security-Policy HTTP response header on all pages that restricts script execution to known first-party origins and explicitly approved third-party CDNs. The policy shall include default-src 'self', shall disallow inline event handlers (no unsafe-inline for script-src except for Next.js nonce-based inline scripts), and shall be reviewed and updated as part of any dependency change that introduces new external script sources.
All form submission endpoints (participant registration, call for speakers, project submission) shall validate a CSRF token tied to the user's session before processing any submitted data. The Next.js server actions or API routes handling form submissions shall reject requests that do not carry a valid token with a 403 Forbidden response. The token shall be rotated on each new page session.
All public-facing pages shall apply the NATO CEDI design token set defined in libs/design-system, using only the semantic Tailwind CSS tokens (bg-background, text-foreground, bg-primary, etc.) and NATO-specific colour variables from styles.css. Hardcoded hex colour values shall not appear in any component source file. The site shall support the theme-light, theme-dark, and theme-nato CSS class variants defined in the monorepo design system.
All public-facing content pages (news articles, event detail pages, media items) shall be rendered using Next.js Static Site Generation (generateStaticParams) at build time. The site shall support Incremental Static Regeneration (ISR) with a revalidation interval of no more than 60 seconds so that newly published CMS content is reflected on the live site within one minute of publication without a full rebuild.