Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions site/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ node_modules
dist
.vercel
cache
src/pages.gen.ts
47 changes: 47 additions & 0 deletions site/components/FamilyNav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Cross-repo navigation for the tevm.sh family of documentation sites.
* Every entry below is a live site.
*/

export const FAMILY = [
{ name: 'tevm.sh', url: 'https://tevm.sh', desc: 'The Ethereum toolkit β€” start here' },
{ name: 'contract.tevm.sh', url: 'https://contract.tevm.sh', desc: 'Typesafe contract bindings' },
{ name: 'bundler.tevm.sh', url: 'https://bundler.tevm.sh', desc: 'Import Solidity from JS' },
{ name: 'cli.tevm.sh', url: 'https://cli.tevm.sh', desc: 'Command line interface' },
{ name: 'test.tevm.sh', url: 'https://test.tevm.sh', desc: 'Contract testing utilities' },
{ name: 'logger.tevm.sh', url: 'https://logger.tevm.sh', desc: 'Structured logging' },
{ name: 'ethers.tevm.sh', url: 'https://ethers.tevm.sh', desc: 'ethers.js integration' },
{ name: 'mud.tevm.sh', url: 'https://mud.tevm.sh', desc: 'MUD framework integration' },
{ name: 'examples.tevm.sh', url: 'https://examples.tevm.sh', desc: 'End-to-end examples' },
{ name: 'voltaire.tevm.sh', url: 'https://voltaire.tevm.sh', desc: 'Ethereum primitives in Zig' },
{
name: 'guillotine.tevm.sh',
url: 'https://guillotine.tevm.sh',
desc: 'High-performance EVM interpreter',
},
{ name: 'mini.tevm.sh', url: 'https://mini.tevm.sh', desc: 'Minimal spec-faithful EVM' },
{ name: 'zevm.tevm.sh', url: 'https://zevm.tevm.sh', desc: 'Zig Ethereum client (this site)' },
]

const CURRENT = 'zevm.tevm.sh'

export function FamilyNav() {
return (
<nav className="tevm-family" aria-label="tevm documentation family">
<p className="tevm-family__title">Explore the tevm family</p>
<div className="tevm-family__grid">
{FAMILY.map((site) => (
<a
key={site.name}
className="tevm-family__item"
href={site.url}
aria-current={site.name === CURRENT ? 'page' : undefined}
>
<span className="tevm-family__name">{site.name}</span>
<span className="tevm-family__desc">{site.desc}</span>
</a>
))}
</div>
</nav>
)
}
45 changes: 45 additions & 0 deletions site/components/Hero.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use client'

import { useState } from 'react'

const INSTALL = 'npm install @evmts/zevm@beta'

export function Hero() {
const [copied, setCopied] = useState(false)

const copy = () => {
navigator.clipboard?.writeText(INSTALL)
setCopied(true)
setTimeout(() => setCopied(false), 1500)
}

return (
<div className="tevm-hero">
<p className="tevm-hero__eyebrow">Ethereum client Β· written in Zig</p>
<h1 className="tevm-hero__title">ZEVM</h1>
<p className="tevm-hero__tagline">
A writable trusted dev node and a proof-backed light client in one binary β€” shipped as a
CLI, a C ABI, and a Node.js addon with prebuilt binaries for macOS, Linux and Windows.
</p>

<div className="tevm-hero__install">
<code>{INSTALL}</code>
<button type="button" className="tevm-copy" onClick={copy}>
{copied ? 'copied' : 'copy'}
</button>
</div>

<div className="tevm-hero__ctas">
<a className="tevm-hero__cta tevm-hero__cta--primary" href="/quickstart/installation">
Get started
</a>
<a className="tevm-hero__cta" href="/reference/cli">
CLI reference
</a>
<a className="tevm-hero__cta" href="https://github.com/evmts/zevm">
GitHub
</a>
</div>
</div>
)
}
189 changes: 189 additions & 0 deletions site/components/PlatformPicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
'use client'

import { useEffect, useState } from 'react'

/**
* Interactive platform-support picker.
*
* ZEVM ships one prebuilt native package per platform under `npm/platforms`,
* wired into `@evmts/zevm` as optionalDependencies. This mirrors that table so a
* reader can answer "is my machine supported, and which package do I get?"
* without cross-referencing package.json files.
*
* Source of truth: the package.json of each npm/platforms directory.
*/

type Target = {
os: string
arch: string
libc?: string
pkg: string
}

const TARGETS: Target[] = [
{ os: 'darwin', arch: 'arm64', pkg: '@evmts/zevm-darwin-arm64' },
{ os: 'darwin', arch: 'x64', pkg: '@evmts/zevm-darwin-x64' },
{ os: 'linux', arch: 'arm64', libc: 'glibc', pkg: '@evmts/zevm-linux-arm64-gnu' },
{ os: 'linux', arch: 'arm64', libc: 'musl', pkg: '@evmts/zevm-linux-arm64-musl' },
{ os: 'linux', arch: 'x64', libc: 'glibc', pkg: '@evmts/zevm-linux-x64-gnu' },
{ os: 'linux', arch: 'x64', libc: 'musl', pkg: '@evmts/zevm-linux-x64-musl' },
{ os: 'win32', arch: 'arm64', pkg: '@evmts/zevm-win32-arm64-msvc' },
{ os: 'win32', arch: 'ia32', pkg: '@evmts/zevm-win32-ia32-msvc' },
{ os: 'win32', arch: 'x64', pkg: '@evmts/zevm-win32-x64-msvc' },
]

