diff --git a/website/src/components/Capabilities.tsx b/website/src/components/Capabilities.tsx
new file mode 100644
index 000000000..280ee1d74
--- /dev/null
+++ b/website/src/components/Capabilities.tsx
@@ -0,0 +1,79 @@
+import { ReactNode } from 'react';
+import { asset } from '../asset';
+
+// Icon, title, and description rows shared by the landing and product pages.
+export function CapList({ items }: { items: { icon: ReactNode; title: string; sub: string }[] }) {
+ return (
+
+ {items.map(cap => (
+
+ {cap.icon}
+
+ {cap.title}
+ {cap.sub}
+
+
+ ))}
+
+ );
+}
+
+export const BoxGlyph = () => (
+
+);
+export const CloudGlyph = () => (
+
+);
+export const LayersGlyph = () => (
+
+);
+// GPU chip glyph for the marketplace rows.
+export const ChipGlyph = () => (
+
+);
+// On-prem glyphs (shared with the landing's "bring your own compute" block).
+export const SlurmGlyph = () => (
+
+);
+export const ServerGlyph = () => (
+
+);
+// The Kubernetes helm wheel from /static/logos/kubernetes.svg, inlined with currentColor so it
+// takes the capability-icon color in both themes (the asset has hardcoded black fills).
+export const KubernetesGlyph = () => (
+
+);
diff --git a/website/src/components/ComputeSourcesTabs.tsx b/website/src/components/ComputeSourcesTabs.tsx
index 7723eb449..41b1fd7b1 100644
--- a/website/src/components/ComputeSourcesTabs.tsx
+++ b/website/src/components/ComputeSourcesTabs.tsx
@@ -1,4 +1,4 @@
-import { CapList, CloudGlyph, KubernetesGlyph, ServerGlyph } from '../pages/Home/GetStartedSection';
+import { CapList, CloudGlyph, KubernetesGlyph, ServerGlyph, SlurmGlyph } from './Capabilities';
import { ContentTabs } from './ContentTabs';
const cloudGroups = [
@@ -10,6 +10,7 @@ const cloudGroups = [
const onPremItems = [
{ icon: , title: 'SSH fleets', sub: 'Connect VMs or bare-metal clusters over SSH' },
{ icon: , title: 'Kubernetes', sub: 'Connect your existing Kubernetes clusters' },
+ { icon: , title: 'Slurm (experimental)', sub: 'Connect your existing Slurm clusters' },
];
export function OnPremCapabilities() {
@@ -48,7 +49,7 @@ export function ComputeSourcesTabs({ cloudsFirst = false }: {
content: ,
footer: (
- Use your existing Kubernetes clusters, VMs, or bare-metal clusters
+ Use your existing Kubernetes or Slurm clusters, VMs, or bare-metal
),
};
diff --git a/website/src/components/SiteNavigation.tsx b/website/src/components/SiteNavigation.tsx
index 796ae7600..ceefad16a 100644
--- a/website/src/components/SiteNavigation.tsx
+++ b/website/src/components/SiteNavigation.tsx
@@ -50,12 +50,12 @@ type ProductLink = {
// The products. products[0] (open-source) is featured at the top of the "Products" menu; the rest
// follow as rows. Reused by the standalone top-nav hover menu and the mobile nav's "Products"
// section.
-// NOTE: the descriptions are duplicated in GetStartedSection.tsx (the product list) and
-// mkdocs/overrides/header-2.html — keep all three in sync.
+// Keep menu descriptions in sync with mkdocs/overrides/header-2.html.
+// GetStartedSection.tsx uses a longer dstack description.
const products: ProductLink[] = [
- { id: 'open-source', text: 'dstack', secondaryText: 'The open-source control plane for AI-native orchestration.', href: docsUrl('installation'), icon: , badge: 'Self-hosted', external: true },
- { id: 'factory', text: 'dstack Factory', secondaryText: 'A heterogeneous orchestration stack for AI token factories.', href: asset(ROUTES.FACTORY), icon: , badge: 'Self-hosted' },
- { id: 'sky-product', text: 'dstack Sky', secondaryText: 'One account across GPU clouds. Better prices and unified billing.', href: asset(ROUTES.SKY), icon: , badge: 'Hosted by us' },
+ { id: 'open-source', text: 'dstack', secondaryText: 'A unified orchestration interface across GPU clouds, Kubernetes, VMs, and bare-metal.', href: docsUrl('installation'), icon: , badge: 'Self-hosted' },
+ { id: 'factory', text: 'dstack Factory', secondaryText: 'A multi-tenant orchestration stack for AI labs, data centers, and AI token factories.', href: asset(ROUTES.FACTORY), icon: , badge: 'Self-hosted' },
+ { id: 'sky-product', text: 'dstack Sky', secondaryText: 'Unified access to GPU clouds. Better prices and one billing.', href: asset(ROUTES.SKY), icon: , badge: 'Hosted by us' },
];
// Items for the mobile slide-out navigation. The blog categories are top-level links (mirroring
diff --git a/website/src/pages/Factory/CapacityTabs.tsx b/website/src/pages/Factory/CapacityTabs.tsx
index 10739e705..b1079643d 100644
--- a/website/src/pages/Factory/CapacityTabs.tsx
+++ b/website/src/pages/Factory/CapacityTabs.tsx
@@ -1,28 +1,7 @@
+import { CapList } from '../../components/Capabilities';
import { OnPremCapabilities } from '../../components/ComputeSourcesTabs';
import { ContentTabs } from '../../components/ContentTabs';
-import { CapList } from '../Home/GetStartedSection';
-
-const observabilityItems = [
- {
- icon: (
-
- ),
- title: 'Events',
- sub: 'Track resource state changes and operations',
- },
- {
- icon: (
-
- ),
- title: 'Metrics',
- sub: 'Monitor utilization, accelerator health, and network health',
- },
-];
+import { eventsCapability, metricsCapability } from './capabilities';
export function CapacityTabs() {
return (
@@ -38,7 +17,7 @@ export function CapacityTabs() {
{
id: 'observability',
label: 'Observability',
- content: ,
+ content: ,
},
]}
/>
diff --git a/website/src/pages/Factory/FactoryGetStartedTabs.tsx b/website/src/pages/Factory/FactoryGetStartedTabs.tsx
new file mode 100644
index 000000000..d28b4cb95
--- /dev/null
+++ b/website/src/pages/Factory/FactoryGetStartedTabs.tsx
@@ -0,0 +1,38 @@
+import { ReactNode } from 'react';
+import { CapList } from '../../components/Capabilities';
+import { ContentTabs } from '../../components/ContentTabs';
+import {
+ billingCapability,
+ eventsCapability,
+ exportsCapability,
+ registryCapability,
+} from './capabilities';
+
+export function FactoryGetStartedTabs({ footer }: { footer?: ReactNode }) {
+ return (
+ ,
+ footer,
+ },
+ {
+ id: 'observability',
+ label: 'Observability',
+ content: ,
+ footer,
+ },
+ {
+ id: 'optimized-inference',
+ label: 'Serverless inference',
+ content: ,
+ footer,
+ },
+ ]}
+ />
+ );
+}
diff --git a/website/src/pages/Factory/InferenceTabs.tsx b/website/src/pages/Factory/InferenceTabs.tsx
index 0a57fc5c5..860b34725 100644
--- a/website/src/pages/Factory/InferenceTabs.tsx
+++ b/website/src/pages/Factory/InferenceTabs.tsx
@@ -1,18 +1,6 @@
+import { CapList } from '../../components/Capabilities';
import { ContentTabs } from '../../components/ContentTabs';
-import { BoxGlyph, CapList, LayersGlyph } from '../Home/GetStartedSection';
-
-const inferenceItems = [
- {
- icon: ,
- title: 'Presets',
- sub: 'Agent-based optimization and kernel generation',
- },
- {
- icon: ,
- title: 'Registry',
- sub: 'Day-0 optimized presets for frontier open models',
- },
-];
+import { presetsCapability, registryCapability } from './capabilities';
export function InferenceTabs() {
return (
@@ -23,7 +11,7 @@ export function InferenceTabs() {
{
id: 'inference-optimization',
label: 'Inference optimization',
- content: ,
+ content: ,
},
]}
/>
diff --git a/website/src/pages/Factory/OrchestrationTabs.tsx b/website/src/pages/Factory/OrchestrationTabs.tsx
index e8d8bec93..1cd46aeeb 100644
--- a/website/src/pages/Factory/OrchestrationTabs.tsx
+++ b/website/src/pages/Factory/OrchestrationTabs.tsx
@@ -1,5 +1,5 @@
+import { CapList, ServerGlyph } from '../../components/Capabilities';
import { ContentTabs } from '../../components/ContentTabs';
-import { CapList, ServerGlyph } from '../Home/GetStartedSection';
const orchestrationItems = [
{
diff --git a/website/src/pages/Factory/TenantTabs.tsx b/website/src/pages/Factory/TenantTabs.tsx
index 967b80cdc..09d421d05 100644
--- a/website/src/pages/Factory/TenantTabs.tsx
+++ b/website/src/pages/Factory/TenantTabs.tsx
@@ -1,40 +1,6 @@
+import { CapList } from '../../components/Capabilities';
import { ContentTabs } from '../../components/ContentTabs';
-import { CapList } from '../Home/GetStartedSection';
-
-const tenantItems = [
- {
- icon: (
-
- ),
- title: 'Projects',
- sub: 'Tenant isolation and resource access control',
- },
- {
- icon: (
-
- ),
- title: 'Exports',
- sub: 'Share selected fleets and gateways across projects',
- },
- {
- icon: (
-
- ),
- title: 'Billing',
- sub: 'Usage metering and automated customer billing',
- },
-];
+import { billingCapability, exportsCapability, projectsCapability } from './capabilities';
export function TenantTabs() {
return (
@@ -45,7 +11,7 @@ export function TenantTabs() {
{
id: 'usage-and-billing',
label: 'Usage and billing',
- content: ,
+ content: ,
},
]}
/>
diff --git a/website/src/pages/Factory/capabilities.tsx b/website/src/pages/Factory/capabilities.tsx
new file mode 100644
index 000000000..871f2ea46
--- /dev/null
+++ b/website/src/pages/Factory/capabilities.tsx
@@ -0,0 +1,69 @@
+import { BoxGlyph, LayersGlyph } from '../../components/Capabilities';
+
+export const eventsCapability = {
+ icon: (
+
+ ),
+ title: 'Events',
+ sub: 'Audit user actions and resource lifecycle events across projects.',
+};
+
+export const metricsCapability = {
+ icon: (
+
+ ),
+ title: 'Metrics',
+ sub: 'Monitor utilization, accelerator health, and network health',
+};
+
+export const projectsCapability = {
+ icon: (
+
+ ),
+ title: 'Projects',
+ sub: 'Tenant isolation and resource access control',
+};
+
+export const exportsCapability = {
+ icon: (
+
+ ),
+ title: 'Exports',
+ sub: 'Share selected fleets and gateways across projects',
+};
+
+export const billingCapability = {
+ icon: (
+
+ ),
+ title: 'Billing',
+ sub: 'Compute and token metering and billing automation',
+};
+
+export const presetsCapability = {
+ icon: ,
+ title: 'Presets',
+ sub: 'Agent-based optimization and kernel generation',
+};
+
+export const registryCapability = {
+ icon: ,
+ title: 'Registry',
+ sub: 'Day-0 optimized presets for frontier open models',
+};
diff --git a/website/src/pages/Home/ExploreSection.tsx b/website/src/pages/Home/ExploreSection.tsx
index d49664ee1..0bc57fb4a 100644
--- a/website/src/pages/Home/ExploreSection.tsx
+++ b/website/src/pages/Home/ExploreSection.tsx
@@ -1,4 +1,5 @@
import { ReactNode } from 'react';
+import Link from '@cloudscape-design/components/link';
import { AlternatingDocBlock } from '../../components/AlternatingDocBlock';
import { ArchitectureDiagram } from '../../components/ArchitectureDiagram';
import { ComputeSourcesTabs } from '../../components/ComputeSourcesTabs';
@@ -23,7 +24,7 @@ export function ExploreSection() {
dstack gives cloud tenants and data-center operators a unified control plane for managing compute and orchestrating AI workloads.
- It improves operational efficiency and removes vendor lock-in. No more hassle of building your own compute stack on top of Kubernetes or Slurm.
+ It improves operational efficiency and removes vendor lock-in. Use your existing infrastructure without building and maintaining your own AI compute stack.
@@ -43,9 +44,10 @@ function BringComputeBlock() {
imageFirst
>
Have bare-metal servers or VMs with SSH access? Point dstack to those hosts and provide SSH
- credentials to create an SSH fleet. Have an existing Kubernetes cluster? Point dstack's
- Kubernetes backend to the kubeconfig. dstack will schedule workloads on them alongside cloud
- clusters.
+ credentials to create an SSH fleet. Have an existing Kubernetes or Slurm cluster? Connect it
+ through the Kubernetes backend or the {highlightTerms('experimental Slurm backend')}.
+ dstack provides a unified workload interface while Kubernetes or Slurm handles scheduling
+ within the cluster.
dstack natively integrates with the major GPU clouds and automates provisioning of clusters.
diff --git a/website/src/pages/Home/FaqSection.tsx b/website/src/pages/Home/FaqSection.tsx
index a51dc60c3..c9aa7c731 100644
--- a/website/src/pages/Home/FaqSection.tsx
+++ b/website/src/pages/Home/FaqSection.tsx
@@ -1,32 +1,58 @@
import { ReactNode, useState } from 'react';
import Button from '@cloudscape-design/components/button';
import ExpandableSection from '@cloudscape-design/components/expandable-section';
+import Link from '@cloudscape-design/components/link';
import SpaceBetween from '@cloudscape-design/components/space-between';
import { mainButtonStyle } from '../../cloudscape-theme';
import { AlternatingDocBlock } from '../../components/AlternatingDocBlock';
import { highlightTerms } from '../../components/highlightTerms';
+import { docsUrl } from '../../routes';
type FaqItem = {
q: string;
- a: string | string[];
+ a: ReactNode;
};
const faqItems: FaqItem[] = [
{
- q: 'How does dstack differ from Slurm?',
- a: 'Slurm is a battle-tested workload manager with decades of production use in HPC environments. dstack is a unified orchestration layer built for containerized AI workloads and heterogeneous AI compute. While both support batch jobs and distributed training, dstack also provides first-class primitives for compute management, inference, and observability, including native cloud provisioning.',
+ q: 'How does dstack compare to Slurm?',
+ a: [
+ 'Slurm is a battle-tested workload manager used in HPC and large-scale AI training. dstack is a unified orchestration layer built for containerized AI workloads and heterogeneous AI compute, with first-class primitives for compute management, training, inference, and observability.',
+ 'dstack can be used instead of Slurm to orchestrate AI workloads directly on cloud GPUs, pre-provisioned VMs, or bare-metal. It can also run on top of existing Slurm clusters through the Slurm backend.',
+ ],
},
{
q: 'How does dstack compare to Kubernetes?',
- a: 'Kubernetes is a general-purpose container orchestrator. dstack also orchestrates containers, but provides a lightweight, streamlined interface purpose-built for AI workloads, with first-class primitives for compute management, training, inference, and observability. It can use Kubernetes as a compute backend or work directly with cloud GPUs, pre-provisioned VMs, or bare-metal, helping cloud tenants and data-center operators improve utilization without building and maintaining their own AI orchestration stack.',
+ a: [
+ 'Kubernetes is a general-purpose container orchestrator. dstack also orchestrates containers, but provides a lightweight, streamlined interface purpose-built for AI workloads, with first-class primitives for compute management, training, inference, and observability.',
+ 'dstack can be used instead of Kubernetes to orchestrate AI workloads directly on cloud GPUs, pre-provisioned VMs, or bare-metal. It can also run on top of existing Kubernetes clusters through the Kubernetes backend.',
+ ],
},
{
q: 'Can I use dstack with Kubernetes?',
- a: 'Yes. Connect existing Kubernetes clusters through the Kubernetes backend, and dstack will schedule AI workloads on them alongside cloud GPUs, VMs, and bare-metal. Use the Kubernetes backend when your GPUs already run on Kubernetes or your team relies on its ecosystem and tooling. Otherwise, cloud backends are often simpler for cloud GPUs, and SSH fleets for pre-provisioned VMs or bare-metal.',
+ a: [
+ <>
+ {highlightTerms('Yes. Connect existing Kubernetes clusters through the ')}
+ {highlightTerms('Kubernetes backend')}
+ {highlightTerms(', and dstack will schedule AI workloads on them alongside cloud GPUs, VMs, and bare-metal.')}
+ >,
+ 'Use the Kubernetes backend when your GPUs already run on Kubernetes or your team relies on its ecosystem and tooling. Otherwise, cloud backends are often simpler for cloud GPUs, and SSH fleets for pre-provisioned VMs or bare-metal.',
+ ],
+ },
+ {
+ q: 'Can I use dstack with Slurm?',
+ a: [
+ <>
+ {highlightTerms('Yes. Connect existing Slurm clusters through the experimental ')}
+ {highlightTerms('Slurm backend')}
+ {highlightTerms('. dstack connects to each cluster’s login node over SSH and submits runs as Slurm jobs.')}
+ >,
+ 'Slurm retains resource allocation and scheduling, while dstack provides the same interface for development, training, and inference used with other backends. The cluster must have Pyxis and enroot installed and configured.',
+ ],
},
{
q: 'When should I use dstack?',
- a: 'Use dstack as a unified orchestration layer for cluster management, training, and inference, built for heterogeneous AI compute. It is designed for cloud tenants, data-center operators, and teams running their own AI token factory at planet scale.',
+ a: 'Use dstack as a unified orchestration layer for cluster management, training, and inference, built for heterogeneous AI compute. It is designed for cloud tenants, data-center operators, and AI token factories.',
},
];
diff --git a/website/src/pages/Home/GetStartedSection.tsx b/website/src/pages/Home/GetStartedSection.tsx
index a07fb08e7..31ee42f1e 100644
--- a/website/src/pages/Home/GetStartedSection.tsx
+++ b/website/src/pages/Home/GetStartedSection.tsx
@@ -1,164 +1,147 @@
-import { ReactNode, useState } from 'react';
+import { Fragment, useId, useState } from 'react';
import CodeView from '@cloudscape-design/code-view/code-view';
import shHighlight from '@cloudscape-design/code-view/highlight/sh';
import Button from '@cloudscape-design/components/button';
import { asset } from '../../asset';
import { mainButtonStyle } from '../../cloudscape-theme';
+import { BoxGlyph, CloudGlyph, LayersGlyph } from '../../components/Capabilities';
+import { ContentTabs } from '../../components/ContentTabs';
+import { highlightTerms } from '../../components/highlightTerms';
import { installMethods, maxInstallLines, padYamlToLines } from '../../data/snippets';
import { DOCS_URL, ROUTES, docsUrl } from '../../routes';
+import { FactoryGetStartedTabs } from '../Factory/FactoryGetStartedTabs';
+import { MarketplaceTabs } from '../Sky/MarketplaceTabs';
-export const BoxGlyph = () => (
-
-);
-export const CloudGlyph = () => (
-
-);
-export const LayersGlyph = () => (
-
-);
-// GPU chip glyph for the marketplace rows.
-export const ChipGlyph = () => (
-
-);
-// On-prem glyphs (shared with the landing's "bring your own compute" block).
-export const ServerGlyph = () => (
-
-);
-// The Kubernetes helm wheel from /static/logos/kubernetes.svg, inlined with currentColor so it
-// takes the capability-icon color in both themes (the asset has hardcoded black fills).
-export const KubernetesGlyph = () => (
-
-);
+// Product menus in SiteNavigation.tsx and mkdocs/overrides/header-2.html use a shorter
+// dstack description.
+const products = [
+ {
+ id: 'dstack',
+ name: 'dstack',
+ description: 'A unified orchestration interface across GPU clouds, Kubernetes, VMs, and bare-metal clusters.',
+ group: 'Self-hosted',
+ icon: ,
+ },
+ {
+ id: 'factory',
+ name: 'dstack Factory',
+ description: 'A multi-tenant orchestration stack for AI labs, data centers, and AI token factories.',
+ group: 'Self-hosted',
+ icon: ,
+ },
+ {
+ id: 'sky',
+ name: 'dstack Sky',
+ description: 'Unified access to GPU clouds. Better prices and one billing.',
+ group: 'Hosted by us',
+ icon: ,
+ },
+] as const;
-// Read-only shell snippet. Line wrapping is left off so padded snippets stay
-// equal height across tabs (see padYamlToLines).
-function ShellCode({ content }: { content: string }) {
- return (
-
-
-
- );
-}
+type ProductId = (typeof products)[number]['id'];
-// Icon, title, and description rows shared by the Home and Sky pages.
-export function CapList({ items }: { items: { icon: ReactNode; title: string; sub: string }[] }) {
- return (
-
- {items.map(cap => (
-
- {cap.icon}
-
- {cap.title}
- {cap.sub}
-
-
- ))}
-
- );
-}
-
-// NOTE: the three product descriptions below are duplicated in SiteNavigation.tsx (products)
-// and mkdocs/overrides/header-2.html — keep all three in sync.
export function GetStartedSection() {
- const [method, setMethod] = useState<(typeof installMethods)[number]['id']>(installMethods[0].id);
-
- const activeInstall = installMethods.find(m => m.id === method) ?? installMethods[0];
+ const [product, setProduct] = useState('dstack');
+ const id = useId();
+ const footer = ;
return (