Developer Page Specifications
Editorial Landing
/:lang/editorial — 8-section structure: hero · latest · industries · most-read · topics · desk · coverage · newsletter.
Complete
Route: /:lang/editorial. The premium curated editorial home — featured spotlight + latest feed + categories grid + topic chips + most-read sidebar + newsletter capture. Built for browsing, not for traffic — every editorial decision (featured choices, most-read ranking, category emphasis) is staff-curated, not algorithmic.
Page sections (top → bottom)
- A · Hero (eyebrow "Editorial Intelligence" + H1 + lede + 2 CTAs)
- B · Featured spotlight (1 large + 2 supporting cards)
- C · Latest feed (8-12 articles, mixed card densities)
- D · Categories grid (9 category tiles with article counts)
- E · Topics chips row (free taxonomy, click → topic page)
- F · Most-read sidebar (top 5 by view count)
- G · Newsletter block (Editorial digest subscribe)
- H · Footer (global)
A · Hero fields
- Eyebrow
- Source: PageConfig.editorialListing.eyebrow. Default: "Editorial Intelligence". Mono uppercase tracking-wider. Brand-orange accent dot prefix.
- H1 title
- Source: PageConfig.editorialListing.title. Default: "Analysis, stories, and founder-focused perspectives." Required: yes. Only H1 on the page.
- Lede paragraph
- Source: PageConfig.editorialListing.description. 1-2 sentences. Bilingual.
- Primary CTA
- Label: "Read latest insights". Action: smooth-scroll to #latest-feed.
- Secondary CTA
- Label: "Submit a story". Action: routerLink to /:lang/submit/story (a pitch form, NOT a publish form — see §10.1 admin doctrine).
B · Featured spotlight
- Main featured card (large)
- Source: 1 article where IsFeatured=true ORDER BY publishedAt DESC LIMIT 1. Hero treatment: 16:9 cover + type chip + topic chip + title H2 + dek + author byline + reading-time pill. Full-width on desktop, full-bleed on mobile.
- Supporting featured cards (2 medium)
- Source: next 2 articles where IsFeatured=true (offset 1, limit 2). Medium card variant: 16:9 cover + type chip + title H3 + author byline.
- No-featured state
- When fewer than 3 IsFeatured=true articles exist, fall back to the 3 most recent IsActive articles regardless of featured flag. Section never renders empty.
C · Latest feed
- Source: ORDER BY publishedAt DESC, excluding the 3 already shown in B. Default 12 cards. Pagination via infinite scroll.
- Card mix: 3-col grid desktop / 2-col tablet / 1-col mobile. Each card uses canonical <app-editorial-card>.
- Card fields: cover (or SVG fallback), type chip, topic chip, title H3, dek (2-line clamp), author byline (name + role), publish date + reading time.
- Empty state: when 0 articles AND filters active, show "No editorial signals match these filters. Clear filters to see the full feed." With "Clear filters" CTA.
D + E · Categories + Topics
- Categories grid (D)
- Source: SELECT * FROM EditorialCategory WHERE IsActive=true ORDER BY DisplayOrder. 3-col desktop tiles. Each tile: category icon + name + 1-line description + article count + latest article preview + CTA "Browse {category}".
- Topics chips row (E)
- Source: SELECT * FROM EditorialTopic ORDER BY ArticleCount DESC LIMIT 20. Display: horizontal scroll-snap row of chip buttons (no max-width clipping). Click → /:lang/editorial/topics/{topicSlug}.
F · Most-read sidebar
- Source: SELECT * FROM EditorialArticle WHERE IsActive=true ORDER BY ViewCount DESC LIMIT 5.
- Display: ranked list with mono ranking number (01, 02, ...) + title (2-line clamp) + category chip + reading time. NO author/date — visual density priority.
- Sticky on desktop (right column when grid is 2-col with feed left), inline below feed on mobile.
G · Newsletter block
- Same component as Opportunity Radar subscribe block, context-aware: source='editorial', preselects "Editorial signals" interest tag.
- Fields: email (required), preferred language, interest categories (multi-select from EditorialCategory.Slug), consent checkbox (required true), partner-consent checkbox (optional).
UI states
- Loading: skeleton cards in feed + skeleton tiles in categories.
- Empty (filters → 0): documented empty state with "Clear filters" CTA.
- Error (API fail): toast + retry inline. Cards area keeps loaded data.
