diff --git a/apps/marketing/content/people/avi.mdx b/apps/marketing/content/people/avi.mdx index dcef90f18a2..1f63103c4b7 100644 --- a/apps/marketing/content/people/avi.mdx +++ b/apps/marketing/content/people/avi.mdx @@ -1,6 +1,7 @@ --- name: Avi Peltz role: Cofounder +bio: Ex-CTO at Adam (YC W25). Previously founded BioGlyph, computer vision research. Builds robots. avatar: /team/avi.jpg twitter: avimakesrobots github: avipeltz diff --git a/apps/marketing/content/people/kiet.mdx b/apps/marketing/content/people/kiet.mdx index 692c733a1d0..b9aa038b1c4 100644 --- a/apps/marketing/content/people/kiet.mdx +++ b/apps/marketing/content/people/kiet.mdx @@ -1,6 +1,7 @@ --- name: Kiet Ho role: Cofounder +bio: Ex-CTO at Onlook (YC W25). Previously at Amazon and ServiceNow. Trains fighting. avatar: /team/kiet.jpg twitter: kietho_ github: kietho diff --git a/apps/marketing/content/people/satya.mdx b/apps/marketing/content/people/satya.mdx index 84cb3592e8c..762e27f5a9e 100644 --- a/apps/marketing/content/people/satya.mdx +++ b/apps/marketing/content/people/satya.mdx @@ -1,7 +1,8 @@ --- name: Satya Patel role: Cofounder -avatar: /team/satya.webp +bio: Ex-CTO at Untether Labs (YC W23). Previously at Scribe, Google, Amazon, and Facebook. Lifts heavy. +avatar: /team/satya.jpeg twitter: saddle_paddle github: saddlepaddle linkedin: saddlepaddle diff --git a/apps/marketing/next.config.ts b/apps/marketing/next.config.ts index 12025d8b7ef..1a43b1aa439 100644 --- a/apps/marketing/next.config.ts +++ b/apps/marketing/next.config.ts @@ -51,6 +51,11 @@ const config: NextConfig = { const docsUrl = process.env.NEXT_PUBLIC_DOCS_URL || "https://docs.superset.sh"; return [ + { + source: "/about", + destination: "/team", + permanent: true, + }, { source: "/docs/:path*", destination: `${docsUrl}/:path*`, diff --git a/apps/marketing/public/team/avi.jpg b/apps/marketing/public/team/avi.jpg index da475f589fd..6fc483a5276 100644 Binary files a/apps/marketing/public/team/avi.jpg and b/apps/marketing/public/team/avi.jpg differ diff --git a/apps/marketing/public/team/satya.jpeg b/apps/marketing/public/team/satya.jpeg new file mode 100644 index 00000000000..7c86f83a7b2 Binary files /dev/null and b/apps/marketing/public/team/satya.jpeg differ diff --git a/apps/marketing/src/app/components/Footer/Footer.tsx b/apps/marketing/src/app/components/Footer/Footer.tsx index 61765944821..077f651fb00 100644 --- a/apps/marketing/src/app/components/Footer/Footer.tsx +++ b/apps/marketing/src/app/components/Footer/Footer.tsx @@ -51,6 +51,12 @@ export function Footer() { > Docs + + About +
diff --git a/apps/marketing/src/app/sitemap.ts b/apps/marketing/src/app/sitemap.ts index 57bf9fecca7..b97ea463ec2 100644 --- a/apps/marketing/src/app/sitemap.ts +++ b/apps/marketing/src/app/sitemap.ts @@ -2,6 +2,7 @@ import { COMPANY } from "@superset/shared/constants"; import type { MetadataRoute } from "next"; import { getBlogPosts } from "@/lib/blog"; import { getChangelogEntries } from "@/lib/changelog"; +import { getAllPeople } from "@/lib/people"; import { getComparisonPages } from "@/lib/compare"; export default function sitemap(): MetadataRoute.Sitemap { @@ -26,6 +27,12 @@ export default function sitemap(): MetadataRoute.Sitemap { changeFrequency: "weekly", priority: 0.9, }, + { + url: `${baseUrl}/team`, + lastModified: new Date(), + changeFrequency: "monthly", + priority: 0.8, + }, { url: `${baseUrl}/community`, lastModified: new Date(), @@ -64,6 +71,14 @@ export default function sitemap(): MetadataRoute.Sitemap { }), ); + const people = getAllPeople(); + const teamPages: MetadataRoute.Sitemap = people.map((person) => ({ + url: `${baseUrl}/team/${person.id}`, + lastModified: new Date(), + changeFrequency: "monthly" as const, + priority: 0.7, + })); + const comparisonPages: MetadataRoute.Sitemap = getComparisonPages().map( (page) => ({ url: `${baseUrl}/compare/${page.slug}`, @@ -73,5 +88,5 @@ export default function sitemap(): MetadataRoute.Sitemap { }), ); - return [...staticPages, ...blogPages, ...changelogPages, ...comparisonPages]; + return [...staticPages, ...blogPages, ...changelogPages, ...teamPages, ...comparisonPages]; } diff --git a/apps/marketing/src/app/team/[id]/page.tsx b/apps/marketing/src/app/team/[id]/page.tsx new file mode 100644 index 00000000000..6041b4d757a --- /dev/null +++ b/apps/marketing/src/app/team/[id]/page.tsx @@ -0,0 +1,331 @@ +import { COMPANY } from "@superset/shared/constants"; +import { ArrowLeft } from "lucide-react"; +import type { Metadata } from "next"; +import Image from "next/image"; +import Link from "next/link"; +import { notFound } from "next/navigation"; +import { MDXRemote } from "next-mdx-remote/rsc"; +import { + RiGithubFill, + RiLinkedinBoxFill, + RiTwitterXFill, +} from "react-icons/ri"; +import { GridCross } from "@/app/blog/components/GridCross"; +import { mdxComponents } from "@/app/blog/components/mdx-components"; +import { BreadcrumbJsonLd } from "@/components/JsonLd"; +import { getAllPeople, getPersonById } from "@/lib/people"; + +interface PageProps { + params: Promise<{ id: string }>; +} + +function PersonJsonLd({ + person, + url, +}: { + person: { + name: string; + role: string; + avatar?: string; + twitter?: string; + github?: string; + linkedin?: string; + }; + url: string; +}) { + const sameAs: string[] = []; + if (person.twitter) sameAs.push(`https://x.com/${person.twitter}`); + if (person.github) sameAs.push(`https://github.com/${person.github}`); + if (person.linkedin) + sameAs.push(`https://linkedin.com/in/${person.linkedin}`); + + const schema = { + "@context": "https://schema.org", + "@type": "Person", + name: person.name, + jobTitle: person.role, + url, + worksFor: { + "@type": "Organization", + name: COMPANY.NAME, + url: COMPANY.MARKETING_URL, + }, + ...(person.avatar && { + image: `${COMPANY.MARKETING_URL}${person.avatar}`, + }), + ...(sameAs.length > 0 && { sameAs }), + }; + + return ( + + ); +} + +export default async function TeamMemberPage({ params }: PageProps) { + const { id } = await params; + const person = getPersonById(id); + + if (!person) { + notFound(); + } + + const allPeople = getAllPeople(); + const otherMembers = allPeople.filter((p) => p.id !== id); + const url = `${COMPANY.MARKETING_URL}/team/${id}`; + const hasContent = person.content.trim().length > 0; + + const initials = person.name + .split(" ") + .map((n) => n[0]) + .join("") + .toUpperCase() + .slice(0, 2); + + return ( ++ {person.bio} +
+ )} + +
+ Superset is built by a team of 3 ex YC CTOs. We want to create the best team that has fun working together.
+
+ Success will be a lagging indicator.
+
No team members yet.
+ ) : ( +