@@ -73,3 +206,7 @@ export function LandingNav() {
function getLandingAnchorHref(hash: string) {
return window.location.pathname === "/" ? hash : `/${hash}`;
}
+
+function getNavHref(href: string) {
+ return href.startsWith("#") ? getLandingAnchorHref(href) : href;
+}
diff --git a/src/components/landing/LandingSections.tsx b/src/components/landing/LandingSections.tsx
index def0cbc..31b1c19 100644
--- a/src/components/landing/LandingSections.tsx
+++ b/src/components/landing/LandingSections.tsx
@@ -221,6 +221,65 @@ export function ClosingCTA() {
}
export function LandingFooter() {
+ const footerGroups = [
+ {
+ title: "Product",
+ links: [
+ { href: "/#studio", label: "Studio" },
+ { href: "/product/github-repo-to-launch-package", label: "Repo to launch package" },
+ { href: "/product/source-backed-launch-assets", label: "Source-backed launch assets" },
+ { href: "/product/cold-start-launch-materials", label: "Cold-start launch materials" },
+ { href: "/product/repository-launch-package-pilot", label: "Launch package pilot" },
+ ],
+ },
+ {
+ title: "Use Cases",
+ links: [
+ { href: "/use-cases/open-source-launch", label: "Open-source launch" },
+ { href: "/use-cases/ai-project-launch", label: "AI project launch" },
+ { href: "/use-cases/devrel-launch-workflow", label: "DevRel launch workflow" },
+ ],
+ },
+ {
+ title: "Resources",
+ links: [
+ { href: "/resources/open-source-launch-checklist", label: "Checklist" },
+ { href: "/resources/github-project-marketing-card-guide", label: "Marketing card guide" },
+ { href: "/resources/github-repo-launch-demand-map", label: "Launch demand map" },
+ { href: "/tools/github-repo-launch-readiness-score", label: "Readiness score" },
+ { href: "/templates/github-launch-announcement", label: "Launch template" },
+ ],
+ },
+ {
+ title: "Examples",
+ links: [
+ { href: "/examples/qwenlm-flashqla-launch-card", label: "FlashQLA" },
+ { href: "/examples/deepseek-twvp-launch-card", label: "DeepSeek TWVP" },
+ { href: "/compare/chatgpt-open-source-launch-copy", label: "ChatGPT comparison" },
+ { href: "/compare/canva-readme-banner-generator", label: "Canva comparison" },
+ ],
+ },
+ {
+ title: "Support",
+ links: [
+ { href: "/contact", label: "Contact" },
+ { href: "/help", label: "Help" },
+ { href: "/sign-in", label: "Sign in" },
+ { href: "/sign-up", label: "Sign up" },
+ ],
+ },
+ {
+ title: "Legal and AI Discovery",
+ links: [
+ { href: "/privacy", label: "Privacy" },
+ { href: "/terms", label: "Terms" },
+ { href: "/llms.txt", label: "llms.txt" },
+ { href: "/pricing.md", label: "pricing.md" },
+ { href: "/sitemap.xml", label: "sitemap.xml" },
+ ],
+ },
+ ];
+
return (
);
diff --git a/src/components/marketing/MarketingPage.tsx b/src/components/marketing/MarketingPage.tsx
index 759daa8..2fd3bd0 100644
--- a/src/components/marketing/MarketingPage.tsx
+++ b/src/components/marketing/MarketingPage.tsx
@@ -4,7 +4,7 @@ import { useEffect } from "react";
import { LandingFooter } from "../landing/LandingSections";
import { LandingNav } from "../landing/LandingNav";
import { trackEvent } from "../../lib/analytics";
-import { marketingPageLinks, type MarketingLink } from "../../marketing/link-catalog";
+import { marketingPageLinks, type MarketingLink, type MarketingPageType } from "../../marketing/link-catalog";
import {
formatMarketingLabel,
getMarketingPageDescription,
@@ -82,6 +82,7 @@ export function MarketingPage({ link }: MarketingPageProps) {
+
@@ -357,14 +358,19 @@ export function MarketingPage({ link }: MarketingPageProps) {
) : null}
{relatedLinks.length > 0 ? (
-
+
Related routes
{relatedLinks.map((relatedLink) => (
-
+
{getMarketingPageTypeLabel(relatedLink)}
{formatMarketingLabel(relatedLink.primaryKeyword)}
{getMarketingPrimaryCtaLabel(relatedLink)}
@@ -379,6 +385,18 @@ export function MarketingPage({ link }: MarketingPageProps) {
);
}
+function MarketingBreadcrumbs({ link }: { link: MarketingLink }) {
+ return (
+
+ );
+}
+
function applyRouteMetadata(link: MarketingLink) {
const previousTitle = document.title;
const descriptionMeta = getOrCreateMetaDescription();
@@ -455,12 +473,107 @@ function applyMarketingSchema(link: MarketingLink) {
}
function getRelatedLinks(currentLink: MarketingLink) {
+ const curatedSlugs = curatedRelatedLinkSlugs[currentLink.slug];
+
+ if (curatedSlugs) {
+ return curatedSlugs
+ .map((slug) => marketingPageLinks.find((link) => link.slug === slug))
+ .filter((link): link is MarketingLink => Boolean(link));
+ }
+
return marketingPageLinks
.filter((link) => link.slug !== currentLink.slug)
.filter((link) => link.funnelStage === currentLink.funnelStage || link.buyerStage === currentLink.buyerStage)
.slice(0, 3);
}
+const curatedRelatedLinkSlugs: Record = {
+ "github-repo-to-launch-package": [
+ "open-source-launch",
+ "open-source-launch-checklist",
+ "github-repo-launch-readiness-score",
+ ],
+ "source-backed-launch-assets": [
+ "github-project-marketing-card-guide",
+ "chatgpt-open-source-launch-copy",
+ "repository-launch-package-pilot",
+ ],
+ "cold-start-launch-materials": [
+ "github-repo-launch-demand-map",
+ "ai-project-launch",
+ "github-repo-launch-materials-map",
+ ],
+ "github-repo-launch-materials-map": [
+ "devrel-launch-workflow",
+ "github-launch-announcement",
+ "github-repo-to-product-outreach",
+ ],
+ "readme-marketing-cards": [
+ "readme-cover-prompt-guide",
+ "canva-readme-banner-generator",
+ "qwenlm-flashqla-launch-card",
+ ],
+ "github-repo-visual-explainer": [
+ "qwenlm-flashqla-launch-card",
+ "deepseek-twvp-launch-card",
+ "github-project-marketing-card-guide",
+ ],
+ "github-repo-to-launch-deck": [
+ "github-launch-announcement",
+ "github-repo-launch-demand-map",
+ "repository-launch-package-pilot",
+ ],
+ "github-repo-to-product-outreach": [
+ "repository-launch-package-pilot",
+ "github-repo-launch-demand-map",
+ "source-backed-launch-assets",
+ ],
+ "github-repo-launch-readiness-score": [
+ "repository-launch-package-pilot",
+ "cold-start-launch-materials",
+ "open-source-launch-checklist",
+ ],
+ "qwenlm-flashqla-launch-card": [
+ "github-repo-visual-explainer",
+ "github-project-marketing-card-guide",
+ "github-repo-to-launch-package",
+ ],
+ "deepseek-twvp-launch-card": [
+ "github-repo-visual-explainer",
+ "source-backed-launch-assets",
+ "ai-project-launch",
+ ],
+ "chatgpt-open-source-launch-copy": [
+ "source-backed-launch-assets",
+ "qwenlm-flashqla-launch-card",
+ "github-repo-to-launch-package",
+ ],
+ "canva-readme-banner-generator": [
+ "readme-marketing-cards",
+ "readme-cover-prompt-guide",
+ "qwenlm-flashqla-launch-card",
+ ],
+};
+
+function getMarketingParentLabel(pageType: MarketingPageType) {
+ const parentLabels: Record = {
+ product: "Product",
+ use_case: "Use Cases",
+ resource: "Resources",
+ tool: "Tools",
+ template: "Templates",
+ example: "Examples",
+ compare: "Compare",
+ contact: "Contact",
+ };
+
+ return parentLabels[pageType];
+}
+
+function getMarketingBreadcrumbLabel(link: MarketingLink) {
+ return getMarketingPageTitle(link).replace(/\s+\|\s+QuickFork$/, "");
+}
+
function getResourceType(link: MarketingLink) {
if (link.slug.includes("checklist")) return "checklist";
if (link.slug.includes("template") || link.slug.includes("prompt")) return "template";
diff --git a/src/styles/app.css b/src/styles/app.css
index 9edfa3c..6b1961e 100644
--- a/src/styles/app.css
+++ b/src/styles/app.css
@@ -142,6 +142,11 @@ blockquote {
position: relative;
}
+.productNavItem:last-of-type .productMenu {
+ right: 0;
+ left: auto;
+}
+
.navLink {
min-height: 36px;
display: inline-flex;
@@ -174,6 +179,12 @@ blockquote {
padding-inline: 12px;
}
+.navBriefLink {
+ border-color: var(--dark);
+ color: #ffffff;
+ background: var(--dark);
+}
+
.productChevron {
transition: transform 160ms ease;
}
@@ -189,6 +200,13 @@ blockquote {
outline-offset: 2px;
}
+.navBriefLink:hover,
+.navBriefLink:focus-visible {
+ border-color: var(--dark);
+ color: #ffffff;
+ background: #191936;
+}
+
.productNavItem:hover .productChevron,
.productNavItem:focus-within .productChevron {
transform: rotate(180deg);
@@ -2331,13 +2349,12 @@ blockquote {
}
.footer {
- min-height: 112px;
border-top: 1px solid var(--border);
display: grid;
- grid-template-columns: minmax(0, 1fr) auto;
- align-items: center;
- justify-content: space-between;
- gap: 24px;
+ grid-template-columns: minmax(220px, 0.7fr) minmax(0, 1.7fr);
+ align-items: start;
+ gap: 32px;
+ padding: 34px 0;
color: var(--muted);
font-size: 11px;
font-weight: 650;
@@ -2363,27 +2380,49 @@ blockquote {
}
.footerNav {
- display: flex;
- flex-wrap: wrap;
- justify-content: flex-end;
- gap: 8px;
+ display: grid;
+ grid-template-columns: repeat(3, minmax(140px, 1fr));
+ gap: 22px 20px;
+}
+
+.footerGroup {
+ display: grid;
+ gap: 10px;
+ align-content: start;
+}
+
+.footerGroup h2 {
+ color: var(--fg);
+ font: 700 12px/1 var(--font-mono);
+ letter-spacing: 0;
+ text-transform: uppercase;
+}
+
+.footerGroup div {
+ display: grid;
+ gap: 6px;
}
.footerNav a {
- min-height: 38px;
+ min-height: 28px;
border: 1px solid transparent;
border-radius: 4px;
display: inline-flex;
align-items: center;
- padding: 0 10px;
+ justify-self: start;
+ padding: 0;
color: var(--muted);
+ font-size: 13px;
+ font-weight: 550;
+ line-height: 1.25;
+ text-transform: none;
}
.footerNav a:hover,
.footerNav a:focus-visible {
- border-color: var(--border);
color: var(--fg);
- background: #ffffff;
+ text-decoration: underline;
+ text-underline-offset: 3px;
}
.secondaryHero,
@@ -2500,6 +2539,7 @@ blockquote {
}
.marketingHeroSection,
+.marketingBreadcrumbs,
.marketingBodySection,
.marketingGrowthSection,
.marketingCaptureSection,
@@ -2508,8 +2548,36 @@ blockquote {
margin: 0 auto;
}
+.marketingBreadcrumbs {
+ padding-top: 34px;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ align-items: center;
+ color: var(--muted);
+ font: 650 12px/1.4 var(--font-mono);
+ text-transform: uppercase;
+}
+
+.marketingBreadcrumbs a {
+ color: var(--fg);
+}
+
+.marketingBreadcrumbs a:hover,
+.marketingBreadcrumbs a:focus-visible {
+ text-decoration: underline;
+ text-underline-offset: 3px;
+}
+
+.marketingBreadcrumbs span[aria-current="page"] {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ color: var(--fg);
+ white-space: nowrap;
+}
+
.marketingHeroSection {
- padding: 92px 0 64px;
+ padding: 44px 0 64px;
}
.marketingHeroGrid {
@@ -3261,6 +3329,7 @@ blockquote {
.studioSection,
.closing,
.marketingHeroSection,
+ .marketingBreadcrumbs,
.marketingBodySection,
.marketingGrowthSection,
.marketingCaptureSection,
@@ -3285,7 +3354,8 @@ blockquote {
justify-self: start;
width: 100%;
gap: 8px;
- overflow: visible;
+ overflow-x: auto;
+ scrollbar-width: none;
}
.productNavItem {
@@ -3503,6 +3573,17 @@ blockquote {
}
.footerNav {
- justify-content: flex-start;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ width: 100%;
+ }
+}
+
+@media (max-width: 520px) {
+ .footerNav {
+ grid-template-columns: 1fr;
+ }
+
+ .marketingBreadcrumbs span[aria-current="page"] {
+ white-space: normal;
}
}