Phones report a viewport taller than the area they actually paint, so
centring in the full 760px hero left a visibly bigger gap above the copy
than below it — on the reported preview roughly 110px above against 56px
below.
Cap the mobile centring box at 700px. Viewports shorter than that are
unaffected and stay exactly centred; taller ones now sit 30px higher.
The hero is a fixed 760px, which is taller than most phone viewports, so
copy centred within the section still sat low on screen — on a 690px
viewport there was 114px above the block and only 36px below it.
Below `lg`, centre the copy in min(100svh, 760px) instead, floored at
560px so a landscape phone cannot clip it. From `lg` up nothing changes:
the same absolute offsets as the homepage, which keeps rendering
byte-identical markup because the new layout is opt-in per page.
Page views, bounce rate and time on site already come from the site-wide
Umami script, and UmamiButtonTracker already fires on every link click —
but it names the event after the element's text. That breaks on a copy
edit, and for the path cards the whole card is the link, so the event name
was the heading, CTA label and body run together.
Give the hero and path-card sections an optional event-name prop and set a
stable name for all seven CTAs. Both props are optional, so the homepage
keeps rendering byte-identical markup.
The centred flex layout spaced the three hero blocks evenly, but the
homepage's offsets are not even (52px above the headline, 78px below), so
the headline landed 22px lower than on the homepage.
Go back to the shared offsets layout on /build-the-parallel. Both pages now
render the hero from the same component with the same absolute positions,
and both overlay their header, so the section starts at page y=0 on each.
The hero placed its three copy blocks at hand-tuned absolute offsets, so
the group drifted a little below the section's centre and the drift moved
with the viewport and the length the copy wrapped to.
Add a `centred` content layout that stacks the same blocks in a flex
column with an even 70px rhythm, centred in the hero, and use it on
/build-the-parallel. The homepage keeps the existing offsets layout and
renders byte-identical markup.
Move the hero and choose-your-path card sections out of sections/home so
pages other than the homepage can compose them, extract the two-line
statement heading, and lift CenterCtaSection out of the Movement page's
private atoms module.
The hero now takes an optional `background` node, defaulting to the same
Logos background video the homepage has always rendered.
Rendered output is unchanged: the homepage's hero, social proof, and
choose-your-path markup and the Movement page body are byte-identical to
develop, and the generated stylesheet loses no rules.
* fix: increase small text to 12px
* fix: use initiative CTA label
* refactor: use Tailwind text-xs utility
* fix: make homepage banner dismissible
* fix: update Discord links and banner text
* fix: refresh Discord invite links
* docs: add page-copy single-source spec and implementation plan
* feat(content): add typed home section schemas and migrate home copy into content
Add 7 bespoke home* section schemas (+ techStack ctas) to the page section
union and populate content/pages/en/home.json with home copy moved verbatim
from messages.
* refactor(web): source home page copy from @repo/content; drop home namespace from messages
Feed every home section from content via findSection/data props (replacing
next-intl getTranslations), remove the home namespace from messages/en.json,
and add a regression guard plus content-based tests. Render output unchanged.
* docs: add get-started/movement page-copy dedup spec and plan
* feat(content): add get-started & movement section schemas and content docs
Move get-started/movement page copy verbatim into content/pages so it is
single-sourced in @repo/content.
* refactor(web): source get-started/movement copy from content; drop those namespaces from messages
Feed both pages from content via findSection/data props (replacing next-intl),
switch them to content-based metadata, delete pages.getStarted/movement from
messages, and add content-based tests + ownership guard. Render unchanged.
* docs: add navbar-pages CMS copy spec and plan
* feat(content): add navbar page section schemas + Pages docs (book, brand-kit, research, node-programme, lambda-prize, manifesto, media, podcast, broadcast, tech-stack explorer)
* refactor(web): source navbar pages copy from content; drop those namespaces from messages
Migrate book, brand-kit, research (incl. rich-text via a tagged-text renderer),
node-programme, lambda-prize, manifesto, media, podcast, logos-broadcast-network,
and the tech-stack explorer to read copy from content via findSection/data props
and content-based metadata; remove the migrated pages.* namespaces from messages;
update guards + contracts. Render output unchanged.
* feat(web): source activist/coalition pages copy from content (CMS title/description)
Migrate activistBuilder, activistLeaderSteward, and coalitionPartner page
metadata from next-intl messages.pages.* into @repo/content PageCopy JSON,
following the established bookCopy pattern.
- Add activistBuilderCopySectionSchema, activistLeaderStewardCopySectionSchema,
coalitionPartnerCopySectionSchema to packages/content/src/schemas/pages.ts
and wire them into the pageSectionSchema discriminated union
- Create content/pages/en/activist-builder.json,
activist-leader-steward.json, coalition-partner.json with verbatim
title/description/heading values from the old messages namespace
- Switch all three route pages from createTranslatedPageMetadata to
createPageMetadata(ROUTE), removing the NAMESPACE constant
- Remove activistBuilder, activistLeaderSteward, coalitionPartner from
apps/web/messages/en.json pages object
- Add schema parse tests, renderToStaticMarkup page tests, messages ownership
guards, and content-route contract entries for all three pages
* chore(web): remove dead faq (pages.faq + unused FaqSection components)
* fix: remove stale faq links
* fix: pass payload env through turbo build
* fix: preserve lambda prize support labels
* fix: preserve live copy after master rebase
* fix: address page copy review feedback
* refactor: move design guide copy to content
* feat: add schemas for home and page copy sections
- Introduced home section schemas including homeSocialProof, homeChoosePath, homeDecide, homeStartBuilding, homeAbout, homeUseCases, and homeBuilderPortal.
- Added page copy section schemas such as getStartedCopy, movementCopy, bookCopy, designGuideCopy, activistBuilderCopy, activistLeaderStewardCopy, coalitionPartnerCopy, researchCopy, nodeProgrammeCopy, lambdaPrizeCopy, mediaCopy, podcastCopy, broadcastCopy, and manifestoCopy.
- Created shared schema for section keys to maintain consistency across sections.
* chore(web): remove dead pages.faq from messages
* fix: resolve page copy migration conflicts
* fix: source connect form page copy from content
* fix: remove duplicated afform page copy exports
* fix: stop generating afform page copy exports
* fix(cms): require only server actions key
* fix(cms): load env files before build validation
* fix(cms): make env loader available during build
* fix(cms): load next env via require
* test(cms): isolate missing env validation
* feat: add homepage testnet highlight
* fix: restore lambda prize support links
Clicking a marker now shows a popup with the soonest upcoming event for
that city (cover image, name, date/time, location) linked to the Luma
event page. Markers with no upcoming event fall back to a placeholder.
- Fetch all upcoming events at build time (EventsSection keeps its 3-item cap)
- Build a city+country lookup in CirclesWorldMap for O(1) event resolution
- Home-page map unaffected (upcomingEvents prop is optional)
Recompress/resize images over 150KB (cap 1920px, webp q80; mozjpeg where webp lost), convert png/jpg to webp where smaller, and update all references. Raster payload drops from ~36MB to ~16MB; ukdebt og image becomes an opaque jpeg for crawler compatibility.
* fix(content): update description for storage overview section
* fix(content): update references from "The Logos Blog" to "Logos Media" across multiple files
* feat: Refactor blog section to media section
- Created new components for articles and podcasts under the media section.
- Updated routing constants to replace blog with media.
- Adjusted all references in the codebase from blog to media, including links, buttons, and navigation.
- Implemented new layout and design for articles and podcasts to enhance user experience.
- Updated translations and content references to align with the new media section.
* feat(about): replace h1 with AnimatedHeading component in AboutHero section
* fix: update import paths for PodcastsSection and adjust LambdaBadge properties in multiple components
* fix: adjust hover translation values for desktop stack items
Move the diagram breakpoint to min-[1367px] (flag renamed desktopAt1367)
and pass it from the shared explorer so detail pages match. Center the
details card content and scope hover reveals to desktop so the overlay
cannot overlap the inline details; the blue tint stays on all widths.
Add a desktopAt1025 flag to TechDetailHero (desktop at lg instead of md)
and drop the phone max-widths at md so hero copy spans the full tablet
width. Enabled on blockchain, networking, and storage heroes.
- Call setRequestLocale(locale) in the docs page factory so next-intl
renders statically instead of bailing to headers(), which broke
output: export on /security, /privacy-policy, /terms-and-conditions,
/testnet-terms-and-conditions and /testnet-v01-faqs.
- Wrap gray-matter in safeMatter() so an RFP with invalid YAML
frontmatter (e.g. RFP-015's unquoted colon in title) falls back to
body-only heuristics instead of being dropped from the listing.
- Added tech-networking-thumb.webp to the nav-overlay/figma directory.
- Added tech-overview-thumb.webp to the nav-overlay/figma directory.
- Added tech-storage-thumb.webp to the nav-overlay/figma directory.
* fix(sitemap): remove FAQ route from static indexable routes
* feat(web): markdown-managed legal pages + Testnet FAQ & Terms
Introduce a markdown-based system for legal/info documents and add the
two testnet pages on the same docs route pattern.
- Add getLegalDoc loader (gray-matter frontmatter + zod validation) and
LegalMarkdown renderer (react-markdown + remark-gfm) mapped to Logos
design tokens; render legal pages as a server component.
- Refactor docs-page-factory to source content from content/legal/<slug>.md
instead of next-intl namespaces; migrate terms, privacy, and security
from messages/en.json to markdown.
- Add /testnet-v01-faqs and /testnet-terms-and-conditions pages with
content mirrored from logos.co; link the FAQ's testnet-terms references
to the internal route.
- Add Testnet FAQ and Testnet Terms to the docs ToC (remove the dead FAQ
entry); register both routes in the sitemap.
- Align docs content to the standard page gutter by removing the
redundant px-3 on the docs page shell.
* chore: optimise page imagery
* feat(web): link Logos Devs X account in community section
* chore(web): hide 'What you can build today' section on get-started and builders-hub
* refactor: reuse builders hub start sections
* feat(builders-hub): source RFPs from GitHub API at build time
Fetch and parse RFPs from the logos-co/rfp repo (markdown + YAML
frontmatter) at build time instead of local content, so the /rfps
listing and [slug] detail pages render from a single live source.
- add rfps-github lib: GitHub contents fetch, gray-matter frontmatter
parse, stable slug from filename, draft/template exclusion
- detail page renders frontmatter-stripped markdown via LegalMarkdown,
with Apply + View on GitHub CTAs
- widen RFP card/row/listing props to RfpListItem so GitHub data
(no reward/image) and local Rfp both satisfy the UI
- add optional markdown body to BuildersHubDetailLayout
* refactor: share get started sections
* feat(node-programme): refactor signup form and implement submission logic
* fix(web): improve layout and styling of feature cards section
* feat(tech-stack): implement tech stack related articles functionality and update blog article fetching logic
- Always render copy before image in DOM; use order + md:contents to
restore the left-image layout on desktop when imagePosition='left'
- Change compact marker height to md:h-[98px] so mobile is not forced
to reserve 98px for the eyebrow marker
- Add copyBodyClassName and actionsClassName props for per-callsite
mobile spacing control
The movement Circles Resources was a hardcoded placeholder. Extract the circles
resources section into a shared CircleResourcesSection and render it on both
pages with the same real resource data and copy.
- Add components/sections/shared/circle-resources-section.tsx (header + whole-row
resource links) — circles resources-section.tsx now delegates to it (output
unchanged)
- movement route fetches getCircleResources() and threads resources through
MovementPageView to its resources section
- movement resources now uses circlesSettings.resourcesSection copy + real rows
(drops placeholder rows / t(resources.*))
tsc + eslint + 61 tests clean.
The movement Upcoming Events was a hardcoded placeholder. Extract the circles
events section into a shared UpcomingEventsSection and render it on both pages
with the same live event data and copy.
- Add components/sections/shared/upcoming-events-section.tsx (date grouping,
EventCard, header, empty state) — circles events-section.tsx now delegates to
it (output unchanged)
- movement route fetches getUpcomingCircleEvents() and threads upcomingEvents +
locale through MovementPageView to the events section
- movement events section now uses circlesSettings.eventsSection copy + real
events (drops placeholder rows / t(events.*) and unused movementImages.event)
tsc + eslint + 61 tests clean.
The Logos Runtime destination is not yet available (waiting on docs).
Mark the foundation row comingSoon so it renders as a non-interactive
card with a "Soon" CTA instead of a link.