From 9b7b36edb2fdd9501473e131e4131050daccde5c Mon Sep 17 00:00:00 2001 From: Boaz Poolman Date: Thu, 25 Jun 2026 13:55:09 +0200 Subject: [PATCH 01/14] chore: clean up cta usage --- .../src/api/cta/content-types/cta/schema.json | 6 -- apps/cms/types/generated/contentTypes.d.ts | 7 +- .../cms/pages/overview-page/template.tsx | 2 +- .../web/src/features/cms/sections/cta/cta.tsx | 84 +++++++++---------- 4 files changed, 42 insertions(+), 57 deletions(-) diff --git a/apps/cms/src/api/cta/content-types/cta/schema.json b/apps/cms/src/api/cta/content-types/cta/schema.json index ee48b12..2a2472b 100644 --- a/apps/cms/src/api/cta/content-types/cta/schema.json +++ b/apps/cms/src/api/cta/content-types/cta/schema.json @@ -36,12 +36,6 @@ "component": "shared.button", "repeatable": false, "required": true - }, - "illustration": { - "type": "enumeration", - "required": true, - "default": "image", - "enum": ["image", "community_members"] } } } diff --git a/apps/cms/types/generated/contentTypes.d.ts b/apps/cms/types/generated/contentTypes.d.ts index 6f20242..b8e88e1 100644 --- a/apps/cms/types/generated/contentTypes.d.ts +++ b/apps/cms/types/generated/contentTypes.d.ts @@ -513,9 +513,6 @@ export interface ApiCtaCta extends Struct.CollectionTypeSchema { createdAt: Schema.Attribute.DateTime; createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & Schema.Attribute.Private; - illustration: Schema.Attribute.Enumeration<['image', 'community_members']> & - Schema.Attribute.Required & - Schema.Attribute.DefaultTo<'image'>; image: Schema.Attribute.Media<'images'> & Schema.Attribute.Required; locale: Schema.Attribute.String & Schema.Attribute.Private; localizations: Schema.Attribute.Relation<'oneToMany', 'api::cta.cta'> & @@ -1522,10 +1519,10 @@ export interface PluginBetterAuthJwks extends Struct.CollectionTypeSchema { }; pluginOptions: { 'content-manager': { - visible: false; + visible: true; }; 'content-type-builder': { - visible: false; + visible: true; }; }; attributes: { diff --git a/apps/web/src/features/cms/pages/overview-page/template.tsx b/apps/web/src/features/cms/pages/overview-page/template.tsx index 97de371..f424c07 100644 --- a/apps/web/src/features/cms/pages/overview-page/template.tsx +++ b/apps/web/src/features/cms/pages/overview-page/template.tsx @@ -35,7 +35,7 @@ const OverviewPageTemplate = ({ document }: Props) => { alt={document.title!} width={480} height={480} - className="mt-10 rounded-lg object-cover ml-auto" + className="rounded-lg object-cover ml-auto" /> )} diff --git a/apps/web/src/features/cms/sections/cta/cta.tsx b/apps/web/src/features/cms/sections/cta/cta.tsx index 0442ad6..7ddb9eb 100644 --- a/apps/web/src/features/cms/sections/cta/cta.tsx +++ b/apps/web/src/features/cms/sections/cta/cta.tsx @@ -60,16 +60,7 @@ const sharedWrapperStyle: React.CSSProperties = { }; const CTASection = async ({ section }: Props) => { - const { cta } = section; - - const isCommunity = cta?.illustration === "community_members"; - - const users = isCommunity - ? await cmsClient.collection("plugin::better-auth.user").find({ - limit: 5, - populate: ["profile"], - }) - : null; + const cta = section.cta!; if (cta?.size === "S") { return ( @@ -77,15 +68,15 @@ const CTASection = async ({ section }: Props) => {
-
-
-

+
+
+

{cta.title}

-

+

{cta.content}

{cta.button?.link && ( @@ -99,22 +90,24 @@ const CTASection = async ({ section }: Props) => { )}
-
- {isCommunity && users?.data && users.data.length > 0 ? ( - - ) : ( - cta.image?.url && ( - { - ) - )} +
+ {cta.image.alternativeText +
+ { +
@@ -129,10 +122,10 @@ const CTASection = async ({ section }: Props) => {
-
+

{cta?.title}

@@ -149,22 +142,23 @@ const CTASection = async ({ section }: Props) => { )}
- - {isCommunity && users?.data && users.data.length > 0 ? ( -
- -
- ) : ( - cta?.image?.url && ( +
+ {cta.image.alternativeText +
{cta.image.alternativeText - ) - )} +
+
From c6c3062f03a94c05674cb7b4cd90c765c5c2ec06 Mon Sep 17 00:00:00 2001 From: Boaz Poolman Date: Thu, 25 Jun 2026 14:41:38 +0200 Subject: [PATCH 02/14] fix: template preview and submit buttons --- apps/web/public/template-fallback-preview.png | Bin 4342 -> 28044 bytes .../content/avatar-pile/avatar-pile.tsx | 9 +++-- .../layout/hero/home-hero/home-hero.tsx | 8 ++--- .../cms/sections/card-grid/card-grid.tsx | 34 +++++++++--------- 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/apps/web/public/template-fallback-preview.png b/apps/web/public/template-fallback-preview.png index e78fbea3f9e1dfdc53bfebf22c152ebeb48010cc..d37723ac6992484e72fbf6728e3f67ca0807edba 100644 GIT binary patch literal 28044 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 diff --git a/apps/web/src/components/content/avatar-pile/avatar-pile.tsx b/apps/web/src/components/content/avatar-pile/avatar-pile.tsx index 9b3eca8..8a18526 100644 --- a/apps/web/src/components/content/avatar-pile/avatar-pile.tsx +++ b/apps/web/src/components/content/avatar-pile/avatar-pile.tsx @@ -7,6 +7,7 @@ type Props = { items: Data.ContentType<"plugin::better-auth.user">[]; size?: "S" | "L"; clickable?: boolean; + white?: boolean; }; // Percentage widths per slot (outer → center → outer), relative to the container. @@ -60,7 +61,7 @@ const AvatarLarge = ({ ); }; -const AvatarPile = ({ items, clickable, size = "S" }: Props) => { +const AvatarPile = ({ items, clickable, size = "S", white = false }: Props) => { if (!items?.length) return null; if (size === "L") { @@ -91,9 +92,7 @@ const AvatarPile = ({ items, clickable, size = "S" }: Props) => { style={{ marginLeft: i === 0 ? 0 : -8 }} /> {items.filter(Boolean).length === 1 && ( - - {items.find(Boolean)?.name} - + {items.find(Boolean)?.name} )} ) : ( @@ -109,7 +108,7 @@ const AvatarPile = ({ items, clickable, size = "S" }: Props) => { {m.name?.[0]}

{items.filter(Boolean).length === 1 && ( - + {items.find(Boolean)?.name} )} diff --git a/apps/web/src/components/layout/hero/home-hero/home-hero.tsx b/apps/web/src/components/layout/hero/home-hero/home-hero.tsx index 345a32f..beaecf2 100644 --- a/apps/web/src/components/layout/hero/home-hero/home-hero.tsx +++ b/apps/web/src/components/layout/hero/home-hero/home-hero.tsx @@ -153,7 +153,7 @@ const HomeHero = (props: Props) => {

{/* Avatar pile */}
- +
@@ -163,7 +163,7 @@ const HomeHero = (props: Props) => {
{/* Preview placeholder */} -
+
{ template.name ?? "" } - className="rounded-lg border border-(--color-grey700)" + className="rounded-lg border border-(--color-grey700) object-cover" />

@@ -187,7 +187,7 @@ const HomeHero = (props: Props) => {

{/* Avatar pile */}
- +

diff --git a/apps/web/src/features/cms/sections/card-grid/card-grid.tsx b/apps/web/src/features/cms/sections/card-grid/card-grid.tsx index 08dd449..c339764 100644 --- a/apps/web/src/features/cms/sections/card-grid/card-grid.tsx +++ b/apps/web/src/features/cms/sections/card-grid/card-grid.tsx @@ -15,23 +15,23 @@ const CardGridSection = ({ section }: Props) => { {section.items?.map((item, index) => (
-
-
- {item.icon && ( - - {renderIcon(item.icon, { - size: 24, - className: "text-(--color-primary700)", - })} - - )} -

- {item.title} -

-
-

+

+ {item.icon && ( + + {renderIcon(item.icon, { + size: 24, + className: "text-(--color-primary700)", + })} + + )} +

+ {item.title} +

+
+
+

{item.content}

From b34279224531ded67b37c367a3f7b0d02cb1d606 Mon Sep 17 00:00:00 2001 From: Boaz Poolman Date: Thu, 25 Jun 2026 14:45:42 +0200 Subject: [PATCH 03/14] chore: clean up migrations --- apps/cms/.env.example | 2 - apps/cms/src/migration/showcases.ts | 132 ---------------------------- 2 files changed, 134 deletions(-) delete mode 100644 apps/cms/src/migration/showcases.ts diff --git a/apps/cms/.env.example b/apps/cms/.env.example index 43acf50..ea12fc3 100644 --- a/apps/cms/.env.example +++ b/apps/cms/.env.example @@ -43,8 +43,6 @@ ENABLE_MIGRATION=false GITHUB_ACCESS_TOKEN=tobemodified -SCREENSHOTONE_KEY=tobemodified - # SendGrid — used for Strapi-native emails (password resets, admin invites). # Automation emails (submission received, approved, etc.) run through n8n with # a separate SendGrid key. See github.com/strapi/community/issues/54. diff --git a/apps/cms/src/migration/showcases.ts b/apps/cms/src/migration/showcases.ts deleted file mode 100644 index b4b096f..0000000 --- a/apps/cms/src/migration/showcases.ts +++ /dev/null @@ -1,132 +0,0 @@ -import * as fs from "node:fs"; -import * as os from "node:os"; -import * as path from "node:path"; -import { parse } from "yaml"; -import { createCategories, uploadFile } from "./utils"; - -const GITHUB_API_URL = - "https://api.github.com/repos/strapi/community-content/contents/showcase/sites.yml?ref=master"; - -type ShowcaseSite = { - title: string; - url: string; - description: string; - categories?: string[]; - frontend?: string[]; - made_by?: string; - made_by_url?: string; -}; - -const captureScreenshot = async (url: string, title: string) => { - const params = new URLSearchParams({ - access_key: process.env.SCREENSHOTONE_KEY, - url, - viewport_width: "1024", - viewport_height: "768", - format: "jpg", - block_ads: "true", - block_cookie_banners: "true", - block_banners_by_heuristics: "false", - block_trackers: "true", - delay: "3", - timeout: "20", - response_type: "by_format", - image_quality: "80", - }); - - const response = await fetch(`https://api.screenshotone.com/take?${params}`, { - signal: AbortSignal.timeout(90_000), - }); - - if (!response.ok) { - throw new Error( - `Screenshot API returned ${response.status} for ${url}. ${await response.text()}`, - ); - } - - const buffer = Buffer.from(await response.arrayBuffer()); - const tmpPath = path.join( - os.tmpdir(), - `screenshot-${Date.now()}-${Math.random().toString(36).slice(2)}.jpg`, - ); - - await fs.promises.writeFile(tmpPath, buffer); - - try { - return await uploadFile(tmpPath, `${title}.jpg`, "image/jpeg"); - } finally { - await fs.promises.unlink(tmpPath).catch(() => {}); - } -}; - -export const migrateShowcases = async () => { - strapi.log.info("Starting showcases migration..."); - let migrated = 0; - let skipped = 0; - let failed = 0; - - try { - const response = await fetch(GITHUB_API_URL, { - headers: { Accept: "application/vnd.github.v3+json" }, - }); - - if (!response.ok) { - throw new Error(`GitHub API request failed: ${response.statusText}`); - } - - const { content } = (await response.json()) as { content: string }; - const yamlContent = Buffer.from(content, "base64").toString("utf-8"); - const sites = parse(yamlContent) as ShowcaseSite[]; - - for (const site of sites) { - const existing = await strapi - .documents("api::showcase.showcase") - .findFirst({ filters: { url: site.url } }); - - if (existing) { - skipped++; - continue; - } - - const categoryIds = await createCategories( - "api::showcase-category.showcase-category", - site.categories ?? [], - ); - - const techStackIds = await createCategories( - "api::tech-stack.tech-stack", - site.frontend ?? [], - ); - - let image = null; - try { - image = await captureScreenshot(site.url, site.title); - } catch (err) { - strapi.log.warn( - `Failed to capture screenshot for ${site.url}, skipping.`, - err, - ); - failed++; - continue; - } - - await strapi.documents("api::showcase.showcase").create({ - data: { - title: site.title, - url: site.url, - description: site.description, - categories: categoryIds, - tech_stacks: techStackIds, - ...(image ? { image: image.id } : {}), - }, - }); - migrated++; - } - } catch (error) { - strapi.log.error("Error migrating showcases:", error); - } finally { - strapi.log.info( - `Showcases migration finished. Migrated: ${migrated}, Skipped: ${skipped}, Failed: ${failed}`, - ); - } -}; From 765e209edea36b62d8d41c7079df5516a696ada8 Mon Sep 17 00:00:00 2001 From: Boaz Poolman Date: Thu, 25 Jun 2026 15:15:16 +0200 Subject: [PATCH 04/14] chore: add modal for filters --- apps/cms/src/index.ts | 2 - .../cms/pages/overview-page/template.tsx | 8 +- .../components/search-index/search-index.tsx | 136 ++++++++++++++++-- .../search/components/sort-by/sort-by.tsx | 2 +- 4 files changed, 127 insertions(+), 21 deletions(-) diff --git a/apps/cms/src/index.ts b/apps/cms/src/index.ts index 730e201..3dd0190 100644 --- a/apps/cms/src/index.ts +++ b/apps/cms/src/index.ts @@ -3,7 +3,6 @@ import { migrateIntegrations } from "./migration/integrations"; import { migratePartners } from "./migration/partners"; import { migratePlugins } from "./migration/plugins"; import { migrateProviders } from "./migration/providers"; -import { migrateShowcases } from "./migration/showcases"; import { seedEmailTemplates } from "./seed/email-templates"; export default { @@ -20,6 +19,5 @@ export default { await migrateIntegrations(); await migratePlugins(); await migrateProviders(); - await migrateShowcases(); }, }; diff --git a/apps/web/src/features/cms/pages/overview-page/template.tsx b/apps/web/src/features/cms/pages/overview-page/template.tsx index f424c07..27b5fcd 100644 --- a/apps/web/src/features/cms/pages/overview-page/template.tsx +++ b/apps/web/src/features/cms/pages/overview-page/template.tsx @@ -17,12 +17,12 @@ const OverviewPageTemplate = ({ document }: Props) => { -
-
+
+
-

+

{document.title}

@@ -35,7 +35,7 @@ const OverviewPageTemplate = ({ document }: Props) => { alt={document.title!} width={480} height={480} - className="rounded-lg object-cover ml-auto" + className="rounded-lg object-cover ml-auto md:ml-auto w-full max-w-120 md:max-w-120 md:min-w-0 md:shrink max-h-130" /> )}

diff --git a/apps/web/src/features/search/components/search-index/search-index.tsx b/apps/web/src/features/search/components/search-index/search-index.tsx index 1c9f6e6..0714c5a 100644 --- a/apps/web/src/features/search/components/search-index/search-index.tsx +++ b/apps/web/src/features/search/components/search-index/search-index.tsx @@ -1,13 +1,16 @@ "use client"; import { instantMeiliSearch } from "@meilisearch/instant-meilisearch"; +import { SlidersHorizontal, X } from "lucide-react"; import type { ComponentPropsWithoutRef, ReactNode } from "react"; +import { createContext, useContext, useEffect, useState } from "react"; import { Configure, InstantSearch } from "react-instantsearch"; import { InstantSearchNext } from "react-instantsearch-nextjs"; import { GridHits } from "@/features/search/components/grid-hits"; import { SearchBox } from "@/features/search/components/search-box"; import { SortBy } from "@/features/search/components/sort-by"; import { Stats } from "@/features/search/components/stats"; +import { cn } from "@/lib/utils"; const { searchClient } = instantMeiliSearch( process.env.NEXT_PUBLIC_SEARCH_URL as string, @@ -15,6 +18,22 @@ const { searchClient } = instantMeiliSearch( { keepZeroFacets: true }, ); +// Context + +interface SearchIndexContextValue { + isFilterModalOpen: boolean; + setIsFilterModalOpen: (open: boolean) => void; + hasFilters: boolean; + setHasFilters: (has: boolean) => void; +} + +const SearchIndexContext = createContext({ + isFilterModalOpen: false, + setIsFilterModalOpen: () => {}, + hasFilters: false, + setHasFilters: () => {}, +}); + // Root interface SearchIndexRootProps { @@ -49,19 +68,91 @@ const SearchIndexRoot = ({ // Layout -const SearchIndexLayout = ({ children }: { children: ReactNode }) => ( -
{children}
-); +const SearchIndexLayout = ({ children }: { children: ReactNode }) => { + const [isFilterModalOpen, setIsFilterModalOpen] = useState(false); + const [hasFilters, setHasFilters] = useState(false); + + useEffect(() => { + if (isFilterModalOpen) { + document.body.style.overflow = "hidden"; + } + return () => { + document.body.style.overflow = ""; + }; + }, [isFilterModalOpen]); + + return ( + +
{children}
+
+ ); +}; // Sidebar -const SearchIndexSidebar = ({ children }: { children?: ReactNode }) => ( - -); +const SearchIndexSidebar = ({ children }: { children?: ReactNode }) => { + const { isFilterModalOpen, setIsFilterModalOpen, setHasFilters } = + useContext(SearchIndexContext); + + useEffect(() => { + setHasFilters(true); + return () => setHasFilters(false); + }, [setHasFilters]); + + if (!children) return null; + + return ( + + ); +}; // FilterGroup @@ -106,9 +197,26 @@ const SearchIndexSearchBox = () => ( // Toolbar -const SearchIndexToolbar = ({ children }: { children: ReactNode }) => ( -
{children}
-); +const SearchIndexToolbar = ({ children }: { children: ReactNode }) => { + const { hasFilters, setIsFilterModalOpen } = useContext(SearchIndexContext); + + return ( +
+ {hasFilters && ( + + )} + {children} +
+ ); +}; // Stats @@ -122,7 +230,7 @@ interface SortItem { } const SearchIndexSortBy = ({ items }: { items: SortItem[] }) => ( -
+
); diff --git a/apps/web/src/features/search/components/sort-by/sort-by.tsx b/apps/web/src/features/search/components/sort-by/sort-by.tsx index 83458bc..aa1d4fb 100644 --- a/apps/web/src/features/search/components/sort-by/sort-by.tsx +++ b/apps/web/src/features/search/components/sort-by/sort-by.tsx @@ -14,7 +14,7 @@ const SortBy = (props: SortByProps) => { return ( setSearchQuery(e.target.value)} + onKeyDown={(e) => { + if (e.key === "Enter" && searchQuery.trim()) { + router.push( + `/marketplace?query=${encodeURIComponent(searchQuery.trim())}`, + ); + } + }} placeholder="Search Community" className="w-full rounded-lg border border-(--color-grey700) px-4 py-3.5 pr-12 text-sm text-white placeholder:text-(--color-hero-nav-muted) focus:outline-none focus:ring-1 focus:ring-(--color-primary500)" style={{ @@ -78,8 +111,8 @@ const HomeHero = (props: Props) => {
- {/* Right: Join Community CTA */} -
+ {/* CTA: Join Community */} +

{ctaTitle}

@@ -104,35 +137,51 @@ const HomeHero = (props: Props) => { {/* Bottom section: Tabs + Cards */} {/* Tab bar */} -
- {tabs.map((tab) => ( - - ))} +
+
+
+ {tabs.map((tab) => ( + + ))} +
+
{/* Cards grid */} -
+
{activeTab === "packages" && packages.map((pkg) => ( -
+
- {/* Preview placeholder */} -
+
{

{pkg.description}

- {/* Avatar pile */}
@@ -160,10 +208,9 @@ const HomeHero = (props: Props) => { ))} {activeTab === "templates" && templates.map((template) => ( -
+
- {/* Preview placeholder */} -
+
{

{template.description}

- {/* Avatar pile */}
@@ -197,7 +243,7 @@ const HomeHero = (props: Props) => { {/* View More button */} {activeTab === "templates" && ( -
+
)} {activeTab === "packages" && ( -
+