Skip to content
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
14e41a6
feat: wire homepage static CTAs and redirects to real destinations
julhoang May 27, 2026
cd8deb7
chore: delete unused context data
julhoang May 27, 2026
e0c7e64
feat: wire homepage community posts to news.Entry
julhoang May 27, 2026
5092750
feat: add User.tagline one-line bio field
julhoang May 27, 2026
bdb6ff3
feat: wire Library Intro Card with real library data
julhoang May 27, 2026
35166e7
feat: wire homepage upcoming events to the Boost calendar
julhoang May 27, 2026
dae2684
feat: wire Boost in numbers to project-wide commits per release
julhoang May 27, 2026
98da102
feat: wire homepage testimonials to live CMS pages
julhoang May 27, 2026
56f9dd7
feat: wire Get Started card to featured library code snippet
julhoang May 28, 2026
5ffc38e
feat: wire join card
julhoang May 28, 2026
2e73548
feat: wire why boost card
julhoang May 28, 2026
056744a
fix: use latest release version in featured library option list
julhoang May 28, 2026
a43cd8d
feat: allow testimonial author role to support hyperlink
julhoang Jun 2, 2026
f0738e2
feat: update Build anything with Boost card content
julhoang Jun 2, 2026
307e3b6
feat: add tooltip to commit bar card to showcase commit counts
julhoang Jun 2, 2026
b9efba8
feat: allow core libraries to be featured in library intro card
julhoang Jun 2, 2026
971ce1b
refactor: create Install System command const and use it across all v…
julhoang Jun 2, 2026
4267d7a
refactor: centralize V3 user/post card dicts on model methods
julhoang Jun 4, 2026
5bcc458
refactor: extract V3 homepage adapters and flatten card context
julhoang Jun 4, 2026
e4a929e
docs: simplify docs
julhoang Jun 4, 2026
8ee7300
chore: update Join Card links
julhoang Jun 4, 2026
949d060
revert: drop User.tagline field
julhoang Jun 4, 2026
9b51edb
chore: drop unused LibraryCodeSnippet model and helper
julhoang Jun 4, 2026
3050d0d
feat: improve empty state of event card
julhoang Jun 4, 2026
41493c7
chore: run hook to fix formatting error
julhoang Jun 4, 2026
810b344
feat: open testimonial user profile links in a new tab
julhoang Jun 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 185 additions & 0 deletions ak/homepage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
"""Adapters turning backend data into V3 homepage template context."""

from django.urls import reverse

from core.constants import SLACK_MEMBER_COUNT
from core.models import HomepageSettings
from core.templatetags.custom_static import large_static
from libraries.models import Library, LibraryVersion, Tier
from libraries.utils import build_library_intro_context
from news.models import Entry
from versions.models import Version


# Fallback code snippet shown on the Get Started card when no featured
# library snippet is available. TODO: replace with a proper empty state.
HELLO_WORLD_SNIPPET = """#include <iostream>
int main()
{
std::cout << "Hello, Boost.";
}"""

# Hero illustration for the V3 homepage.
HERO_LEGACY_IMAGE_URL_LIGHT = large_static("img/v3/home-page/heros.png")
HERO_LEGACY_IMAGE_URL_DARK = large_static("img/v3/home-page/heros_light.png")
HERO_FOREGROUND_IMAGE_URL = large_static("img/v3/home-page/home-page-foreground.png")


def get_v3_featured_library():
"""LibraryVersion to feature on the V3 homepage.

Prefers the library an editor chose in HomepageSettings, otherwise a
random flagship- or core-tier library. Resolves to that library's
latest-release LibraryVersion, or None if it has none.
"""
library = HomepageSettings.load().featured_library
latest_version = Version.objects.most_recent()

if not library:
library = (
Library.objects.filter(
tier__in=[Tier.FLAGSHIP, Tier.CORE],
library_version__version=latest_version,
)
.order_by("?")
.first()
)
if not library:
return None

return LibraryVersion.objects.filter(
library=library, version=latest_version
).first()


# Static "Why Boost" card grid; pure presentation data so it lives at module
# scope rather than being rebuilt per request.
WHY_BOOST_CARDS = [
{
"title": "Performant",
"description": "Optimized for production at any scale, Boost outperforms many standard benchmarks.",
"icon_name": "speed-fast",
"icon_viewbox": "0 0 16 16",
},
{
"title": "Peer-reviewed",
"description": "Well tested by members of the C++ standards committee.",
"icon_name": "eye",
},
{
"title": "Portable",
"description": "Works across all platforms, compilers, and C++ standards.",
"icon_name": "arrows-horizontal",
"icon_viewbox": "0 0 16 16",
},
{
"title": "Free",
"description": "Open source now and always, thanks to the Boost Software License.",
"icon_name": "lock",
"icon_viewbox": "0 0 16 16",
},
{
"title": "Innovative",
"description": "Over 40 Boost libraries have become part of the C++ standard over the past 25 years.",
"icon_name": "bookmarks",
"icon_viewbox": "0 0 16 16",
},
{
"title": "Community-powered",
"description": "Contributing to Boost builds credibility, sharpens skills, and advances careers.",
"icon_name": "users",
"icon_viewbox": "0 0 16 16",
},
{
"title": "Known worldwide",
"description": "Used in countless projects, you've probably encountered Boost without realizing it",
"icon_name": "building-community",
"icon_viewbox": "0 0 16 16",
},
{
"title": "Production-ready",
"description": "Battle-tested in critical systems across industries around the globe.",
"icon_name": "zap",
"icon_viewbox": "0 0 16 16",
},
]


