Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions site/src/components/marketing/Closing.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
const {
title = 'Try the xNet alpha',
body = 'Download the desktop app or open the browser demo.'
} = Astro.props
---

<section class="m-cta">
<div class="m-wrap">
<div>
<h2 class="m-heading">{title}</h2>
<p class="m-copy mt-5">{body}</p>
</div>
<a href="/download" class="m-button">
Try xNet <span aria-hidden="true">↗</span>
</a>
</div>
</section>
17 changes: 17 additions & 0 deletions site/src/components/marketing/PageHero.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
interface Props {
eyebrow: string
title: string
description: string
}
const { eyebrow, title, description } = Astro.props
---

<header class="m-page-hero">
<div class="m-wrap">
<p class="m-eyebrow">{eyebrow}</p>
<h1 class="m-title">{title}</h1>
<p class="m-lede">{description}</p>
<slot />
</div>
</header>
85 changes: 85 additions & 0 deletions site/src/components/marketing/Substrate.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
import CodeBlock from '../ui/CodeBlock.astro'
const pieces = [
{
name: 'Nodes',
label: 'Reusable records',
example: 'A task, a contact, a page.',
description: 'Each record has an ID. Relations connect records across your workspace.',
color: 'text-indigo-600 dark:text-indigo-400 bg-indigo-500/10'
},
{
name: 'Schemas',
label: 'A shared structure',
example: 'Title, status, project.',
description: 'Define fields and relations. Add fields in your namespace or create a new type.',
color: 'text-emerald-700 dark:text-emerald-400 bg-emerald-500/10'
},
{
name: 'Views',
label: 'Different ways to work',
example: 'A table, a board, your own app.',
description: 'Read and edit the same records through a different interface.',
color: 'text-violet-600 dark:text-violet-400 bg-violet-500/10'
}
]
const schemaCode = `<span class="tok-keyword">import</span> { defineSchema, text, checkbox }
<span class="tok-keyword">from</span> <span class="tok-string">'@xnetjs/data'</span>

<span class="tok-keyword">const</span> Task = <span class="tok-function">defineSchema</span>({
name: <span class="tok-string">'Task'</span>,
namespace: <span class="tok-string">'xnet://my-app/'</span>,
properties: {
title: <span class="tok-function">text</span>({ required: <span class="tok-number">true</span> }),
done: <span class="tok-function">checkbox</span>({ default: <span class="tok-number">false</span> })
}
})`
---

<div class="mt-7 grid items-start gap-6 lg:grid-cols-2">
<ol class="grid gap-3" aria-label="Three parts of the xNet substrate">
{pieces.map((piece) => (
<li class="rounded-xl border border-border p-4">
<div class="flex flex-wrap items-center gap-3">
<h3 class={`rounded-md px-2 py-1 text-sm font-semibold ${piece.color}`}>{piece.name}</h3>
<span class="text-sm font-medium">{piece.label}</span>
</div>
<p class="mt-2 text-sm text-gray-600 dark:text-gray-400">
<strong class="font-medium text-gray-800 dark:text-gray-200">{piece.example}</strong>{' '}
{piece.description}
</p>
</li>
))}
</ol>
<div class="min-w-0">
<CodeBlock filename="task.schema.ts" code={schemaCode} />
<p class="mt-3 text-xs text-gray-500">
A schema defines the data. Your interface decides how to display it.
</p>
</div>
</div>
<details class="mechanics mt-5 rounded-xl border border-border bg-surface/40 px-5 py-3">
<summary class="cursor-pointer text-sm font-medium">
How storage, sync, and permissions work
</summary>
<div class="mt-4 grid gap-4 text-sm text-gray-600 dark:text-gray-400 sm:grid-cols-3">
<p>
<strong class="text-gray-900 dark:text-gray-100">Local storage.</strong> The workspace keeps a
copy on your device. Offline changes sync when connected.
</p>
<p>
<strong class="text-gray-900 dark:text-gray-100">Signed changes.</strong> Structured edits
form a signed, hash-linked log. Peers can check who signed an edit and detect changes to it.
</p>
<p>
<strong class="text-gray-900 dark:text-gray-100">Merge rules.</strong> Yjs merges document
edits; structured fields use last-writer-wins rules. Grants govern sharing and access.
</p>
</div>
<a
href="/docs/concepts/data-model/"
class="mt-4 inline-block text-sm text-indigo-600 hover:underline dark:text-indigo-400"
>
Data model documentation →
</a>
</details>
24 changes: 24 additions & 0 deletions site/src/components/marketing/WorkspaceImage.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<figure>
<div class="m-screen">
<img
class="screen-light"
src="/images/workbench-light.png"
width="1600"
height="1000"
alt="xNet’s workspace with a document open beside the explorer. The document contains example project content."
loading="lazy"
/>
<img
class="screen-dark"
src="/images/workbench-dark.png"
width="1600"
height="1000"
alt="xNet’s workspace in dark mode, showing an example project document and explorer."
loading="lazy"
/>
</div>
<figcaption class="m-caption">
<span>The xNet workspace · example content</span>
<span>Documents, databases, and canvases on your device.</span>
</figcaption>
</figure>
Loading
Loading