{title}
+{text}
+diff --git a/MEDIA_CAPTURE.md b/MEDIA_CAPTURE.md index 88918dc..b46212e 100644 --- a/MEDIA_CAPTURE.md +++ b/MEDIA_CAPTURE.md @@ -1,3 +1,7 @@ +# October 2026 distribution UI + +`project-import-2026-10-20.png` and `project-deployments-2026-10-20.png` are unaltered captures of the merged distribution UI, built from the product release branch on 20 October 2026. They use a disposable local Docker instance and a synthetic Weekend planner source folder. The folder contained a package.json and no Compose file; folder browsing, import and opening Add deployment were exercised through the UI. No production workload was changed. These are interface demonstrations, not deployment-success evidence. The tour captions distinguish them from the dated production evidence below. + # Public evidence captures The public site uses unaltered desktop captures from the operator's authenticated GroundControl interface, captured on 22 September 2026. No generated interface or chat image is presented as product evidence. diff --git a/README.md b/README.md index b347af2..b5a3cbb 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,12 @@ GroundControl itself is a self-hosted, single-tenant control plane. Each operato ## Current product story +“Put your agents to work” leads with GroundControl’s promise: deploy and operate applications with the agents you use, on infrastructure you own. The homepage brings the article’s operational context, MCP tools, OAuth access and durable execution into the product story. It explains what the connection enables: inspect application state, request supported deployments, and return to their recorded results. + +The homepage uses a dark theme with Serendepify’s lime and coral accents, with Schibsted Grotesk headings, Hanken Grotesk body text and JetBrains Mono details. Fonts are self-hosted through Next.js. + +The product tour and dated deployment evidence describe available capabilities. The separate Autopilot section is explicitly marked **Product direction**; customer-journey testing and proactive recovery are not presented as available features. The installation guide remains the primary call to action. + GroundControl gives software agents bounded infrastructure capabilities through MCP + OAuth: - inspect deployments, runtime and health; @@ -15,7 +21,7 @@ GroundControl gives software agents bounded infrastructure capabilities through - use connector capability health for GitHub, GHCR and Daytona; - keep SSH keys, provider credentials and the human PTY outside the agent tool surface. -Fresh installs use the canonical on-host installer and a one-time human ownership claim. +Fresh installs start with the computer launcher: local Docker or a remote Linux server, followed by a one-time ownership claim. The canonical on-host installer remains available for server operators. ## Verified deployment proof @@ -34,13 +40,14 @@ The full deployment and Daytona contract is maintained in the main repository at ## Install -Human-readable: +On your computer (macOS / Linux, or Windows through WSL): ```bash -curl -fsSL https://raw.githubusercontent.com/teckedd-code2save/groundcontrol/main/scripts/install | sudo bash +curl -fsSL https://raw.githubusercontent.com/teckedd-code2save/groundcontrol/main/scripts/start -o groundcontrol-start +bash groundcontrol-start ``` -Agent-oriented JSON result: +Directly on a Linux server, with an agent-oriented JSON result: ```bash curl -fsSL https://raw.githubusercontent.com/teckedd-code2save/groundcontrol/main/scripts/install \ @@ -78,8 +85,9 @@ MIT ## Native documentation and public evidence -The complete adoption path lives at `/docs`. Twelve guides cover the philosophy and workload model, install/claim, next steps after installation, HTTPS publishing, host discovery, existing application enrollment, new template deployments, ChatGPT OAuth/MCP, deployment automation, maintenance, troubleshooting and evidence. No GitHub visit is required to follow a guide. +The complete adoption path lives at `/docs`. Thirteen guides cover projects and deployment instances, the philosophy and workload model, install/claim, next steps after installation, HTTPS publishing, host discovery, existing application enrollment, new template deployments, ChatGPT OAuth/MCP, deployment automation, maintenance, troubleshooting and evidence. No GitHub visit is required to follow a guide. +- `content/setup-guides.tsx` contains local/remote setup and the project/source/deployment model. - `content/guides.tsx` contains the guide sections, runnable examples and expected results. - `content/journey-guides.tsx` contains the philosophy, post-install, discovery and new-deployment guides. `content/guide-parts.tsx` supplies shared guide elements. - `content/guide-index.ts` defines sidebar order and search terms. @@ -89,4 +97,8 @@ The complete adoption path lives at `/docs`. Twelve guides cover the philosophy - Product screenshots open at full size and preserve their aspect ratio. - See `MEDIA_CAPTURE.md` for capture provenance, dates and claim boundaries. -Validate guide links/anchors, assets, endpoint formatting, clipboard behavior, product-tour keyboard navigation and checklist state with `npm test`. Review the actual rendered pages and capture any limits in `SITE_REVIEW.md`. The current browser runtime does not expose viewport emulation, so real phone testing remains outstanding. +Validate guide links/anchors, assets, endpoint formatting, clipboard behavior, product-tour keyboard navigation and checklist state with `npm test`. Review the actual rendered pages and capture any limits in `SITE_REVIEW.md`. Browser viewport testing covers desktop and narrow layouts; physical phone testing remains outstanding. + +## Sharing + +Share https://trygroundcontrol.serendepify.com/ or link directly to `/docs/getting-started`. The root metadata provides a dark Open Graph image and a large social card, generated at build time by `app/opengraph-image.tsx`. The install guide is self-contained; the public site does not collect credentials or expose an operator login. diff --git a/SITE_REVIEW.md b/SITE_REVIEW.md index 890beae..a7ec021 100644 --- a/SITE_REVIEW.md +++ b/SITE_REVIEW.md @@ -1,6 +1,25 @@ -# Public site review, 22 September 2026 +# Distribution release site review · 20 October 2026 + +The homepage, article and all thirteen handbook guides now share a dark theme with lime calls to action. The copy leads with agentic deployment on infrastructure the visitor owns, and explains the new local/remote computer launcher, folder/GitHub project import, and connect-existing/launch-new deployment paths. The project model separates application source from runtime instances. Desktop limits, WSL, AMD64 emulation and the server-only HTTPS/upgrade flows are explicit in the relevant guides. + +The first two walkthrough stages use fresh captures of the distribution UI with a disposable example project. The September OAuth and production-operation evidence keeps its original dates and qualifications. No production deployment was used or changed for the new captures. A static dark Open Graph image and large social card make the public URL ready to share. + +Validation: lint, TypeScript, all nine behavior/navigation tests and the production build passed. Browser review covered the homepage at 1280 and 390 pixels, walkthrough switching, the 390-pixel installation guide and expandable documentation navigation, image loading and the generated 1200×630 share card. No horizontal page overflow was observed. Actual physical-device testing remains unverified. + +## Earlier reviews + +# Public site review + +## Serendepify brand alignment, 3 October 2026 + +The public marketing site adopts the company site's current visual language while leading with GroundControl’s own promise: “Put your agents to work.” The opening explains agentic deployment on infrastructure the reader owns. The capability section brings forward the article’s application context, scoped execution and durable results, and links directly to the full story. The navigation now calls that article “Why GroundControl.” The proof section explains signed GitHub deployment automation and the agent’s access to recorded outcomes. Warm paper, lime accents, an outlined headline and the company's font families connect the two sites without replacing GroundControl's identity or its real product screenshots. + +Available capabilities stay separate from the clearly labeled Autopilot product direction. The existing September evidence dates and provenance qualifications are preserved. Installation, native guides, product-tour behavior and operator-owned authentication boundaries are unchanged. No operator instance or deployment is part of this revision. + +Local lint, TypeScript, all nine tests and the static production build passed. Browser review covered the homepage at 1280 pixels, its tour selection, the installation link, and the installation guide's expandable documentation menu at 390 pixels. Font inspection confirmed Schibsted Grotesk headings and Hanken Grotesk body text. Neither the homepage nor the installation guide had horizontal document overflow at 390 pixels after constraining the installation panel's grid columns; long commands retain their own scroll area. Physical device testing remains outstanding. + +## Product journey revision, 22 September 2026 -## Product journey revision The homepage now has a four-part product tour using actual desktop captures, a post-install sequence, an illustrated workload model, inspectable deployment proof and direct learning paths. Twelve native guides cover the GroundControl philosophy, installation, next steps, publishing, discovery, enrollment, new template deployments, agent access, automation, maintenance, troubleshooting and evidence. diff --git a/app/articles/agentic-deployment-with-oauth-and-mcp/page.tsx b/app/articles/agentic-deployment-with-oauth-and-mcp/page.tsx index 838884c..26cca27 100644 --- a/app/articles/agentic-deployment-with-oauth-and-mcp/page.tsx +++ b/app/articles/agentic-deployment-with-oauth-and-mcp/page.tsx @@ -45,7 +45,7 @@ export default function ArticlePage() { Connect an agent From merge to deployment The agent’s view - Use it on your VPS + Use your own infrastructure
- Install GroundControl, claim your instance and review the host - scan. Choose one application, confirm its identity and connect - your agent. A health check gives you a first result you can + Start GroundControl from your computer, locally or on a Linux + server. Add a project from a folder or GitHub, connect or launch + its deployment, and authorize your agent. A health check gives you a first result you can compare with the product interface. From there, follow the deployment guide for the operations your workload supports.
diff --git a/app/components/NextSteps.tsx b/app/components/NextSteps.tsx index 62d9da1..1788f57 100644 --- a/app/components/NextSteps.tsx +++ b/app/components/NextSteps.tsx @@ -19,10 +19,10 @@ const paths = [ { id: "new", title: "I want to deploy a new app", - intro: "Use a template to validate, create and enroll a new deployment.", + intro: "Add your project, then choose the launch path supported by its host.", steps: [ - ["Choose a template for your application", "new-deployment#choose"], - ["Connect and verify the source", "new-deployment#source"], + ["Add your project from a folder or GitHub", "projects#sources"], + ["Choose a host and deployment environment", "projects#deployments"], ["Configure and review the proposed deployment", "new-deployment#review"], ["Deploy and check the public result", "new-deployment#verify"], ["Grant your agent access to that workload", "agent-access#consent"], diff --git a/app/components/ProductTour.tsx b/app/components/ProductTour.tsx index 8b05600..8075ee6 100644 --- a/app/components/ProductTour.tsx +++ b/app/components/ProductTour.tsx @@ -6,24 +6,26 @@ import Capture from "./Capture"; const stages = [ { - title: "Discover", - heading: "Start with what is already running.", - text: "GroundControl reads the active host, finds Compose folders and containers, and presents candidates you can inspect.", - fact: "Review the candidates and choose which to enroll.", - file: "discovery-desktop.jpg", - alt: "GroundControl discovered workloads with source paths and Enrol deployment buttons", - href: "/docs/discovery", - link: "How discovery works", + title: "Project", + heading: "Start with the application you’re building.", + text: "Pick a folder from your computer or import a GitHub repository. Your project brings the source, purpose and deployment instances together.", + fact: "Add source first. Choose its deployments separately.", + file: "project-import-2026-10-20.png", + alt: "GroundControl Add project chooser with folder and GitHub import options", + caption: "Current interface · isolated demo · 20 October 2026", + href: "/docs/projects#sources", + link: "Add your first project", }, { - title: "Enrol", - heading: "Choose what belongs in GroundControl.", - text: "Enrol one candidate, keep its files where they are, and optionally group it into a project. Confirm its source, runtime and public address.", - fact: "Enrollment preserves the workload’s existing location.", - file: "enrollment-desktop.jpg", - alt: "GroundControl enrollment dialog showing optional project grouping", - href: "/docs/first-deployment", - link: "Follow the enrollment guide", + title: "Deploy", + heading: "Give each environment its own instance.", + text: "Connect an application already running on your host, or launch a new instance. Each deployment has its own environment, configuration and release history.", + fact: "Local Docker or your Linux server. Your infrastructure.", + file: "project-deployments-2026-10-20.png", + alt: "GroundControl Add deployment dialog offering connect existing or launch new", + caption: "Current interface · example project · 20 October 2026", + href: "/docs/projects#deployments", + link: "Choose a deployment path", }, { title: "Connect", @@ -31,6 +33,7 @@ const stages = [ text: "Add your instance’s MCP endpoint to a compatible client, sign in through OAuth and select the deployments it may access.", fact: "The grant names the capabilities and workloads.", file: "agents-desktop.jpg", + caption: "Operator interface · captured 22 September 2026", alt: "GroundControl Agents workspace showing a real active ChatGPT grant", href: "/docs/agent-access", link: "Connect your agent", @@ -41,6 +44,7 @@ const stages = [ text: "Read runtime checks and the public endpoint result. A durable operation ID lets your agent return to the same work after a timeout.", fact: "RentAWeekend recorded release · 21 September 2026.", file: "verification-desktop.jpg", + caption: "Recorded release · captured 22 September 2026", alt: "GroundControl runtime image verification and public endpoint evidence", href: "/docs/evidence", link: "Inspect the recorded evidence", @@ -109,7 +113,7 @@ export default function ProductTour() {
- Open-source operations for infrastructure you own.
-
A Serendepify product.
+ Agentic deployment on infrastructure you own.
+
Built by{" "}
+
+ Serendepify
+ {" "}
+ in Accra, Ghana.
Updated
- 22 September 2026
+ {guide.updated ?? "22 September 2026"}
The operator’s handbook
Install, claim and connect the local host.
+Choose your computer or a server and open the setup link.
Installation guide → 02 / ContinueReview discovery and choose your first application.
+Add a project, then connect or launch a deployment.
Follow the next steps → diff --git a/app/globals.css b/app/globals.css index f323cb9..4ae1fd1 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1,23 +1,37 @@ @import "tailwindcss"; :root { - --paper: #f7f6f2; - --surface: #ffffff; - --ink: #202923; - --muted: #626a64; - --line: #dcdfd8; - --dark: #141c18; - --dark-line: #38473e; - --green: #326349; - --soft-green: #eaf0e8; - --code: #e1eadd; - --font-sans: var(--font-geist-sans); - --font-mono: var(--font-geist-mono); + /* Serendepify's lime and coral on a dark, warm-neutral canvas. */ + --paper: #11130f; + --paper-deep: #171b14; + --lime: #c8ff3d; + --coral: #ff8165; + --grid-line: rgba(225, 237, 203, 0.045); + --lime-wash: rgba(200, 255, 61, 0.08); + --light-ink: #f0f2e8; + --dark-muted: #b7bfab; + --dark-active: #252d1b; + --panel-line: #414a36; + --surface: #1c2118; + --ink: #f0f2e8; + --muted: #b7bfab; + --line: #353d2d; + --dark: #0b0e09; + --dark-line: #353d2d; + --green: #c8ff3d; + --soft-green: #232c18; + --code: #20271a; + --on-accent: #11160a; + --accent-hover: #daff84; + --font-sans: var(--font-brand-body); + --font-display: var(--font-brand-display); + --font-mono: var(--font-brand-mono); } * { box-sizing: border-box; } html { + color-scheme: dark; scroll-behavior: smooth; scroll-padding-top: 100px; } @@ -56,8 +70,8 @@ pre:focus-visible, outline-offset: 5px; } ::selection { - background: #d5e6d6; - color: var(--ink); + background: var(--lime); + color: var(--on-accent); } h1, h2, @@ -69,7 +83,8 @@ figure { h1, h2, h3 { - font-weight: 500; + font-family: var(--font-display), sans-serif; + font-weight: 600; } img { display: block; @@ -118,8 +133,8 @@ img { top: -100px; z-index: 99; padding: 14px 22px; - background: var(--ink); - color: white; + background: var(--lime); + color: var(--on-accent); } .skip-link:focus { top: 12px; @@ -139,16 +154,19 @@ img { gap: 30px; min-height: 48px; padding: 15px 21px; - background: var(--ink); - color: white; - border: 1px solid var(--ink); - border-radius: 4px; + background: var(--lime); + color: var(--on-accent); + border: 1px solid var(--lime); + border-radius: 8px; font-size: 14px; - font-weight: 500; + font-weight: 600; transition: background 0.2s; } .button:hover { - background: var(--green); + background: var(--accent-hover); +} +.button > span { + color: inherit; } .button.compact { min-height: 42px; @@ -173,7 +191,7 @@ img { align-items: center; } .site-header { - min-height: 82px; + min-height: 76px; padding: 0 max(32px, calc((100% - 1264px) / 2)); display: flex; justify-content: space-between; @@ -244,20 +262,22 @@ img { /* Product story */ .landing-hero { display: grid; - grid-template-columns: 1.15fr 1fr; + grid-template-columns: 1.12fr 1fr; gap: 8%; - padding-block: 78px 70px; + padding-block: 72px 60px; align-items: end; } .hero-heading h1 { - font-size: clamp(54px, 5.65vw, 79px); - line-height: 1.05; + font-size: clamp(72px, 7.6vw, 106px); + line-height: 0.96; + font-weight: 600; letter-spacing: -0.063em; margin-top: 25px; } .hero-heading em { font-style: normal; - color: var(--green); + color: transparent; + -webkit-text-stroke: 1.4px var(--ink); } .hero-intro { padding-bottom: 5px; @@ -312,7 +332,7 @@ img { border: 1px solid var(--dark-line); border-radius: 8px; background: var(--dark); - color: #edf1e8; + color: var(--light-ink); overflow: hidden; } .tour-tabs { @@ -327,7 +347,7 @@ img { align-items: center; gap: 17px; font-size: 15px; - color: #bec9be; + color: var(--dark-muted); border-bottom: 2px solid transparent; text-align: left; } @@ -337,7 +357,7 @@ img { .tour-tabs button > span:first-child { font-family: var(--font-mono); font-size: 10px; - color: #a0afa4; + color: var(--dark-muted); } .tour-tabs button > span:last-child { margin-left: auto; @@ -345,11 +365,11 @@ img { } .tour-tabs button[aria-selected="true"] { color: white; - background: #26372d; - border-bottom-color: #97bd9b; + background: var(--dark-active); + border-bottom-color: var(--lime); } .product-tour :focus-visible { - outline-color: #b5d2b5; + outline-color: var(--lime); outline-offset: -5px; } .tour-panel { @@ -361,7 +381,7 @@ img { min-height: 555px; } .tour-copy .eyebrow { - color: #a3b4a6; + color: var(--dark-muted); font-size: 10px; } .tour-copy h2 { @@ -374,7 +394,7 @@ img { font-size: 14px; line-height: 1.85; margin-top: 19px; - color: #bcc8bd; + color: var(--dark-muted); } .tour-copy .tour-fact { border-top: 1px solid var(--dark-line); @@ -386,7 +406,7 @@ img { display: inline-block; font-size: 13px; color: white; - border-bottom: 1px solid #64876a; + border-bottom: 1px solid var(--lime); padding: 12px 0 6px; margin-top: 12px; } @@ -487,8 +507,8 @@ img { color: var(--green); } .philosophy-band { - background: #e9eee7; - border-block: 1px solid #d4ded1; + background: var(--paper-deep); + border-block: 1px solid var(--line); padding-block: 75px; } .philosophy-grid { @@ -499,24 +519,24 @@ img { } .philosophy-grid > div > p:not(.eyebrow) { font-size: 15px; - color: #536151; + color: var(--muted); line-height: 1.85; margin-top: 22px; } .philosophy-grid .text-link { - border-color: #bdcbbc; + border-color: var(--panel-line); margin-top: 20px; } .workload-model { padding: 25px; - border: 1px solid #c7d4c5; + border: 1px solid var(--panel-line); border-radius: 5px; - background: #f7faf3; + background: var(--paper); } .workload-model figcaption { font-size: 11px; line-height: 1.6; - color: #52694f; + color: var(--muted); padding-bottom: 22px; } .model-row { @@ -524,14 +544,14 @@ img { flex-wrap: wrap; gap: 7px 18px; padding: 17px; - background: white; - border: 1px solid #d0dccb; + background: var(--surface); + border: 1px solid var(--panel-line); align-items: center; } .model-row > span { font-size: 10px; font-family: var(--font-mono); - color: #63715e; + color: var(--muted); width: 80px; } .model-row strong { @@ -541,11 +561,11 @@ img { .model-row small { width: 100%; padding-left: 98px; - color: #687362; + color: var(--muted); font-size: 10px; } .model-deployment { - border-left: 1px solid #b6c8b2; + border-left: 1px solid var(--panel-line); margin: 0 0 0 15px; padding: 20px 0 0 17px; } @@ -556,17 +576,17 @@ img { padding: 13px 0; } .model-services > span { - border: 1px solid #d0dccb; + border: 1px solid var(--panel-line); padding: 13px; font-family: var(--font-mono); font-size: 12px; - background: #eaf1e4; + background: var(--paper-deep); } .model-services small { display: block; font-family: var(--font-sans); font-size: 10px; - color: #586b52; + color: var(--muted); margin-top: 7px; } .model-route { @@ -574,7 +594,7 @@ img { } .workload-model > p { font-size: 12px; - color: #52654b; + color: var(--muted); line-height: 1.8; margin-top: 20px; } @@ -688,10 +708,13 @@ img { } .start-grid { display: grid; - grid-template-columns: 1fr 1fr; + grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9%; align-items: center; } +.start-grid > div { + min-width: 0; +} .start-grid .eyebrow, .start-grid .small { color: #a5b5a7; @@ -793,7 +816,7 @@ img { width: 100%; min-height: 48px; padding: 13px; - border: 1px solid #b6c0b5; + border: 1px solid var(--panel-line); border-radius: 3px; color: var(--ink); font-family: var(--font-mono); @@ -805,7 +828,7 @@ img { margin-top: 13px !important; } .endpoint-builder .input-error { - color: #a03f2e !important; + color: var(--coral) !important; } .endpoint-builder .code-block { margin-bottom: 13px; @@ -852,7 +875,7 @@ img { } .docs-sidebar nav a:hover { color: var(--ink); - background: #ecefe7; + background: var(--surface); } .docs-sidebar nav a.active { border-left-color: var(--green); @@ -866,7 +889,7 @@ img { .nav-group > p { font-size: 10px; font-family: var(--font-mono); - color: #737a72; + color: var(--muted); padding: 7px 12px 8px; } .sidebar-note { @@ -971,7 +994,7 @@ img { .prose li { font-size: 16px; line-height: 1.8; - color: #4c584e; + color: var(--muted); } .prose p + p { margin-top: 19px; @@ -1004,9 +1027,9 @@ img { .prose code { font-family: var(--font-mono); font-size: 0.82em; - background: #eaf0e5; - color: #375534; - border: 1px solid #dbe4d6; + background: var(--soft-green); + color: var(--ink); + border: 1px solid var(--line); padding: 2px 4px; border-radius: 3px; overflow-wrap: anywhere; @@ -1024,8 +1047,8 @@ img { } .callout { padding: 19px 21px; - border-left: 2px solid #adbda5; - background: #eff1e9; + border-left: 2px solid var(--panel-line); + background: var(--paper-deep); margin-block: 26px; } .callout > strong { @@ -1065,11 +1088,11 @@ td { } th { font-weight: 600; - background: #eaf0e5; - color: #42553d; + background: var(--soft-green); + color: var(--ink); } td { - color: #4f5c4c; + color: var(--muted); } td + td, th + th { @@ -1094,7 +1117,7 @@ tr:last-child td { flex-direction: column; gap: 10px; padding: 19px; - background: white; + background: var(--surface); } .scope-map > div + div { border-left: 1px solid var(--line); @@ -1152,7 +1175,7 @@ tr:last-child td { gap: 0; margin-block: 15px 27px; border: 1px solid var(--line); - background: white; + background: var(--surface); border-radius: 5px; } .docs-entrypoints > a { @@ -1264,7 +1287,7 @@ tr:last-child td { } .next-steps { border: 1px solid var(--line); - background: white; + background: var(--surface); border-radius: 5px; margin-block: 26px; overflow: hidden; @@ -1353,7 +1376,7 @@ tr:last-child td { margin: 0; padding: 16px 20px; font-size: 11px; - background: #f4f6f0; + background: var(--paper-deep); color: var(--muted); line-height: 1.7; } @@ -1455,7 +1478,7 @@ tr:last-child td { .operation-record { padding: 25px; background: var(--soft-green); - border: 1px solid #cedbc8; + border: 1px solid var(--line); margin-block: 25px; } .operation-record > code { @@ -1472,7 +1495,7 @@ tr:last-child td { .operation-record dl > div { display: flex; gap: 22px; - border-top: 1px solid #cdd9c8; + border-top: 1px solid var(--line); padding: 13px 0; font-size: 13px; } @@ -1670,7 +1693,7 @@ tr:last-child td { gap: 35px; } .start-grid { - grid-template-columns: 1fr; + grid-template-columns: minmax(0, 1fr); gap: 35px; } .start-grid .code-block { @@ -1954,7 +1977,7 @@ tr:last-child td { padding: 0; border: 1px solid var(--line); border-radius: 4px; - background: white; + background: var(--surface); } .docs-toggle { display: flex; @@ -2166,6 +2189,204 @@ tr:last-child td { font-size: 12px; } } +/* Brand story sections use Serendepify's visual language with real product evidence. */ +.hero-field { + background: radial-gradient(ellipse at 60% 24%, var(--lime-wash), transparent 40%), + repeating-linear-gradient(90deg, var(--grid-line) 0 1px, transparent 1px 88px); +} +.hero-heading .eyebrow { + text-transform: uppercase; + letter-spacing: .12em; + font-size: 10px; +} +.hero-heading .status-dot { + background: var(--coral); + box-shadow: 0 0 0 4px color-mix(in srgb, var(--coral) 12%, transparent); +} +.hero-intro .lead { + font-size: clamp(24px, 2.25vw, 32px); + line-height: 1.25; + font-family: var(--font-display), sans-serif; + font-weight: 500; +} +.hero-intro > p + p { + font-size: 17px; + line-height: 1.65; +} +.button.secondary { + background: transparent; + color: var(--ink); + border-color: var(--panel-line); +} +.button.secondary > span { + color: var(--ink); +} +.button.secondary:hover { + background: var(--surface); +} +.hero-intro .returning-link { + margin-top: 15px; + border: 0; + color: var(--muted); +} +.hero-intro .returning-link:hover { + color: var(--ink); + text-decoration: underline; +} +.hero-spec { + border-top: 1px solid var(--line); + padding-top: 20px; +} +.hero-field .tour-section { + padding-bottom: 64px; +} +.product-tour { + border-radius: 12px; + box-shadow: 0 24px 50px color-mix(in srgb, var(--ink) 10%, transparent); +} +.tour-tabs button[aria-selected="true"] > span:first-child { + color: var(--lime); +} +.capability-story { + padding-block: 80px 92px; +} +.capability-story .section-heading h2 { + max-width: 13ch; +} +.capability-columns { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + border-top: 1px solid var(--line); +} +.capability-columns article { + padding: 28px 30px 0 0; +} +.capability-columns article + article { + border-left: 1px solid var(--line); + padding-left: 30px; +} +.capability-columns .mono { + color: var(--green); +} +.capability-columns h3 { + font-size: 23px; + letter-spacing: -.045em; + line-height: 1.2; + margin-top: 25px; +} +.capability-columns p { + color: var(--muted); + font-size: 16px; + line-height: 1.7; + margin-top: 15px; +} +.direction-section { + display: grid; + grid-template-columns: .65fr 1.35fr; + gap: 60px; + padding-block: 44px 54px; + border-block: 1px solid var(--line); +} +.direction-label { + display: flex; + align-items: flex-start; + flex-direction: column; + gap: 16px; +} +.direction-badge { + border: 1px solid var(--panel-line); + border-radius: 5px; + padding: 7px 10px; + font: 11px/1.4 var(--font-mono), monospace; + color: var(--green); +} +.direction-section h2 { + font-size: clamp(30px, 3vw, 42px); + line-height: 1.15; + letter-spacing: -.04em; +} +.direction-section p { + max-width: 640px; + color: var(--muted); + font-size: 16px; + line-height: 1.8; + margin-top: 20px; +} +.direction-section .text-link { + margin-top: 14px; +} +.company-link { + text-decoration: underline; + text-underline-offset: 3px; +} +.company-link:hover { + color: var(--ink); +} +.start-grid .button { + background: var(--lime); + color: var(--ink); + border-color: var(--lime); +} +.start-grid .button > span { + color: var(--ink); +} +.start-grid .button:hover { + background: var(--light-ink); + border-color: var(--light-ink); +} +@media (max-width: 950px) { + .direction-section { + grid-template-columns: 1fr; + gap: 28px; + } + .direction-label { + flex-direction: row; + align-items: center; + flex-wrap: wrap; + } +} +@media (max-width: 700px) { + .capability-story { + padding-block: 54px; + } + .capability-columns { + grid-template-columns: 1fr; + } + .capability-columns article { + padding: 24px 0; + } + .capability-columns article + article { + border-left: 0; + border-top: 1px solid var(--line); + padding-left: 0; + } + .capability-columns h3 { + margin-top: 12px; + } + .capability-columns p { + margin-top: 10px; + } + .hero-field .tour-section { + padding-bottom: 44px; + } + .direction-section { + padding-block: 32px; + gap: 24px; + } + .hero-intro .actions { + gap: 10px; + } + .hero-intro .actions .button { + flex: 1 1 180px; + } +} +@media (prefers-contrast: more), (forced-colors: active) { + .hero-heading em { + color: var(--ink); + -webkit-text-stroke: 0; + } +} + @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; diff --git a/app/layout.test.tsx b/app/layout.test.tsx index 60eb5df..e153951 100644 --- a/app/layout.test.tsx +++ b/app/layout.test.tsx @@ -1,8 +1,9 @@ import { beforeAll, describe, expect, it, vi } from "vitest"; vi.mock("next/font/google", () => ({ - Geist: () => ({ variable: "--font-geist-sans" }), - Geist_Mono: () => ({ variable: "--font-geist-mono" }), + Hanken_Grotesk: () => ({ variable: "--font-brand-body" }), + Schibsted_Grotesk: () => ({ variable: "--font-brand-display" }), + JetBrains_Mono: () => ({ variable: "--font-brand-mono" }), })); import { render, screen } from "@testing-library/react"; diff --git a/app/layout.tsx b/app/layout.tsx index 019ac32..1967bd0 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,21 +1,34 @@ import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; +import { Hanken_Grotesk, JetBrains_Mono, Schibsted_Grotesk } from "next/font/google"; import "./globals.css"; -const geistSans = Geist({ - variable: "--font-geist-sans", +const bodyFont = Hanken_Grotesk({ + variable: "--font-brand-body", subsets: ["latin"], }); -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", +const displayFont = Schibsted_Grotesk({ + variable: "--font-brand-display", + subsets: ["latin"], +}); + +const monoFont = JetBrains_Mono({ + variable: "--font-brand-mono", subsets: ["latin"], }); export const metadata: Metadata = { - title: "GroundControl | Open-source agentic deployment with MCP + OAuth", + metadataBase: new URL("https://trygroundcontrol.serendepify.com"), + openGraph: { + type: "website", + siteName: "GroundControl", + title: "Put your agents to work | GroundControl", + description: "Deploy and operate on infrastructure you own. Start on your computer or a Linux server, bring a project from a folder or GitHub, and connect your agent.", + }, + twitter: { card: "summary_large_image" }, + title: "GroundControl | Agentic deployment on infrastructure you own", description: - "Open-source agentic deployment for Docker Compose infrastructure, with scoped OAuth and MCP access for software agents.", + "Connect your agents to your applications through MCP and OAuth. Inspect workloads, run supported deployments, and verify results on infrastructure you own. Open source and self-hosted.", icons: { icon: "/favicon.svg", shortcut: "/favicon.svg", @@ -28,10 +41,11 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - - + + Skip to content diff --git a/app/opengraph-image.tsx b/app/opengraph-image.tsx new file mode 100644 index 0000000..ee75aa5 --- /dev/null +++ b/app/opengraph-image.tsx @@ -0,0 +1,26 @@ +import { ImageResponse } from "next/og"; + +export const alt = "GroundControl — Put your agents to work. Deploy and operate on infrastructure you own."; +export const size = { width: 1200, height: 630 }; +export const contentType = "image/png"; + +export default function Image() { + return new ImageResponse( +- - Open-source agentic deployment -
-- Discover your applications, choose what to manage, and let your - agents help operate them. -
-- GroundControl is a self-hosted control plane for your VPS. It - gives agents controlled access through OAuth and MCP, so approved - work can move from a request to a verified result without repeated - access and credential handoffs. -
-+ + Open-source agentic deployment +
++ Deploy and operate on infrastructure you own. +
++ Connect ChatGPT or a compatible MCP agent to your applications. + Give it the context and tools to deploy changes, inspect + workloads, and verify the result. You choose its + access. Your infrastructure stays yours. +
+Connect your workloads. Put your agent to work.
+ The product today · actual interface
- A working connection to your infrastructure
+
01 / From instruction to execution
++ GroundControl connects your application’s source, containers, + configuration, and public address. Your agent works from that + shared context, with tools to carry an authorized request through + to a result you can inspect.
- Explore the product{text}
+Installation is the beginning
+02 / Start with what you have
- The local host is connected. GroundControl can now help you - understand what is running and bring one application into its - control plane. + Start on your computer or connect an existing Linux server. + Add the application you’re building, then decide where and how + its deployments run.
The GroundControl approach
+03 / Autonomy without surrender
- GroundControl connects the source, runtime and public route to - one workload identity. Your team and your agents can work from - that shared context. + Bring a project from your computer or GitHub. Connect its + existing deployments or launch a new instance on your own + infrastructure. Keep your sources and environments together.
- You choose the scope. The control plane holds the infrastructure - credentials and records execution. Verification shows what - worked and what still needs attention. + MCP gives your agent the tools. OAuth defines its access. You + can work through the interface or your agent, using the same + application identity and recorded results. Review and revoke + access from the Agents workspace.
Read the philosophy and core concepts → @@ -142,17 +196,18 @@ export default function Home() {Used on a real VPS
+04 / Evidence from a real VPS
- GroundControl deployed RentAWeekend from a GitHub push. ChatGPT - connected through MCP to inspect its health and read the operation - record. + For managed workloads with merge automation enabled, a signed + GitHub push starts a deployment your agent can follow. In this + recorded example, GroundControl deployed RentAWeekend, and ChatGPT + inspected its health and operation record through MCP.
+ Serendepify’s vision is a system that understands service relationships, + tests affected customer journeys, and helps recover from regressions + within an operator’s policy. This is the direction for Autopilot, + not a promise of unattended recovery in today’s release. +
+ Explore the Serendepify vision +Start with one host and one application
- Install privately, claim ownership, and choose the first - workload. + Install GroundControl, choose an application, and connect your + agent. Start with a health check, then explore the operations + your workload supports.
Follow the installation guide @@ -266,13 +323,13 @@ export default function Home() {
- Linux · Docker · root or sudo
+ Choose this computer or a remote Linux server.
- Read the installation guide for prerequisites and host access.
+ macOS / Linux · Windows through WSL · Docker for local installs.
- GroundControl is a privileged host operations tool. Its canonical
- Compose file mounts the Docker socket and host directories such as{" "}
- /opt, /etc and /var/www.
- Install it on a host you intend it to manage. The MCP grant later
- exposes a much narrower set of operations to an agent.
-
- SSH into your VPS, then run this there. The script downloads the
- published image, writes installation files under{" "}
- /opt/groundcontrol, creates persistent database
- storage and starts the container on 127.0.0.1:3003.
-
For an agent or script that needs structured output, use:
-
- Look for claim_required, healthy container checks,
- a claimUrl and its expiry. The claim is single-use
- and lasts 30 minutes by default. Keep its token private.
-
- In a second terminal on your own computer, open a tunnel. Replace{" "}
- YOUR_USER and YOUR_VPS_IP with the SSH
- account and address you normally use.
-
- Leave that terminal running. Open the installer’s full{" "}
- http://127.0.0.1:3003/claim#token=… URL in your
- computer’s browser. The URL reaches the VPS through your tunnel;
- it is not a public management endpoint.
-
- If local port 3003 is occupied, use{" "}
-
- ssh -N -L 13003:127.0.0.1:3003 YOUR_USER@YOUR_VPS_IP
- {" "}
- and change only the port in the claim URL to 13003.
-
- On Claim GroundControl, enter an administrator - username, a password and its confirmation. The password requires - at least 12 characters with upper and lower case letters, a number - and a symbol. The installing agent should not retain it. -
-- The claim code is read from the URL fragment. Submit the form to - establish ownership. If the claim expired before you used it, - rerun the installer on that still-unclaimed instance for a new - claim; an already-claimed instance uses its existing login. -
-- Onboarding opens after claim. The local host should already be - enrolled. You do not need to paste its SSH private key back into - GroundControl. Additional remote servers can be added separately - through Add server. -
-- Run these read-only checks on the VPS. Replace the port if you - changed it during installation. -
-- Continue with{" "} - After installation to - review the host scan and choose your first application. Remote - agents need{" "} - a reachable HTTPS address;{" "} - for a private evaluation, keep using the tunnel. -
- > - ), - }, - ], - }, + ...setupGuides, publishing: { + updated: "20 October 2026", title: "Give your instance a stable HTTPS address", description: "Publish the control plane from onboarding, then verify the address your agent client will use for MCP and OAuth.", @@ -198,7 +33,7 @@ export const guides: RecordAfter claim, continue to the onboarding step titled{" "} - Publish this GroundControl instance. Choose a + Publish this GroundControl instance on a Linux server installation. Desktop installations remain local; this publishing flow is for servers. Choose a method appropriate for the host and DNS you control.
Local GroundControl manages Docker workloads. It does not manage native Mac or Windows services. On a server, GroundControl is a privileged host operations tool; install it on infrastructure you intend it to manage.
+ > }, + { id: "install", title: "1. Run the launcher on your computer", body: <> +Choose this computer or a remote server when prompted. Local setup uses Docker. Remote setup connects through SSH, installs GroundControl on the server and opens the private tunnel for you.
+You can also choose the destination directly:
+The launcher prints a link on 127.0.0.1. A new instance opens setup; an instance you already own opens login. Local setup writes its configuration to .groundcontrol-desktop in the current folder by default. Retain that folder and the Docker database volume.
Open the complete link printed by the launcher in your browser on the same computer. Its one-time claim token establishes ownership; keep the link private.
+The remote server stays private unless you deliberately publish it. Rerunning the launcher reconnects to an existing installation; it does not upgrade it.
+ > }, + { id: "claim", title: "3. Create your owner account", body: <> +On Claim GroundControl, enter an administrator username and a password with at least 12 characters, upper and lower case letters, a number and a symbol. This account belongs to your own instance.
+A claim link is single-use and expires after 30 minutes by default. Rerun the launcher for a fresh link if the unclaimed instance’s link expires. An already-claimed instance uses your existing login.
+The local Docker workspace or destination Linux host is connected automatically. Continue setup to review it; you do not need to add that same host a second time.
Use the private verification step, then review the onboarding summary. On a desktop, the Linux environment belongs to the container; it is not the operating system of your Mac or Windows PC.
+Open Projects → Add project. Pick a folder or a GitHub repository, then connect an existing deployment or launch a new one. Follow the projects and deployments guide.
+A local-only address is for you on this computer. Remote MCP clients need a reachable HTTPS endpoint. The server installation supports publishing over HTTPS; desktop onboarding stays private.
If you are already working in the destination server’s shell, use the canonical installer. Unlike the computer launcher, this command does not open an SSH tunnel on your computer.
+Add -s -- --json after bash for structured installer output. From your computer, forward the default management port with:
Open the server installer’s complete claim link through that tunnel. Server installations live under /opt/groundcontrol by default and use persistent Docker database storage. See upgrade and recovery for maintenance.
A project gives your application or product a home. Its source can be a local folder or a GitHub repository. Its deployments are instances of that application—for example, development on your computer and production on a Linux server.
+A project does not require a Compose file. Compose is one runtime method, alongside a standalone container. Registering source does not automatically build or start an application.
+ > }, + { id: "sources", title: "1. Pick a folder or GitHub repository", body: <> +Adding source records the project’s identity. It does not move your files or restart existing deployments. Removing a source link does not delete the original folder or repository.
The picker browses the selected host. A remote server’s filesystem is different from your computer’s. If Docker Desktop cannot read a local folder, allow that location in Docker Desktop’s file-sharing settings and select a smaller accessible folder. Windows users browse locations available to WSL and Docker.
Open the project and select Add deployment. Choose the host, give the instance a useful name and set its environment.
+Multiple instances may share source while running in different environments. A source folder alone is not a deployment and is not offered as a running workload to agents.
+Follow existing app enrollment or new deployment setup for the remaining runtime-specific steps.
+ > }, + { id: "discovery", title: "3. Keep discovery useful", body: <> +Discovery suggests workloads on the selected host. Compose services from the same stack appear together, and GroundControl excludes its own helper containers.
+Use Dismiss to hide a suggestion you do not want. Undo or Restore hidden brings it back. Dismissing a suggestion does not stop or remove the underlying workload.
+Projects without Compose can still be added through the folder or GitHub flow. Their runtime becomes a deployment only when you explicitly connect or launch an instance.
+ > }, + { id: "operate", title: "4. Work from a known deployment", body: <> +Confirm the instance’s host, environment, services and public URL before operating it. Existing deployments, their configuration and their recorded history remain available when you organize them into projects.
+For an external agent, authorize OAuth access to the specific deployments and capabilities it needs. Adding a project or connecting a runtime does not grant external-agent access on its own.
+ > }, + ], + }, +}; diff --git a/public/proof/project-deployments-2026-10-20.png b/public/proof/project-deployments-2026-10-20.png new file mode 100644 index 0000000..5b95702 Binary files /dev/null and b/public/proof/project-deployments-2026-10-20.png differ diff --git a/public/proof/project-import-2026-10-20.png b/public/proof/project-import-2026-10-20.png new file mode 100644 index 0000000..bf8784a Binary files /dev/null and b/public/proof/project-import-2026-10-20.png differ