def build_community_posts(limit=5):
"""Top-ranked posts shown on the V3 homepage.

Returns just the list of post dicts; the surrounding card chrome
(heading, CTA, variant, theme) lives in the template. Uses
`Entry.ranked()` (popularity-ordered), not chronological.
"""
popular_entries = (
Entry.objects.ranked()
.filter(deleted_at__isnull=True, published=True)
.select_related("author")[:limit]
)
return [entry.to_v3_post_card_dict() for entry in popular_entries]


def build_join_developers_links():
"""Three-link list for the 'Join developers building the future of C++'
card. Surrounding card chrome (heading, CTA, variant, theme) lives in
the template.
"""
return [
{
"title": "Get help",
"description": f"Tap into quick answers, networking, and chat with {SLACK_MEMBER_COUNT} members.",
"icon_name": "message",
"icon_viewbox": "0 0 16 16",
"url": "https://cppalliance.org/slack/",
},
{
"title": "Contribute",
"description": "Learn how to test or evaluate library submissions, or submit your own.",
"icon_name": "documentation",
"icon_viewbox": "0 0 16 16",
"url": reverse(
"docs-user-guide",
kwargs={"content_path": "contributor-guide/contributors-faq.html"},
),
},
{
"title": "Stay updated",
"description": "Get updates on the latest releases, fixes and announcements.",
"icon_name": "bullseye-pixel",
"url": "https://lists.boost.org/mailman3/lists/boost-announce.lists.boost.org/",
},
]


def build_get_started_code():
"""The Get Started code card. Hardcoded for now; a redesign of this
component is tracked in a separate PR.
"""
return {
"heading": "Get started with our libraries",
"code": HELLO_WORLD_SNIPPET,
"language": "cpp",
"library_slug": "",
}


def build_library_intro():
"""Library Intro card content for the V3 homepage, or None if no
featured library is available.
"""
featured_library = get_v3_featured_library()
if not featured_library:
return None
return build_library_intro_context(featured_library, include_contributors=False)


def hero_image_context():
"""Hero image URLs used by `_hero_home.html`"""
return {
"hero_legacy_image_url_light": HERO_LEGACY_IMAGE_URL_LIGHT,
"hero_legacy_image_url_dark": HERO_LEGACY_IMAGE_URL_DARK,
"hero_image_url": HERO_FOREGROUND_IMAGE_URL,
"hero_image_url_light": HERO_FOREGROUND_IMAGE_URL,
"hero_image_url_dark": HERO_FOREGROUND_IMAGE_URL,
}
173 changes: 53 additions & 120 deletions ak/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,31 @@
from django.core.exceptions import PermissionDenied
from django.http import Http404, HttpResponse
from django.shortcuts import render
from django.urls import reverse
from django.views import View
from django.views.generic import TemplateView

from core.calendar import extract_calendar_events, events_by_month, get_calendar
from core.calendar import (
extract_calendar_events,
events_by_month,
get_calendar,
upcoming_events,
)
from core.install_commands import INSTALL_PKG_MANAGERS, INSTALL_SYSTEM_INSTALL
from core.mixins import V3Mixin
from core.templatetags.custom_static import large_static
from libraries.constants import LATEST_RELEASE_URL_PATH_STR
from libraries.mixins import ContributorMixin
from news.models import Entry
from testimonials.models import Testimonial
from core.mock_data import SharedResources
from ak.homepage import (
WHY_BOOST_CARDS,
build_community_posts,
build_get_started_code,
build_join_developers_links,
build_library_intro,
hero_image_context,
)
from testimonials.utils import get_testimonial_cards
from libraries.utils import commit_data_to_stats_bars, get_commit_data_by_release


logger = structlog.get_logger()
Expand Down Expand Up @@ -74,124 +87,44 @@ def get_events(self):
return dict(sorted_events)

def get_v3_context_data(self, **kwargs):
# super() here is TemplateView.get_context_data, not this view's
# legacy get_context_data — V3Mixin merges the legacy context in
# via render_v3_response.
ctx = super().get_context_data(**kwargs)
ctx["install_card_pkg_managers"] = SharedResources.install_card_pkg_managers
ctx["install_card_system_install"] = SharedResources.install_card_system_install

