Compare commits

...

1 Commits

Author SHA1 Message Date
Anselm
13c844f63b Move features up and start shortening them even more 2024-10-10 10:46:21 +01:00
6 changed files with 205 additions and 201 deletions

View File

@@ -0,0 +1,29 @@
import clsx from "clsx";
import { ReactNode } from "react";
import { H2 } from "../atoms/Headings";
import { twMerge } from "tailwind-merge";
export function FeatureGrid({
children,
className,
title,
}: {
children: ReactNode;
className?: string;
title?: string;
}) {
return (
<div
className={twMerge(
clsx(
"grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-4",
"items-stretch",
className,
),
)}
>
{title && <H2 className="col-span-full">{title}</H2>}
{children}
</div>
);
}

View File

@@ -1,26 +0,0 @@
import clsx from "clsx";
import { ReactNode } from "react";
import { H2 } from "../../components/atoms/Headings";
export function GappedGrid({
children,
className,
title
}: {
children: ReactNode;
className?: string;
title?: string;
}) {
return (
<div
className={clsx(
"grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-4",
"items-stretch",
className
)}
>
{title && <H2 className="col-span-full">{title}</H2>}
{children}
</div>
);
}

View File

@@ -13,16 +13,16 @@ export function LabelledFeatureIcon({
return (
<div
className={clsx(
"p-4 flex flex-col gap-3",
"py-5 flex flex-col gap-3",
"not-prose text-base",
"border border-stone-200 dark:border-stone-900 rounded-xl"
// "border border-stone-200 dark:border-stone-900 rounded-xl"
)}
>
<div>
<Icon className="text-stone-500" strokeWidth={1} strokeLinecap="butt" size={40} />
</div>
<div className="text-stone-900 font-medium md:text-base dark:text-stone-100">
{label}
<div className="flex items-center gap-2">
<Icon className="text-stone-900 dark:text-stone-100" strokeWidth={1.5} strokeLinecap="butt" size={25} />
<div className="text-stone-900 text-base md:text-lg dark:text-stone-100">
{label}
</div>
</div>
<div className="leading-relaxed space-y-3 text-sm">
{explanation}

View File

@@ -5,7 +5,7 @@ import {
} from "gcmp-design-system/src/app/components/molecules/Prose";
import { SectionHeader } from "gcmp-design-system/src/app/components/molecules/SectionHeader";
import { HairlineBleedGrid } from "gcmp-design-system/src/app/components/molecules/HairlineGrid";
import { GappedGrid } from "gcmp-design-system/src/app/components/molecules/GappedGrid";
import { FeatureGrid } from "gcmp-design-system/src/app/components/molecules/FeatureGrid";
import { LabelledFeatureIcon } from "gcmp-design-system/src/app/components/molecules/LabelledFeatureIcon";
import { GridCard } from "gcmp-design-system/src/app/components/atoms/GridCard";
import { CodeRef } from "gcmp-design-system/src/app/components/atoms/CodeRef";
@@ -91,15 +91,158 @@ export default function Home() {
Build your next&nbsp;app with sync.
</h1>
<p className="text-lg text-pretty leading-relaxed max-w-3xl dark:text-stone-200 md:text-xl">
Jazz is an open-source framework for building local-first
apps, removing 90% of the backend and infrastructure
complexity. Get real-time sync, storage, auth, permissions,
instant UI updates, file uploads, and more &mdash; all on
day one.
<p className="text-lg leading-relaxed max-w-3xl dark:text-stone-200 md:text-xl text-balance">
Jazz is an open-source framework for building local-first apps, removing 90% of the backend and
infrastructure complexity.
</p>
<div className="flex flex-col gap-4 md:gap-6 mt-16">
<SectionHeader
title="Everything you need to ship top-tier apps quickly."
slogan="Get features that used to take months to build on day one."
/>
<FeatureGrid className="md:grid-cols-3 lg:grid-cols-4">
<LabelledFeatureIcon
label="Local-first data"
icon={HardDriveDownloadIcon}
explanation={
<>
<p>
All data you load or create is persisted
locally, so your users can work offline.
</p>
{/* <p>
When youre back online, your local
changes are synced to the server.
</p> */}
</>
}
/>
<LabelledFeatureIcon
label="Cross-device sync"
icon={MonitorSmartphoneIcon}
explanation={
<>
<p>
Build your app around mutable local
state attached to an account.
</p>
{/* <p>
Every device with the same account will
always have everything in sync.
</p> */}
</>
}
/>
<LabelledFeatureIcon
label="Real-time multiplayer"
icon={MousePointerSquareDashedIcon}
explanation={
<>
<p>
Share state with other users and get
automatic real-time multiplayer.
</p>
{/* <p>
Use the same primitives to quickly build
user presence UI, like cursors.
</p> */}
</>
}
/>
<LabelledFeatureIcon
label="Teams & social features"
icon={UsersIcon}
explanation={
<>
<p>
Groups of accounts are first class
entities that you can create anywhere.
</p>
{/* <p>
Building multi-user apps becomes as easy
as building the UI for them.
</p> */}
</>
}
/>
<LabelledFeatureIcon
label="Built-in permissions"
icon={FileLock2Icon}
explanation={
<>
<p>
Control access to data with role-based
permissions, easily defined locally.
</p>
{/* <p>
Reference data across permission scopes
for granular access control.
</p> */}
</>
}
/>
<LabelledFeatureIcon
label="Data & blob storage"
icon={UploadCloudIcon}
explanation={
<>
<p>
Create & handle structured data and
binary streams/blobs the same way.
</p>
{/* <p>
<Link
className="underline"
href="/mesh"
>
Jazz Mesh
</Link>{" "}
or your own server become both cloud
database and blob storage.
</p> */}
</>
}
/>
<LabelledFeatureIcon
label="Instant UI updates"
icon={GaugeIcon}
explanation={
<>
<p>
Get instant updates throughout your UI
every time you locally mutate data.
</p>
{/* <p>
Remote changes are synced and applied
with minimal latency.
</p> */}
</>
}
/>
<LabelledFeatureIcon
label="E2EE & signatures"
icon={KeyRoundIcon}
explanation={
<>
<p>
All data is end-to-end encrypted and
cryptographically signed by default.
</p>
{/* <p>
So it cant be tampered with and Jazz
Mesh only sees encrypted data.
</p> */}
</>
}
/>
</FeatureGrid>
</div>
</div>
<div className="bg-stone-100 dark:bg-stone-925 py-8 lg:py-16">
<div className="container grid gap-8 lg:gap-12">
<h2 className="font-display md:text-center text-stone-950 dark:text-white text-2xl md:text-3xl font-semibold tracking-tight">
@@ -185,149 +328,7 @@ export default function Home() {
</div>
<div className="container flex flex-col gap-8 py-8 lg:gap-20 lg:py-20">
<div className="flex flex-col gap-4 md:gap-6">
<SectionHeader
title="Everything you need to ship top-tier apps quickly."
slogan="Features that used to take months to build now work out-of-the-box."
/>
<HairlineBleedGrid>
<LabelledFeatureIcon
label="Local-first storage"
icon={HardDriveDownloadIcon}
explanation={
<>
<p>
All data you load or create is persisted
locally, so your users can work offline.
</p>
<p>
When youre back online, your local
changes are synced to the server.
</p>
</>
}
/>
<LabelledFeatureIcon
label="Cross-device sync"
icon={MonitorSmartphoneIcon}
explanation={
<>
<p>
Build your app around mutable local
state attached to an account.
</p>
<p>
Every device with the same account will
always have everything in sync.
</p>
</>
}
/>
<LabelledFeatureIcon
label="Real-time multiplayer"
icon={MousePointerSquareDashedIcon}
explanation={
<>
<p>
Share state with other users and get
automatic real-time multiplayer.
</p>
<p>
Use the same primitives to quickly build
user presence UI, like cursors.
</p>
</>
}
/>
<LabelledFeatureIcon
label="Teams & social features"
icon={UsersIcon}
explanation={
<>
<p>
Groups of accounts are first class
entities that you can create anywhere.
</p>
<p>
Building multi-user apps becomes as easy
as building the UI for them.
</p>
</>
}
/>
<LabelledFeatureIcon
label="Built-in permissions"
icon={FileLock2Icon}
explanation={
<>
<p>
Control access to data with role-based
permissions, easily defined locally.
</p>
<p>
Reference data across permission scopes
for granular access control.
</p>
</>
}
/>
<LabelledFeatureIcon
label="Data & blob storage"
icon={UploadCloudIcon}
explanation={
<>
<p>
Create & handle structured data and
binary streams/blobs the same way.
</p>
<p>
<Link
className="underline"
href="/mesh"
>
Jazz Mesh
</Link>{" "}
or your own server become both cloud
database and blob storage.
</p>
</>
}
/>
<LabelledFeatureIcon
label="Instant UI updates"
icon={GaugeIcon}
explanation={
<>
<p>
Get instant updates throughout your UI
every time you locally mutate data.
</p>
<p>
Remote changes are synced and applied
with minimal latency.
</p>
</>
}
/>
<LabelledFeatureIcon
label="E2EE & signatures"
icon={KeyRoundIcon}
explanation={
<>
<p>
All data is end-to-end encrypted and
cryptographically signed by default.
</p>
<p>
So it cant be tampered with and Jazz
Mesh only sees encrypted data.
</p>
</>
}
/>
</HairlineBleedGrid>
</div>
<div>
<SectionHeader
@@ -402,7 +403,7 @@ export default function Home() {
</Prose>
</div>
<GappedGrid
<FeatureGrid
title="Bread-and-butter datastructures"
className="grid-cols-2 lg:grid-cols-4"
>
@@ -442,9 +443,9 @@ export default function Home() {
<CoStreamDescription />
</SmallProse>
</GridCard>
</GappedGrid>
</FeatureGrid>
<GappedGrid
<FeatureGrid
title="First-class files & binary data"
className="grid-cols-2 lg:grid-cols-4"
>
@@ -465,9 +466,9 @@ export default function Home() {
<ImageDefinitionDescription />
</SmallProse>
</GridCard>
</GappedGrid>
</FeatureGrid>
<GappedGrid
<FeatureGrid
title="Secure permissions, authorship & teams"
className="grid-cols-2 lg:grid-cols-4"
>
@@ -487,7 +488,7 @@ export default function Home() {
<AccountDescription />
</SmallProse>
</GridCard>
</GappedGrid>
</FeatureGrid>
<div>
<SectionHeader
@@ -501,7 +502,7 @@ export default function Home() {
</SmallProse>
</div>
<GappedGrid>
<FeatureGrid>
<GridCard>
<SectionHeader
title="Auto-sub"
@@ -566,7 +567,7 @@ export default function Home() {
<VideoPresenceCallsDescription />
</SmallProse>
</GridCard>
</GappedGrid>
</FeatureGrid>
<div>
<div className="flex flex-col justify-between gap-3">

View File

@@ -1,6 +1,6 @@
import { HeroHeader } from "gcmp-design-system/src/app/components/molecules/HeroHeader";
import { SectionHeader } from "gcmp-design-system/src/app/components/molecules/SectionHeader";
import { GappedGrid } from "gcmp-design-system/src/app/components/molecules/GappedGrid";
import { FeatureGrid } from "gcmp-design-system/src/app/components/molecules/FeatureGrid";
import { GridCard } from "gcmp-design-system/src/app/components/atoms/GridCard";
import { ComingSoonBadge } from "gcmp-design-system/src/app/components/atoms/ComingSoonBadge";
import { P } from "gcmp-design-system/src/app/components/atoms/Paragraph";
@@ -37,7 +37,7 @@ export default function Mesh() {
<GappedGrid>
<GridCard>
<H3>Optimal mesh routing.</H3>
FeatureGrid
<P>
Get ultra-low latency between any group of users
with our decentralized mesh interconnect.
@@ -62,12 +62,12 @@ export default function Mesh() {
</GappedGrid>
</div>
<div>
<div>FeatureGrid
<SectionHeader title="Pricing" slogan="" />
<GappedGrid>
<GridCard>
<H3>
Mesh Free{" "}
FeatureGrid Mesh Free{" "}
<div className="text-2xl float-right">$0</div>
</H3>
@@ -119,7 +119,7 @@ export default function Mesh() {
</GappedGrid>
<H3>FAQ</H3>
<SmallProse>
<PricingFAQ />
FeatureGridFAQ />
</SmallProse>
</div>
@@ -131,7 +131,7 @@ export default function Mesh() {
<GappedGrid>
<div className="text-sm">
<H4>Under 50ms RTT</H4>
<UL>
FeatureGrid>
<LI>Frankfurt</LI>
<LI>New York</LI>
<LI>Newark</LI>
@@ -186,7 +186,7 @@ export default function Mesh() {
</GappedGrid>
<H3>Enterprise</H3>
<P>
<PFeatureGrid
Custom deployment in the cloud, your private cloud,
on-premises or hybrids?
<br />
@@ -208,7 +208,7 @@ export default function Mesh() {
<GappedGrid>
<GridCard>
<Prose>
<MeshPlusBackup />
FeatureGrid <MeshPlusBackup />
</Prose>
</GridCard>
<GridCard>
@@ -224,5 +224,5 @@ export default function Mesh() {
</GappedGrid>
</div>
</div>
);
);FeatureGrid
}

View File

@@ -64,7 +64,7 @@ importers:
specifier: ^3.4.1
version: 3.4.3
typescript:
specifier: ^5
specifier: ^5.3.3
version: 5.4.5
homepage:
@@ -167,7 +167,7 @@ importers:
specifier: ^0.25.13
version: 0.25.13(typescript@5.4.5)
typescript:
specifier: ^5
specifier: ^5.3.3
version: 5.4.5
packages: