Skip to content

Commit 02c1988

Browse files
ikhareConvex, Inc.
authored andcommitted
Make the docs home page a little cleaner (#34310)
* Encourage folks to see the new overview docs * Use more current language to describe Convex * Remove the YouTube embeds and make them links * Clean up card styling a bit GitOrigin-RevId: b726a0dbd05bfb1c5479167a3594bd5c2c2abaeb
1 parent cc1fc95 commit 02c1988

File tree

4 files changed

+190
-96
lines changed

4 files changed

+190
-96
lines changed

npm-packages/docs/docs/home.mdx

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,32 @@ hide_table_of_contents: true
66

77
import TutorialGraphic from "@site/static/img/tutorial-graphic.svg";
88
import { QuickstartsList } from "@site/src/QuickstartsList.tsx";
9+
import { LargeCardList } from "@site/src/QuickstartsList.tsx";
910
import { YouTubeList } from "@site/src/YouTubeLink.tsx";
11+
import Link from "@docusaurus/Link";
1012

11-
<span className="convex-hero">
12-
Convex is an all-in-one backend platform with thoughtful, product-centric
13-
APIs.
14-
</span>
15-
<span className="convex-hero">
16-
Use [TypeScript](understanding/best-practices/typescript) to write [queries as
17-
code](functions/query-functions) that are [automatically
18-
cached](realtime#automatic-caching) and [realtime](realtime), with an acid
19-
compliant [relational database](database).
20-
</span>
21-
22-
<CardLink
23-
className="convex-hero-card"
24-
item={{
25-
icon: <TutorialGraphic height={40} />,
26-
href: "/tutorial",
27-
docId: "tutorial/index",
28-
label: "Learn Convex by creating a chat app",
29-
}}
13+
Convex is the open source, reactive database where queries are TypeScript code
14+
running right in the database. Just like React components react to state
15+
changes, Convex queries react to database changes.
16+
17+
Convex provides a database, a place to write your server functions, and client
18+
libraries. It makes it easy to build and scale dynamic live-updating apps.
19+
20+
<LargeCardList
21+
items={[
22+
{
23+
title: "Tutorial: Build a chat app",
24+
description:
25+
"Follow a step-by-step tutorial to build your first Convex app - a real-time chat application.",
26+
href: "/tutorial",
27+
},
28+
{
29+
title: "Understanding Convex",
30+
description:
31+
"Learn about the core concepts and architecture that make Convex unique and powerful.",
32+
href: "/understanding",
33+
},
34+
]}
3035
/>
3136

3237
## Quickstarts
@@ -41,7 +46,7 @@ Quickly get up and running with your favorite frontend tooling or language:
4146
items={[
4247
{
4348
src: "https://www.youtube.com/embed/Xjud1weG4z8?si=OMMfKzK_Dp8RgmgM",
44-
label: "Backends Should be Designed for Product Developers",
49+
label: "Backends for Product Developers",
4550
},
4651
{
4752
src: "https://www.youtube.com/embed/UVvd7BF99-4?si=Z9_pLHMnpL9kaduE",
@@ -73,26 +78,11 @@ Read the team's Perspectives on [Stack](https://stack.convex.dev):
7378
href: "https://stack.convex.dev/convex-vs-firebase",
7479
label: "Convex vs Firebase",
7580
},
76-
{
77-
type: "link",
78-
href: "https://stack.convex.dev/not-sql",
79-
label: "It's not you, it's SQL",
80-
},
8181
{
8282
type: "link",
8383
href: "https://stack.convex.dev/how-convex-works",
8484
label: "How Convex Works",
8585
},
86-
{
87-
type: "link",
88-
href: "https://stack.convex.dev/the-software-defined-database",
89-
label: "The Software-Defined Database",
90-
},
91-
{
92-
type: "link",
93-
href: "https://stack.convex.dev/tag/Perspectives",
94-
label: "Convex Perspectives",
95-
},
9686
]}
9787
/>
9888

@@ -102,15 +92,15 @@ Read the team's Perspectives on [Stack](https://stack.convex.dev):
10292
items={[
10393
{
10494
src: "https://www.youtube.com/embed/vaQZYRSiimI?si=JLfdVVs3QkCLTZwc",
105-
label: "A quick start guide for using Convex with Next.js",
95+
label: "Convex with Next.js Quickstart",
10696
},
10797
{
10898
src: "https://www.youtube.com/embed/0OaDyjB9Ib8?si=V5_9FN3UieZmnOM5",
109-
label: "Fullstack Notion Clone: Next.js 13, React, Convex, Tailwind",
99+
label: "Notion Clone: Next.js 13, React, Convex, Tailwind",
110100
},
111101
{
112102
src: "https://www.youtube.com/embed/zfAb95tJvZQ?si=PaiBxNxCO0s2BuEZ",
113-
label: "Build and Deploy a Saas Podcast Platform in Next.js",
103+
label: "Build a Saas Podcast Platform in Next.js",
114104
},
115105
{
116106
src: "https://www.youtube.com/embed/Vjtn9pWAZDI?si=of21uqly5laJQJAs",

npm-packages/docs/src/QuickstartsList.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
declare module "*.svg" {
2+
const content: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
3+
export default content;
4+
}
5+
16
import ExpoLogo from "@site/static/img/expo-logo.svg";
27
import NextJSLogo from "@site/static/img/nextjs-logo.svg";
38
import HtmlLogo from "@site/static/img/html-logo.svg";
@@ -26,6 +31,13 @@ type Item = {
2631
invertIcon?: true;
2732
};
2833

34+
// Add this new type after the existing Item type
35+
type LargeCardItem = {
36+
href: string;
37+
title: string;
38+
description: string;
39+
};
40+
2941
export function DocCardList(props: { items: Item[] }) {
3042
const { items } = props;
3143
return (
@@ -64,6 +76,21 @@ export function CardLink({
6476
</Link>
6577
);
6678
}
79+
80+
// Add this new component before QuickstartsList
81+
export function LargeCardList(props: { items: LargeCardItem[] }) {
82+
return (
83+
<div className="large-cards">
84+
{props.items.map((item, index) => (
85+
<Link key={index} href={item.href} className="large-card">
86+
<Heading as="h2">{item.title}</Heading>
87+
<p>{item.description}</p>
88+
</Link>
89+
))}
90+
</div>
91+
);
92+
}
93+
6794
// End DocsCardList.tsx variant for Quickstarts page
6895

6996
export function QuickstartsList() {
Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,37 @@
11
import React from "react";
22

3-
type Item = {
4-
src: string;
5-
label: string;
6-
};
7-
8-
export function YouTubeList(props: { items: Item[] }) {
9-
const { items } = props;
10-
3+
function PlayIcon(props: React.SVGProps<SVGSVGElement>) {
114
return (
12-
<div className="youtube-list">
13-
{items.map((item, index) => (
14-
<YouTubeEmbed key={index} item={item} />
15-
))}
16-
</div>
5+
<svg viewBox="0 0 24 24" fill="currentColor" {...props}>
6+
<path d="M8 5v14l11-7z" />
7+
</svg>
178
);
189
}
1910

20-
function YouTubeEmbed(props: { item: Item }) {
21-
const { item } = props;
11+
type YouTubeItem = {
12+
src: string;
13+
label: string;
14+
};
15+
16+
export function YouTubeList({ items }: { items: YouTubeItem[] }) {
2217
return (
23-
<div className="youtube-item">
24-
<iframe
25-
className="youtube-video"
26-
src={item.src}
27-
title="YouTube video player"
28-
frameBorder="0"
29-
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
30-
referrerPolicy="strict-origin-when-cross-origin"
31-
allowFullScreen
32-
></iframe>
33-
<h2>{item.label}</h2>
18+
<div className="video-cards">
19+
{items.map((item) => {
20+
// Extract video ID from src URL
21+
const videoId = item.src.split("/").pop()?.split("?")[0];
22+
return (
23+
<a
24+
key={item.label}
25+
href={`https://www.youtube.com/watch?v=${videoId}`}
26+
target="_blank"
27+
rel="noopener noreferrer"
28+
className="video-card"
29+
>
30+
<PlayIcon className="play-icon h-8 w-8" />
31+
<h2>{item.label}</h2>
32+
</a>
33+
);
34+
})}
3435
</div>
3536
);
3637
}

npm-packages/docs/src/css/custom.css

Lines changed: 108 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ article .markdown a {
281281
color var(--ifm-transition-fast) var(--ifm-transition-timing-default),
282282
text-decoration-color var(--ifm-transition-fast)
283283
var(--ifm-transition-timing-default);
284+
text-underline-position: under;
284285
text-decoration-thickness: 1px;
285286
}
286287

@@ -319,37 +320,6 @@ article code {
319320
background-color: var(--convex-code-block-header-background-color);
320321
}
321322

322-
/* START: Youtube video list */
323-
.youtube-list {
324-
display: grid;
325-
gap: 1.25rem;
326-
margin: 0 0 2em;
327-
}
328-
329-
.youtube-list .youtube-item h2 {
330-
font-family: var(--ifm-font-family-base);
331-
font-weight: 600;
332-
font-size: 1rem;
333-
letter-spacing: normal;
334-
335-
height: 2em;
336-
line-height: 1.5em;
337-
}
338-
339-
.youtube-list .youtube-video {
340-
aspect-ratio: 16 / 9;
341-
width: 100%;
342-
border-radius: var(--ifm-code-border-radius);
343-
}
344-
345-
/* This magic number 743 is the size of the article div container as rendered */
346-
@container (width > 743px) {
347-
.youtube-list {
348-
grid-template-columns: 1fr 1fr;
349-
}
350-
}
351-
/* END: YouTube video list */
352-
353323
/* START: Custom cards implementation */
354324
.cards {
355325
display: grid;
@@ -399,6 +369,8 @@ a.card {
399369
gap: 1rem;
400370
align-items: center;
401371
max-width: 550px;
372+
text-decoration: none;
373+
background-color: var(--ifm-background-color);
402374
}
403375

404376
.qs-cards a.card {
@@ -415,8 +387,9 @@ a.card svg {
415387

416388
a.card:hover {
417389
box-shadow: none;
418-
border-color: var(--ifm-font-color-base);
390+
background-color: var(--ifm-menu-color-background-active);
419391
color: var(--ifm-font-color-base);
392+
text-decoration: none;
420393
}
421394

422395
a.card h2 {
@@ -1282,3 +1255,106 @@ html[data-theme="dark"] .StackPosts-title-image--dark {
12821255
.StackPosts-post-content-author-name {
12831256
font-size: 0.875rem;
12841257
}
1258+
1259+
/* START: Large cards implementation */
1260+
.large-cards {
1261+
display: grid;
1262+
gap: 1.25rem;
1263+
margin: 2rem 0 3rem;
1264+
}
1265+
1266+
@container (width > 743px) {
1267+
.large-cards {
1268+
grid-template-columns: 1fr 1fr;
1269+
}
1270+
}
1271+
1272+
a.large-card {
1273+
box-shadow: none;
1274+
padding: 1.5rem;
1275+
border: 1px solid var(--ifm-toc-border-color);
1276+
border-radius: var(--ifm-card-border-radius);
1277+
display: flex;
1278+
flex-direction: column;
1279+
justify-content: center;
1280+
gap: 0.5rem;
1281+
height: 100%;
1282+
min-height: 150px;
1283+
text-decoration: none;
1284+
background-color: var(--ifm-background-color);
1285+
}
1286+
1287+
a.large-card:hover {
1288+
box-shadow: none;
1289+
background-color: var(--ifm-menu-color-background-active);
1290+
color: var(--ifm-font-color-base);
1291+
text-decoration: none;
1292+
}
1293+
1294+
a.large-card h2 {
1295+
font-size: 1.25rem;
1296+
margin: 0;
1297+
}
1298+
1299+
a.large-card p {
1300+
font-size: 1rem;
1301+
margin: 0;
1302+
color: var(--ifm-color-emphasis-700);
1303+
line-height: 1.5;
1304+
}
1305+
1306+
/* END: Large cards implementation */
1307+
1308+
/* Video link cards */
1309+
.video-cards {
1310+
display: grid;
1311+
gap: 1.25rem;
1312+
margin: 2rem 0 3rem;
1313+
grid-template-columns: repeat(1, minmax(0, 1fr));
1314+
}
1315+
1316+
@media (min-width: 997px) {
1317+
.video-cards {
1318+
grid-template-columns: repeat(3, minmax(0, 1fr));
1319+
}
1320+
}
1321+
1322+
a.video-card {
1323+
box-shadow: none;
1324+
padding: 1.5rem;
1325+
border: 1px solid var(--ifm-toc-border-color);
1326+
border-radius: var(--ifm-card-border-radius);
1327+
display: flex;
1328+
gap: 1rem;
1329+
align-items: center;
1330+
text-decoration: none;
1331+
background-color: var(--ifm-background-color);
1332+
}
1333+
1334+
a.video-card:hover {
1335+
box-shadow: none;
1336+
background-color: var(--ifm-menu-color-background-active);
1337+
color: var(--ifm-font-color-base);
1338+
text-decoration: none;
1339+
}
1340+
1341+
a.video-card .play-icon {
1342+
color: var(--ifm-font-color-base);
1343+
flex-shrink: 0;
1344+
}
1345+
1346+
a.video-card h2 {
1347+
font-size: 1rem;
1348+
margin-bottom: 0;
1349+
overflow: hidden;
1350+
text-overflow: ellipsis;
1351+
display: -webkit-box;
1352+
-webkit-line-clamp: 2;
1353+
line-clamp: 2;
1354+
-webkit-box-orient: vertical;
1355+
white-space: normal;
1356+
font-weight: 400;
1357+
font-family: var(--ifm-font-family-base);
1358+
letter-spacing: normal;
1359+
max-height: 2.4em;
1360+
}

0 commit comments

Comments
 (0)