demo_cards = [
{
"title": "Performant",
"description": "Optimized for production at any scale, Boost outperforms many standard benchmarks.",
"icon_name": "bullseye-arrow",
},
{
"title": "Peer-reviewed",
"description": "Well tested by members of the C++ standards committee.",
"icon_name": "get-help",
},
{
"title": "Portable",
"description": "Works across all platforms, compilers, and C++ standards.",
"icon_name": "link",
},
{
"title": "Innovative",
"description": "Over 40 Boost libraries have become part of the C++ standard over the past 25 years.",
"icon_name": "bullseye-arrow",
},
{
"title": "Community-powered",
"description": "Contributing to Boost builds credibility, sharpens skills, and advances careers.",
"icon_name": "human",
},
{
"title": "Known worldwide",
"description": "Used in countless projects, you've probably encountered Boost without realizing it.",
"icon_name": "link",
},
{
"title": "Free",
"description": "Open source now and always, thanks to the Boost Software License.",
"icon_name": "check",
},
{
"title": "Production-ready",
"description": "Battle-tested in critical systems across industries around the globe.",
"icon_name": "bullseye-arrow",
},
]

ctx["library_cards"] = demo_cards
ctx["why_boost_cards"] = demo_cards[:8]
ctx["calendar_card"] = {
"title": "Boost is released three times a year",
"text": "Each release has updates to existing libraries, and any new libraries that have passed the rigorous acceptance process.",
"primary_button_url": "www.example.com",
"primary_button_label": "View the Release Calendar",
"secondary_button_url": "www.example.com",
"secondary_button_label": "Secondary Button",
"image": large_static("img/v3/demo-page/calendar.png"),
}
ctx["info_card"] = {
"title": "How we got here",
"text": "Since 1998, Boost has been where C++ innovation happens. What started with three developers has grown into the foundation of modern C++ development.",
"primary_button_url": "www.example.com",
"primary_button_label": "Explore Our History",
}
tag_display = {"blogpost": "Blog"}
popular_entries = (
Entry.objects.ranked()
.filter(deleted_at__isnull=True, published=True)
.select_related("author")[:5]

# Install Card
ctx["install_card_pkg_managers"] = INSTALL_PKG_MANAGERS
ctx["install_card_system_install"] = INSTALL_SYSTEM_INSTALL

# Why Boost Card
ctx["why_boost_cards"] = WHY_BOOST_CARDS

# Posts Card
ctx["community_posts"] = build_community_posts()

# Join Card
ctx["join_developers_links"] = build_join_developers_links()

# Upcoming Events
ctx["upcoming_events"] = upcoming_events(self.get_events(), 4)

# Testimonial Card
ctx["testimonial_cards"] = get_testimonial_cards(limit=5)

# Get Started Card
ctx["get_started_code"] = build_get_started_code()

# Library Intro Card
ctx["library_intro"] = build_library_intro()

# "Boost in numbers" is project-wide, not tied to the featured library.
ctx["commits_data"] = commit_data_to_stats_bars(
get_commit_data_by_release(limit=10)
)
ctx["posts_from_the_boost_community"] = {
"heading": "Posts from the Boost Community",
"primary_cta_label": "View all posts",
"primary_cta_url": reverse("news"),
"variant": "card",
"theme": "teal",
"items": [
{
"title": entry.title,
"url": entry.get_absolute_url(),
"date": entry.publish_at,
"category": (
tag_display.get(str(entry.tag).lower(), entry.tag.capitalize())
if entry.tag
else ""
),
"tag": "",
"author": entry.author.to_v3_profile_dict(),
}
for entry in popular_entries
],
}
ctx["join_developers_building_the_future_of_cpp"] = {
"items": SharedResources.demo_join_community_links[:5]
}
ctx["boost_community_data"] = {
"heading": "The Boost community",
"view_all_url": "#",
"view_all_label": "Explore the community",
"posts": SharedResources.demo_posts,
}
ctx["popular_terms"] = SharedResources.popular_terms
ctx["demo_events_with_links"] = SharedResources.demo_events_with_links[:4]
ctx["code_demo_hello"] = SharedResources.code_demo_hello
ctx["stats_in_numbers"] = {
"example_library_commits_bars": SharedResources.example_library_commits_bars
}
ctx["testimonial_data"] = {"testimonials": SharedResources.testimonials}

ctx["library_intro"] = SharedResources.library_intro

ctx["build_anything_with_boost"] = SharedResources.build_anything_with_boost

ctx["hero_legacy_image_url_light"] = SharedResources.hero_legacy_image_url_light
ctx["hero_legacy_image_url_dark"] = SharedResources.hero_legacy_image_url_dark
ctx["hero_image_url"] = SharedResources.hero_image_url
ctx["hero_image_url_light"] = SharedResources.hero_image_url_light
ctx["hero_image_url_dark"] = SharedResources.hero_image_url_dark

# Hero Image
ctx.update(hero_image_context())

return ctx


Expand Down
1 change: 1 addition & 0 deletions config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
INSTALLED_APPS += [
"wagtail.contrib.forms",
"wagtail.contrib.redirects",
"wagtail.contrib.settings",
"wagtail.embeds",
"wagtail.sites",
"wagtail.users",
Expand Down
Loading
Loading