const OS_LABELS: Record<string, string> = {
darwin: 'macOS',
linux: 'Linux',
win32: 'Windows',
}

const ARCHES = ['arm64', 'x64', 'ia32']
const LIBCS = ['glibc', 'musl']

function find(os: string, arch: string, libc: string) {
return TARGETS.find(
(t) => t.os === os && t.arch === arch && (os === 'linux' ? t.libc === libc : true),
)
}

/** Best-effort guess of the visitor's platform from the UA string. */
function guess(): { os: string; arch: string } {
if (typeof navigator === 'undefined') return { os: 'darwin', arch: 'arm64' }
const ua = navigator.userAgent
const os = /Win/.test(ua) ? 'win32' : /Linux|Android/.test(ua) ? 'linux' : 'darwin'
const arch = /arm|aarch64|Mac OS X/.test(ua) && !/Intel Mac/.test(ua) ? 'arm64' : 'x64'
return { os, arch }
}

export function PlatformPicker() {
const [os, setOs] = useState('darwin')
const [arch, setArch] = useState('arm64')
const [libc, setLibc] = useState('glibc')
const [copied, setCopied] = useState(false)

useEffect(() => {
const g = guess()
setOs(g.os)
setArch(g.arch)
}, [])

// Windows has no arm64/x64/ia32 gap, but arm64 is absent on Windows ia32 etc.
// Keep the selected arch valid whenever the OS changes.
useEffect(() => {
if (!TARGETS.some((t) => t.os === os && t.arch === arch)) {
const first = TARGETS.find((t) => t.os === os)
if (first) setArch(first.arch)
}
}, [os, arch])

const match = find(os, arch, libc)
const install = 'npm install @evmts/zevm@beta'

const copy = () => {
navigator.clipboard?.writeText(install)
setCopied(true)
setTimeout(() => setCopied(false), 1500)
}

return (
<div className="zevm-platform">
<div className="zevm-platform__row">
<div className="zevm-platform__group">
<span className="zevm-platform__label" id="zevm-os">
Operating system
</span>
<div className="zevm-platform__options" role="group" aria-labelledby="zevm-os">
{Object.keys(OS_LABELS).map((value) => (
<button
key={value}
type="button"
className="zevm-chip"
aria-pressed={os === value}
onClick={() => setOs(value)}
>
{OS_LABELS[value]}
</button>
))}
</div>
</div>

<div className="zevm-platform__group">
<span className="zevm-platform__label" id="zevm-arch">
Architecture
</span>
<div className="zevm-platform__options" role="group" aria-labelledby="zevm-arch">
{ARCHES.map((value) => {
const available = TARGETS.some((t) => t.os === os && t.arch === value)
return (
<button
key={value}
type="button"
className="zevm-chip"
aria-pressed={arch === value}
disabled={!available}
onClick={() => setArch(value)}
>
{value}
</button>
)
})}
</div>
</div>

{os === 'linux' && (
<div className="zevm-platform__group">
<span className="zevm-platform__label" id="zevm-libc">
libc
</span>
<div className="zevm-platform__options" role="group" aria-labelledby="zevm-libc">
{LIBCS.map((value) => (
<button
key={value}
type="button"
className="zevm-chip"
aria-pressed={libc === value}
onClick={() => setLibc(value)}
>
{value}
</button>
))}
</div>
</div>
)}
</div>

<div className="zevm-platform__result">
{match ? (
<>
<div className="zevm-platform__pkg">
<span className="zevm-badge zevm-badge--ok">Prebuilt binary</span>
<code>{match.pkg}</code>
</div>
<div className="tevm-hero__install">
<code>{install}</code>
<button type="button" className="tevm-copy" onClick={copy}>
{copied ? 'copied' : 'copy'}
</button>
</div>
<p className="zevm-platform__note">
npm resolves <code>{match.pkg}</code> automatically through the{' '}
<code>optionalDependencies</code> of <code>@evmts/zevm</code>. Nothing is compiled at
install time.
</p>
</>
) : (
<>
<div className="zevm-platform__pkg">
<span className="zevm-badge zevm-badge--none">No prebuilt binary</span>
</div>
<p className="zevm-platform__note">
This combination has no published package. Build the binary yourself β€” see{' '}
<a href="/guides/building-from-source">Building From Source</a>.
</p>
</>
)}
</div>
</div>
)
}
4 changes: 4 additions & 0 deletions site/public/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added site/public/tevm-logo-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added site/public/tevm-logo-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading