Skip to content

Commit 1aaf221

Browse files
committed
feat: add libraries highlight carousel card
1 parent c7720d2 commit 1aaf221

12 files changed

Lines changed: 514 additions & 31 deletions

File tree

ak/homepage.py

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,11 @@
55
from core.constants import SLACK_MEMBER_COUNT
66
from core.models import HomepageSettings
77
from core.templatetags.custom_static import large_static
8-
from libraries.models import LibraryVersion, Tier
9-
from libraries.utils import build_library_intro_context
8+
from libraries.models import FEATURED_LIBRARY_TIERS, Library, LibraryVersion
9+
from libraries.utils import build_library_intro_context, get_documentation_url
1010
from news.models import Entry
1111
from versions.models import Version
1212

13-
# Fallback code snippet shown on the Get Started card when no featured
14-
# library snippet is available. TODO: replace with a proper empty state.
15-
HELLO_WORLD_SNIPPET = """#include <iostream>
16-
int main()
17-
{
18-
std::cout << "Hello, Boost.";
19-
}"""
20-
2113
# Hero illustration for the V3 homepage.
2214
HERO_LEGACY_IMAGE_URL_LIGHT = large_static("img/v3/home-page/heros.png")
2315
HERO_LEGACY_IMAGE_URL_DARK = large_static("img/v3/home-page/heros_light.png")
@@ -45,7 +37,7 @@ def get_v3_featured_library():
4537
return (
4638
LibraryVersion.objects.filter(
4739
version=latest_version,
48-
library__tier__in=[Tier.FLAGSHIP, Tier.CORE],
40+
library__tier__in=FEATURED_LIBRARY_TIERS,
4941
)
5042
.order_by("?")
5143
.first()
@@ -152,17 +144,62 @@ def build_join_developers_links():
152144
]
153145

154146

155-
def build_get_started_code():
156-
"""The Get Started code card. Hardcoded for now; a redesign of this
157-
component is tracked in a separate PR.
147+
def build_library_highlight_carousel(limit=3):
148+
"""Per-slide content for the homepage 'Explore battle tested libraries'
149+
carousel.
150+
151+
Shows the libraries an editor curated in HomepageSettings first (in random
152+
order); when fewer than `limit` are curated, the remaining slots are filled
153+
with random flagship/core libraries in the latest release. Returns a list
154+
of dicts (name, category_tags, description, added_in_version, docs_url);
155+
empty when no candidate library exists.
158156
"""
159-
return {
160-
"heading": "Get started with our libraries",
161-
"code": HELLO_WORLD_SNIPPET,
162-
"language": "cpp",
163-
"library_slug": "",
157+
latest = Version.objects.most_recent()
158+
libraries = list(
159+
HomepageSettings.load()
160+
.highlighted_libraries.prefetch_related("categories")
161+
.order_by("?")
162+
)
163+
164+
remaining_slots = limit - len(libraries)
165+
if remaining_slots > 0:
166+
libraries += list(
167+
Library.objects.filter(
168+
tier__in=FEATURED_LIBRARY_TIERS,
169+
library_version__version=latest,
170+
)
171+
.exclude(id__in=[lib.id for lib in libraries])
172+
.distinct()
173+
.prefetch_related("categories")
174+
.order_by("?")[:remaining_slots]
175+
)
176+
if not libraries:
177+
return []
178+
179+
library_versions = {
180+
lv.library_id: lv
181+
for lv in LibraryVersion.objects.filter(library__in=libraries, version=latest)
164182
}
165183

184+
slides = []
185+
for library in libraries:
186+
lv = library_versions.get(library.id)
187+
first_version = library.first_boost_version
188+
slides.append(
189+
{
190+
"name": library.display_name_short,
191+
"category_tags": library.category_tags,
192+
"description": (
193+
(lv.description if lv else None) or library.description or ""
194+
),
195+
"added_in_version": (
196+
first_version.display_name if first_version else ""
197+
),
198+
"docs_url": get_documentation_url(lv, latest=True) if lv else "",
199+
}
200+
)
201+
return slides
202+
166203

167204
def build_library_intro():
168205
"""Library Intro card content for the V3 homepage, or None if no

ak/views.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
from ak.homepage import (
2727
WHY_BOOST_CARDS,
2828
build_community_posts,
29-
build_get_started_code,
3029
build_join_developers_links,
30+
build_library_highlight_carousel,
3131
build_library_intro,
3232
hero_image_context,
3333
)
@@ -116,8 +116,8 @@ def get_v3_context_data(self, **kwargs):
116116
# Testimonial Card
117117
ctx["testimonial_cards"] = get_testimonial_cards(limit=5)
118118

119-
# Get Started Card
120-
ctx["get_started_code"] = build_get_started_code()
119+
# Library Highlight Carousel ("Explore battle tested libraries")
120+
ctx["library_highlight_carousel"] = build_library_highlight_carousel()
121121

