From c2a5958542b5a20955cdac9846e28bced7f926e6 Mon Sep 17 00:00:00 2001 From: Musilah Date: Fri, 27 Mar 2026 15:20:38 +0300 Subject: [PATCH 1/4] update SEO Signed-off-by: Musilah --- app/(marketing)/imprint/page.tsx | 3 +- app/(marketing)/page.tsx | 65 +++++++++++ app/(marketing)/privacy/page.tsx | 3 +- app/(marketing)/terms/page.tsx | 3 +- app/(marketing)/use-cases/[slug]/page.tsx | 136 +++++++++++++++++++--- app/docs/[...slug]/page.tsx | 36 +++++- app/docs/page.tsx | 19 ++- app/layout.tsx | 30 ++++- app/robots.ts | 23 ++++ app/sitemap.ts | 29 +++++ components/JsonLd.tsx | 16 +++ components/sections/FAQ.tsx | 50 ++++++++ components/use-cases/UseCaseCTA.tsx | 34 +++++- components/use-cases/UseCaseHero.tsx | 4 +- lib/metadata.ts | 9 +- next.config.ts | 15 +++ public/llms.txt | 27 +++++ 17 files changed, 462 insertions(+), 40 deletions(-) create mode 100644 app/robots.ts create mode 100644 app/sitemap.ts create mode 100644 components/JsonLd.tsx create mode 100644 components/sections/FAQ.tsx create mode 100644 public/llms.txt diff --git a/app/(marketing)/imprint/page.tsx b/app/(marketing)/imprint/page.tsx index ef9de0a..6242fe2 100644 --- a/app/(marketing)/imprint/page.tsx +++ b/app/(marketing)/imprint/page.tsx @@ -1,8 +1,9 @@ import { createMetadata } from '@/lib/metadata'; export const metadata = createMetadata({ - title: 'Imprint - Ultraviolet', + title: 'Imprint | Cube AI', description: 'Imprint and Legal Information for Ultraviolet', + alternates: { canonical: '/imprint/' }, }); export default function ImprintPage() { diff --git a/app/(marketing)/page.tsx b/app/(marketing)/page.tsx index 4734c84..fc1e457 100644 --- a/app/(marketing)/page.tsx +++ b/app/(marketing)/page.tsx @@ -4,16 +4,81 @@ import Integrations from "@/components/sections/Integrations"; import Gateway from "@/components/sections/Gateway"; import UseCases from "@/components/sections/UseCases"; import Partners from "@/components/sections/Partners"; +import FAQ from "@/components/sections/FAQ"; +import JsonLd from "@/components/JsonLd"; + +const homepageFAQs = [ + { + question: "What is Cube AI?", + answer: "Cube AI is an open-source framework that deploys Large Language Models inside hardware Trusted Execution Environments (TEEs), providing cryptographic guarantees that neither the cloud provider nor infrastructure operators can access your data or model weights.", + }, + { + question: "How does TEE isolation work in Cube AI?", + answer: "Cube AI runs LLM inference inside AMD SEV-SNP or Intel TDX enclaves — hardware-isolated memory regions where code and data are encrypted in use. Remote attestation lets you verify cryptographically that the code running inside the enclave has not been tampered with.", + }, + { + question: "Is Cube AI HIPAA compliant?", + answer: "Cube AI's architecture supports HIPAA compliance by ensuring PHI never leaves the TEE in plaintext, applying automated PII/PHI masking at the AI Gateway layer, and generating cryptographic audit trails for all model interactions.", + }, + { + question: "Can Cube AI run on-premises?", + answer: "Yes. Cube AI is deployment-agnostic and supports on-premise hospital data centers, private cloud environments, and air-gapped government networks — anywhere your data sovereignty requirements demand the AI runs locally.", + }, + { + question: "Does Cube AI support OpenAI-compatible APIs?", + answer: "Yes. Cube AI exposes an OpenAI-compatible REST API, enabling teams to switch from public LLM APIs to confidential AI infrastructure with minimal code changes.", + }, + { + question: "Who is behind Cube AI?", + answer: "Cube AI is developed by Ultraviolet, a member of the Linux Foundation and the Confidential Computing Consortium, with backing from the European Commission and enterprise partners including Nokia, Ericsson, Thales, and Fujitsu.", + }, +]; + +const organizationSchema = { + "@context": "https://schema.org", + "@type": "Organization", + "@id": "https://cube.ultraviolet.rs/#organization", + "name": "Ultraviolet", + "url": "https://ultraviolet.rs", + "description": "Confidential computing and secure AI platform provider", + "email": "info@ultraviolet.rs", + "sameAs": [ + "https://github.com/ultravioletrs/cube", + "https://linkedin.com/company/ultravioletrs", + "https://twitter.com/ultravioletrs", + ], + "memberOf": [ + { "@type": "Organization", "name": "Linux Foundation" }, + { "@type": "Organization", "name": "Confidential Computing Consortium" }, + ], +}; + +const softwareApplicationSchema = { + "@context": "https://schema.org", + "@type": "SoftwareApplication", + "name": "Cube AI", + "applicationCategory": "SecurityApplication", + "operatingSystem": "Linux", + "offers": { "@type": "Offer", "price": "0", "priceCurrency": "USD" }, + "url": "https://cube.ultraviolet.rs", + "downloadUrl": "https://github.com/ultravioletrs/cube", + "license": "https://github.com/ultravioletrs/cube/blob/main/LICENSE", + "description": "Open-source framework for securing LLMs with TEEs, built-in governance, and privacy-preserving AI gateways.", + "featureList": ["Hardware TEE isolation", "AI Gateway", "PII redaction", "Cryptographic audit trails", "RBAC", "OpenAI-compatible API"], + "author": { "@type": "Organization", "@id": "https://cube.ultraviolet.rs/#organization", "name": "Ultraviolet" }, +}; export default function Home() { return (
+ +
); } diff --git a/app/(marketing)/privacy/page.tsx b/app/(marketing)/privacy/page.tsx index bb4e8e2..1a7962a 100644 --- a/app/(marketing)/privacy/page.tsx +++ b/app/(marketing)/privacy/page.tsx @@ -1,8 +1,9 @@ import { createMetadata } from '@/lib/metadata'; export const metadata = createMetadata({ - title: 'Privacy Policy - Ultraviolet', + title: 'Privacy Policy | Cube AI', description: 'Privacy Policy for Cube AI Platform', + alternates: { canonical: '/privacy/' }, }); export default function PrivacyPage() { diff --git a/app/(marketing)/terms/page.tsx b/app/(marketing)/terms/page.tsx index 65754c6..4ce421c 100644 --- a/app/(marketing)/terms/page.tsx +++ b/app/(marketing)/terms/page.tsx @@ -1,8 +1,9 @@ import { createMetadata } from '@/lib/metadata'; export const metadata = createMetadata({ - title: 'Terms of Service - Ultraviolet', + title: 'Terms of Service | Cube AI', description: 'Terms of Service for Cube AI Platform', + alternates: { canonical: '/terms/' }, }); export default function TermsPage() { diff --git a/app/(marketing)/use-cases/[slug]/page.tsx b/app/(marketing)/use-cases/[slug]/page.tsx index 17a29eb..a103666 100644 --- a/app/(marketing)/use-cases/[slug]/page.tsx +++ b/app/(marketing)/use-cases/[slug]/page.tsx @@ -2,13 +2,91 @@ import React from "react"; import { notFound } from "next/navigation"; import { Metadata } from "next"; import { getUseCaseBySlug, useCases } from "@/lib/use-cases"; +import { createMetadata, baseUrl } from "@/lib/metadata"; +const useCaseOgImages: Record = { + "financial-services": "/img/finance-hero.png", + "healthcare": "/img/healthcare-hero.png", + "government": "/img/government-hero.png", +}; + +import JsonLd from "@/components/JsonLd"; +import FAQ from "@/components/sections/FAQ"; import UseCaseHero from "@/components/use-cases/UseCaseHero"; import UseCaseChallenges from "@/components/use-cases/UseCaseChallenges"; import UseCaseSolutions from "@/components/use-cases/UseCaseSolutions"; import UseCaseDeployments from "@/components/use-cases/UseCaseDeployments"; import UseCaseCTA from "@/components/use-cases/UseCaseCTA"; +const useCaseFAQs: Record = { + "financial-services": [ + { + question: "Is Cube AI compliant with SEC and FINRA regulations?", + answer: "Cube AI's verifiable compute policies and cryptographic audit trails support compliance with SEC Rule 17a-4 and FINRA requirements for data integrity and access control in AI-assisted trading systems.", + }, + { + question: "How does Cube AI protect proprietary trading algorithms?", + answer: "Trading models run inside hardware TEEs, making model weights and inference logic inaccessible to cloud operators, co-tenants, or unauthorized employees — even with root access to the host system.", + }, + { + question: "Can multiple banks collaborate on AI models without sharing raw data?", + answer: "Yes. Cube AI's attestation layer enables multi-party computation where each institution can verify the model and policies before contributing data, without any party seeing another's raw inputs.", + }, + { + question: "What latency overhead does TEE-based inference add?", + answer: "Typical overhead is 5–15% compared to unprotected inference, depending on workload. For compliance-sensitive use cases, this is an acceptable trade-off versus regulatory and reputational risk.", + }, + { + question: "Does Cube AI integrate with existing Bloomberg or Reuters data feeds?", + answer: "Cube AI's OpenAI-compatible API layer allows integration with any data pipeline. Specific connector support depends on your deployment configuration.", + }, + ], + "healthcare": [ + { + question: "How does Cube AI prevent PHI from entering LLM training data?", + answer: "Cube AI's AI Gateway applies automated PHI detection and masking (names, SSNs, MRNs, dates of birth) before prompts reach the model, and hardware TEEs ensure the model operator cannot log or access the raw prompt stream.", + }, + { + question: "Is Cube AI HIPAA compliant?", + answer: "Cube AI's architecture supports HIPAA compliance through encrypted-in-use computation, PHI masking, role-based access control, and cryptographic audit logs. Compliance certification requires your specific deployment configuration to be assessed.", + }, + { + question: "Can hospitals securely collaborate on AI research without sharing patient records?", + answer: "Yes. Hardware attestation allows multiple institutions to verify that an agreed model policy is enforced before contributing data. No institution sees another's raw patient records.", + }, + { + question: "Does Cube AI support on-premise deployment in hospital data centers?", + answer: "Yes. Cube AI is designed for environments where data cannot leave the hospital network. Full on-premise deployment is a primary use case.", + }, + { + question: "How are medical AI model outputs audited for regulatory purposes?", + answer: "Every inference request generates a cryptographically signed audit trail stored outside the TEE, providing tamper-evident logs suitable for regulatory review and medical liability documentation.", + }, + ], + "government": [ + { + question: "Is Cube AI FedRAMP aligned?", + answer: "Cube AI's confidential computing architecture aligns with FedRAMP High baseline controls around data-at-rest and data-in-use encryption, zero-trust access, and audit logging. Formal FedRAMP authorization requires a specific deployment assessment.", + }, + { + question: "Can Cube AI operate in air-gapped environments?", + answer: "Yes. Cube AI supports fully isolated, air-gapped deployments with no external network dependencies for inference. Model updates and attestation verification can be performed offline.", + }, + { + question: "How does Cube AI support zero-trust security models?", + answer: "Cube AI assumes no implicit trust in the host OS, hypervisor, or cloud provider. All sensitive operations are confined to hardware TEEs with cryptographic proof of integrity available at any time via remote attestation.", + }, + { + question: "What classification levels can Cube AI support?", + answer: "Cube AI has been evaluated for environments requiring IL4-equivalent protections. Specific classification level support depends on your hardware platform (AMD SEV-SNP, Intel TDX) and deployment configuration.", + }, + { + question: "Does Cube AI support multi-agency data sharing?", + answer: "Yes. Using hardware attestation, multiple government agencies can share AI infrastructure while maintaining cryptographic guarantees that each agency's data is processed only by authorized models under agreed policies.", + }, + ], +}; + interface UseCasePageProps { params: Promise<{ slug: string }>; } @@ -27,20 +105,24 @@ export async function generateMetadata({ params }: UseCasePageProps): Promise - + - + )} + ); diff --git a/app/docs/[...slug]/page.tsx b/app/docs/[...slug]/page.tsx index 3828b39..10aa134 100644 --- a/app/docs/[...slug]/page.tsx +++ b/app/docs/[...slug]/page.tsx @@ -3,6 +3,8 @@ import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/layo import { notFound } from 'next/navigation'; import type { Metadata } from 'next'; import defaultMdxComponents from 'fumadocs-ui/mdx'; +import { createMetadata, baseUrl } from '@/lib/metadata'; +import JsonLd from '@/components/JsonLd'; export default async function Page(props: { params: Promise<{ slug?: string[] }>; @@ -14,7 +16,21 @@ export default async function Page(props: { // eslint-disable-next-line @typescript-eslint/no-explicit-any const { body: MDX, toc, full } = page.data as any; + const techArticleSchema = { + "@context": "https://schema.org", + "@type": "TechArticle", + "headline": page.data.title, + "description": page.data.description ?? "", + "url": `https://cube.ultraviolet.rs/docs/${params.slug?.join('/') ?? ''}/`, + "isPartOf": { "@id": "https://cube.ultraviolet.rs/#website" }, + "author": { "@type": "Organization", "@id": "https://cube.ultraviolet.rs/#organization", "name": "Ultraviolet" }, + "publisher": { "@type": "Organization", "name": "Ultraviolet", "url": "https://ultraviolet.rs" }, + "dateModified": new Date().toISOString().split('T')[0], + }; + return ( + <> + {page.data.title} {page.data.description} @@ -22,6 +38,7 @@ export default async function Page(props: { + ); } @@ -36,8 +53,19 @@ export async function generateMetadata(props: { const page = source.getPage(params.slug); if (!page) notFound(); - return { - title: page.data.title, - description: page.data.description, - }; + const canonical = `/docs/${params.slug?.join('/') ?? ''}/`; + return createMetadata({ + title: `${page.data.title} | Cube AI Docs`, + description: page.data.description ?? `${page.data.title} — Cube AI technical reference. Learn how to configure, deploy, and secure LLMs with hardware Trusted Execution Environments.`, + alternates: { + canonical, + }, + openGraph: { + url: `${baseUrl}${canonical}`, + images: [{ url: "/img/cube-ai-docs.png", width: 1200, height: 630, alt: "Cube AI Documentation" }], + }, + twitter: { + images: ["/img/cube-ai-docs.png"], + }, + }); } diff --git a/app/docs/page.tsx b/app/docs/page.tsx index 62c873a..d9721d7 100644 --- a/app/docs/page.tsx +++ b/app/docs/page.tsx @@ -3,6 +3,7 @@ import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/layo import { notFound } from 'next/navigation'; import type { Metadata } from 'next'; import defaultMdxComponents from 'fumadocs-ui/mdx'; +import { createMetadata, baseUrl } from '@/lib/metadata'; export default async function Page() { const page = source.getPage([]); @@ -26,8 +27,18 @@ export async function generateMetadata(): Promise { const page = source.getPage([]); if (!page) notFound(); - return { - title: page.data.title, - description: page.data.description, - }; + return createMetadata({ + title: 'Cube AI Documentation | Ultraviolet', + description: page.data.description ?? 'Technical documentation for Cube AI — deploy LLMs inside hardware TEEs, configure the AI Gateway, manage attestation policies, and integrate via OpenAI-compatible APIs.', + alternates: { + canonical: '/docs/', + }, + openGraph: { + url: `${baseUrl}/docs/`, + images: [{ url: "/img/cube-ai-docs.png", width: 1200, height: 630, alt: "Cube AI Documentation" }], + }, + twitter: { + images: ["/img/cube-ai-docs.png"], + }, + }); } diff --git a/app/layout.tsx b/app/layout.tsx index 221da26..1714034 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -2,6 +2,19 @@ import type { Metadata } from "next"; import { Roboto_Mono } from "next/font/google"; import "./globals.css"; import { RootProvider } from 'fumadocs-ui/provider/next'; +import JsonLd from "@/components/JsonLd"; +import { baseUrl } from "@/lib/metadata"; + +const isProd = baseUrl === "https://cube.ultraviolet.rs"; + +const websiteSchema = { + "@context": "https://schema.org", + "@type": "WebSite", + "@id": "https://cube.ultraviolet.rs/#website", + "url": "https://cube.ultraviolet.rs", + "name": "Cube AI", + "publisher": { "@id": "https://cube.ultraviolet.rs/#organization" }, +}; const robotoMono = Roboto_Mono({ variable: "--font-roboto-mono", @@ -9,22 +22,30 @@ const robotoMono = Roboto_Mono({ }); export const metadata: Metadata = { + metadataBase: new URL(baseUrl), title: "Cube AI - Secure LLM & Confidential AI Platform", description: "Cube AI is an open-source framework for securing Large Language Models (LLMs) with TEEs, built-in governance, and privacy-preserving AI gateways.", - keywords: ["Cube AI", "secure LLM", "confidential AI", "TEE", "AI gateway", "privacy-preserving AI", "Ollama", "Hugging Face", "enterprise AI"], authors: [{ name: "Ultraviolet" }], + alternates: { + canonical: "/", + }, + robots: isProd + ? { index: true, follow: true, googleBot: { index: true, follow: true, 'max-image-preview': 'large', 'max-snippet': -1 } } + : { index: false, follow: false }, openGraph: { title: "Cube AI - Secure LLM & Confidential AI Platform", description: "Cube AI is an open-source framework for securing Large Language Models (LLMs) with TEEs, built-in governance, and privacy-preserving AI gateways.", - images: ["https://ultraviolet.rs/img/header.avif"], - url: "https://ultraviolet.rs/cube/", + images: [{ url: "/img/cube-ai-hero.png", width: 1200, height: 630, alt: "Cube AI — Confidential AI Platform" }], + url: baseUrl, type: "website", + siteName: "Cube AI", }, twitter: { card: "summary_large_image", + site: "@ultravioletrs", title: "Cube AI - Secure LLM & Confidential AI Platform", description: "Cube AI is an open-source framework for securing Large Language Models (LLMs) with TEEs, built-in governance, and privacy-preserving AI gateways.", - images: ["https://ultraviolet.rs/img/header.avif"], + images: ["/img/cube-ai-hero.png"], }, }; @@ -39,6 +60,7 @@ export default function RootLayout({ className={`${robotoMono.className} antialiased bg-background font-sans`} > + {children} diff --git a/app/robots.ts b/app/robots.ts new file mode 100644 index 0000000..b47fa91 --- /dev/null +++ b/app/robots.ts @@ -0,0 +1,23 @@ +import type { MetadataRoute } from "next"; +import { baseUrl } from "@/lib/metadata"; + +export const dynamic = "force-static"; + +const isProd = baseUrl === "https://cube.ultraviolet.rs"; + +export default function robots(): MetadataRoute.Robots { + if (!isProd) { + return { rules: [{ userAgent: "*", disallow: "/" }] }; + } + + return { + rules: [ + { userAgent: "*", allow: "/", disallow: "/api/" }, + { userAgent: "GPTBot", allow: "/" }, + { userAgent: "ClaudeBot", allow: "/" }, + { userAgent: "PerplexityBot", allow: "/" }, + { userAgent: "Google-Extended", allow: "/" }, + ], + sitemap: `${baseUrl}/sitemap.xml`, + }; +} diff --git a/app/sitemap.ts b/app/sitemap.ts new file mode 100644 index 0000000..01fc779 --- /dev/null +++ b/app/sitemap.ts @@ -0,0 +1,29 @@ +import type { MetadataRoute } from "next"; + +export const dynamic = "force-static"; +import { baseUrl } from "@/lib/metadata"; +import { source } from "@/lib/source"; +import { useCases } from "@/lib/use-cases"; + +export default function sitemap(): MetadataRoute.Sitemap { + const marketingPages: MetadataRoute.Sitemap = [ + { url: `${baseUrl}/`, priority: 1.0, changeFrequency: "weekly" }, + { url: `${baseUrl}/docs/`, priority: 0.9, changeFrequency: "weekly" }, + ...useCases.map((uc) => ({ + url: `${baseUrl}/use-cases/${uc.slug}/`, + priority: 0.8 as const, + changeFrequency: "monthly" as const, + })), + { url: `${baseUrl}/imprint/`, priority: 0.3, changeFrequency: "yearly" }, + { url: `${baseUrl}/terms/`, priority: 0.3, changeFrequency: "yearly" }, + { url: `${baseUrl}/privacy/`, priority: 0.3, changeFrequency: "yearly" }, + ]; + + const docsPages: MetadataRoute.Sitemap = source.getPages().map((page) => ({ + url: `${baseUrl}${page.url}`, + priority: 0.7, + changeFrequency: "weekly" as const, + })); + + return [...marketingPages, ...docsPages]; +} diff --git a/components/JsonLd.tsx b/components/JsonLd.tsx new file mode 100644 index 0000000..a3f3b0d --- /dev/null +++ b/components/JsonLd.tsx @@ -0,0 +1,16 @@ +type JsonLdData = Record | Record[]; + +export default function JsonLd({ data }: { data: JsonLdData }) { + const schemas = Array.isArray(data) ? data : [data]; + return ( + <> + {schemas.map((schema, i) => ( +