cross-link: forum auto-link, NAB hub, sponsor strip, recent stories
Feature 3 — forum auto-linking
Thread + reply bodies in /forum/thread/[id] now wrap company-name
mentions with /manufacturers/<slug> links via a new client-side
LinkifyPlainText component. Loads the directory list once per page
(module-level promise cache), regex-scans each body, preserves
whitespace, caps at 10 links per body to avoid clutter.
CompanyMentionsHover mounted on the page so the same preview card
pops on hover.
Adds /api/public/companies/list — minimal { name, slug } directory
feed, cached 10min.
Feature 4 — /nab-2026 live coverage hub
New page aggregating every directory company with exhibits_nab=true.
Three sections:
- Coverage Partners — active advertisers exhibiting at NAB, larger
tiles with emerald Sponsor border
- Latest from the show floor — last 60 days of articles with NAB
in the title, cinematic grid
- All NAB 2026 exhibitors — alphabetical, capped at 200 with link
to full /manufacturers directory
Every company tile carries data-company-slug for hover previews.
Feature 5b — Sponsor logo strip on homepage
New SponsorLogoStrip server component renders just above the footer
on the homepage, showing logos of every current banner advertiser
with a directory entry + logo. Each links to the manufacturer
profile with the hover-card slug attribute.
Feature 5c — Recent coverage on manufacturer profiles
/manufacturers/[slug] now includes a grid of the 6 most recent
articles matching the company name in the title, with thumbnails.
Renames the existing manufacturer_id-linked block to "Press
releases" since it's a separate data source.
This commit is contained in:
29
src/app/api/public/companies/list/route.ts
Normal file
29
src/app/api/public/companies/list/route.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { createAdminClient } from "@/lib/supabase/admin";
|
||||
|
||||
// Cache aggressively — directory rarely changes, and 1k+ companies is ~50KB.
|
||||
export const revalidate = 600;
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const svc = createAdminClient();
|
||||
const { data } = await svc
|
||||
.from("tracked_companies")
|
||||
.select("company_name, slug")
|
||||
.eq("directory_visible", true)
|
||||
.not("slug", "is", null)
|
||||
.not("company_name", "is", null);
|
||||
|
||||
const rows = (data || [])
|
||||
.filter((r: any) => r.company_name && r.slug)
|
||||
.map((r: any) => ({ name: String(r.company_name).trim(), slug: String(r.slug) }))
|
||||
.filter((r) => r.name.length >= 3);
|
||||
|
||||
return NextResponse.json(
|
||||
{ companies: rows },
|
||||
{ headers: { "Cache-Control": "public, s-maxage=600, stale-while-revalidate=1200" } },
|
||||
);
|
||||
} catch (e: any) {
|
||||
return NextResponse.json({ companies: [], error: e?.message || "error" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user