122122
# Library Intro Card
123123
ctx["library_intro"] = build_library_intro()
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Generated by Django 6.0.2 on 2026-06-30 16:03
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("core", "0008_popularsearchterm_popularsearchtermexclusion"),
10+
("libraries", "0041_category_short_description"),
11+
]
12+
13+
operations = [
14+
migrations.AddField(
15+
model_name="homepagesettings",
16+
name="highlighted_libraries",
17+
field=models.ManyToManyField(
18+
blank=True,
19+
help_text="Libraries shown in the homepage 'Explore battle tested libraries' carousel. Only flagship and core libraries present in the latest stable release are listed. If empty, a random selection of flagship or core libraries is used.",
20+
related_name="+",
21+
to="libraries.library",
22+
),
23+
),
24+
]

core/models.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,18 +144,20 @@ def wordcloud_ignore_set(self):
144144

145145

146146
class HomepageSettingsForm(WagtailAdminModelForm):
147-
"""Scopes the featured-library chooser to flagship and core libraries
148-
present in the latest stable release, A→Z."""
147+
"""Scopes the library choosers to flagship and core libraries present in
148+
the latest stable release, A→Z."""
149149

150150
def __init__(self, *args, **kwargs):
151151
super().__init__(*args, **kwargs)
152-
from libraries.models import Library, Tier
152+
from libraries.models import FEATURED_LIBRARY_TIERS, Library
153153

154-
qs = Library.objects.filter(tier__in=[Tier.FLAGSHIP, Tier.CORE])
154+
qs = Library.objects.filter(tier__in=FEATURED_LIBRARY_TIERS)
155155
latest = Version.objects.most_recent()
156156
if latest:
157157
qs = qs.filter(library_version__version=latest)
158-
self.fields["featured_library"].queryset = qs.order_by(Lower("name"))
158+
qs = qs.order_by(Lower("name"))
159+
self.fields["featured_library"].queryset = qs
160+
self.fields["highlighted_libraries"].queryset = qs
159161

160162

161163
@register_setting
@@ -178,7 +180,22 @@ class HomepageSettings(BaseGenericSetting):
178180
),
179181
)
180182

181-
panels = [FieldPanel("featured_library")]
183+
highlighted_libraries = models.ManyToManyField(
184+
"libraries.Library",
185+
blank=True,
186+
related_name="+",
187+
help_text=(
188+
"Libraries shown in the homepage 'Explore battle tested "
189+
"libraries' carousel. Only flagship and core libraries present in "
190+
"the latest stable release are listed. If empty, a random "
191+
"selection of flagship or core libraries is used."
192+
),
193+
)
194+
195+
panels = [
196+
FieldPanel("featured_library"),
197+
FieldPanel("highlighted_libraries"),
198+
]
182199

183200
class Meta:
184201
verbose_name = "Homepage Settings"

core/views.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1852,6 +1852,47 @@ def get_context_data(self, **kwargs):
18521852
},
18531853
]
18541854

1855+
context["demo_library_highlight_slides"] = [
1856+
{
1857+
"name": "Beast",
1858+
"category_tags": [
1859+
{"label": "Concurrent", "slug": "concurrent"},
1860+
{"label": "IO", "slug": "io"},
1861+
],
1862+
"description": (
1863+
"Portable HTTP, WebSocket, and network operations using only "
1864+
"C++11 and Boost.Asio. Designed for performance at scale."
1865+
),
1866+
"added_in_version": "1.66.0",
1867+
"docs_url": "#",
1868+
},
1869+
{
1870+
"name": "Asio",
1871+
"category_tags": [
1872+
{"label": "Concurrent", "slug": "concurrent"},
1873+
{"label": "IO", "slug": "io"},
1874+
],
1875+
"description": (
1876+
"Cross-platform C++ library for network and low-level I/O "
1877+
"programming with a consistent asynchronous model."
1878+
),
1879+
"added_in_version": "1.35.0",
1880+
"docs_url": "#",
1881+
},
1882+
{
1883+
"name": "Hana",
1884+
"category_tags": [
1885+
{"label": "Metaprogramming", "slug": "metaprogramming"},
1886+
],
1887+
"description": (
1888+
"A modern C++ metaprogramming library for computations on both "
1889+
"types and values."
1890+
),
1891+
"added_in_version": "1.61.0",
1892+
"docs_url": "#",
1893+
},
1894+
]
1895+
18551896
context["learn_card_data"] = {
18561897
"title": "I want to learn:",
18571898
"text": "How to install Boost, use its libraries, build projects, and get help when you need it.",

libraries/models.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,10 @@ class Tier(models.IntegerChoices):
223223
LEGACY = 40, "Legacy"
224224

225225

226+
# Tiers eligible to be featured on the V3 homepage (spotlight + highlight carousel).
227+
FEATURED_LIBRARY_TIERS = [Tier.FLAGSHIP, Tier.CORE]
228+
229+
226230
class Library(models.Model):
227231
"""
228232
Model to represent component Libraries of Boost

static/css/v3/components.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
@import "./avatar.css";
66
@import "./carousel-buttons.css";
77
@import "./cards-carousel.css";
8+
@import "./library-highlight-carousel.css";
89
@import "./badge.css";
910
@import "./count-badge.css";
1011
@import "./v3-examples-section.css";

0 commit comments

Comments
 (0)