feat: redesign compute page sections with interactive code examples
- Replaced static use cases section with tabbed interface showing AI/ML, application hosting, and edge compute capabilities - Added ComputeCodeTabs component with interactive code examples (train.py, deploy.yaml, edge.ts) - Updated CallToAction section with new bordered layout and restructured CTA buttons for hosting and deploying
This commit is contained in:
112
src/pages/compute/ComputeCodeTabs.tsx
Normal file
112
src/pages/compute/ComputeCodeTabs.tsx
Normal file
@@ -0,0 +1,112 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
|
||||
const files = [
|
||||
{
|
||||
id: "train",
|
||||
label: "train.py",
|
||||
code: `from mycelium import GPUCluster, Dataset
|
||||
|
||||
# connect to private GPU cluster
|
||||
cluster = GPUCluster("secure://my-node")
|
||||
|
||||
# load training data
|
||||
data = Dataset.load("s3://models/private-dataset")
|
||||
|
||||
# run a reproducible training job
|
||||
job = cluster.train(
|
||||
model="resnet50",
|
||||
dataset=data,
|
||||
epochs=40,
|
||||
deterministic=True
|
||||
)
|
||||
|
||||
job.save("s3://models/checkpoints/resnet-private")`,
|
||||
},
|
||||
{
|
||||
id: "deploy",
|
||||
label: "deploy.yaml",
|
||||
code: `apiVersion: mycelium/v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: vector-api
|
||||
spec:
|
||||
image: registry.mycelium/vector:latest
|
||||
replicas: 3
|
||||
selfHeal: true
|
||||
mesh: private
|
||||
resources:
|
||||
gpu: 1
|
||||
cpu: 2
|
||||
memory: 4Gi`,
|
||||
},
|
||||
{
|
||||
id: "edge",
|
||||
label: "edge.ts",
|
||||
code: `import { EdgeClient } from "@mycelium/sdk"
|
||||
|
||||
// deploy inference to nearest node
|
||||
const client = new EdgeClient()
|
||||
|
||||
await client.deploy({
|
||||
model: "resnet-private",
|
||||
region: "eu-home-nodes",
|
||||
autoscale: true,
|
||||
cache: "on-device"
|
||||
})`,
|
||||
},
|
||||
];
|
||||
|
||||
export function ComputeCodeTabs() {
|
||||
const [active, setActive] = useState("train");
|
||||
const file = files.find((f) => f.id === active)!;
|
||||
|
||||
return (
|
||||
<div className="sm:px-6 lg:px-0">
|
||||
<div className="relative isolate overflow-hidden bg-indigo-500 px-6 pt-8 sm:mx-auto sm:max-w-2xl sm:rounded-3xl sm:pt-16 sm:pr-0 sm:pl-16 lg:mx-0 lg:max-w-none">
|
||||
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="absolute -inset-y-px -left-3 -z-10 w-full origin-bottom-left skew-x-[-30deg] bg-indigo-100 opacity-20 ring-1 ring-white ring-inset"
|
||||
/>
|
||||
|
||||
<div className="mx-auto max-w-2xl sm:mx-0 sm:max-w-none">
|
||||
<div className="w-screen overflow-hidden rounded-tl-xl bg-gray-900 ring-1 ring-white/10">
|
||||
|
||||
{/* FILE TABS */}
|
||||
<div className="flex bg-gray-800/40 ring-1 ring-white/5">
|
||||
<div className="-mb-px flex text-sm font-medium text-gray-400">
|
||||
|
||||
{files.map((f) => (
|
||||
<button
|
||||
key={f.id}
|
||||
onClick={() => setActive(f.id)}
|
||||
className={`px-4 py-2 border-r border-white/10 ${
|
||||
active === f.id
|
||||
? "border-b border-b-white/20 bg-white/5 text-white"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
{f.label}
|
||||
</button>
|
||||
))}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* CODE BLOCK */}
|
||||
<div className="px-6 pt-6 pb-14 font-mono text-xs leading-relaxed text-gray-200 whitespace-pre overflow-x-auto">
|
||||
{file.code}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="pointer-events-none absolute inset-0 ring-1 ring-white/10 ring-inset sm:rounded-3xl"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user