diff --git a/.claude/launch.json b/.claude/launch.json new file mode 100644 index 00000000..52e73cbe --- /dev/null +++ b/.claude/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.0.1", + "configurations": [ + { + "name": "dev", + "runtimeExecutable": "pnpm", + "runtimeArgs": ["dev"], + "port": 5173 + } + ] +} diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 936b5b8d..2cdbf926 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -93,6 +93,17 @@ export default withMermaid( head: [ ["link", { rel: "icon", href: "/logo/favicon-32x32.png" }], + // Font preload for critical rendering + [ + "link", + { + rel: "preload", + href: "/fonts/Inter/Inter-roman.var.woff2", + as: "font", + type: "font/woff2", + crossorigin: "", + }, + ], // Google Analytics with Consent Mode v2 ["script", { async: "", src: "https://www.googletagmanager.com/gtag/js?id=G-JF828SKW90" }], [ @@ -190,8 +201,8 @@ export default withMermaid( { text: "Self-hosting", link: "/self-hosting/overview" }, { text: "API Reference", link: "/api-reference/introduction" }, { text: "Build and extend", link: "/dev-tools/build-plane-app/overview" }, - { text: "Plane Docs", link: "https://docs.plane.so" }, - { text: "Sign in", link: "https://app.plane.so/sign-in" }, + { text: "Plane Docs", link: "https://docs.plane.so", noIcon: true }, + { text: "Sign in", link: "https://app.plane.so/sign-in", noIcon: true }, ], sidebar: { @@ -758,13 +769,6 @@ export default withMermaid( ], }, - socialLinks: [ - { icon: "github", link: "https://github.com/makeplane/plane" }, - { icon: "discord", link: "https://discord.com/invite/A92xrEGCge" }, - { icon: "twitter", link: "https://twitter.com/planepowers" }, - { icon: "linkedin", link: "https://www.linkedin.com/company/planepowers/" }, - ], - search: searchConfig, editLink: { diff --git a/docs/.vitepress/theme/components/Card.vue b/docs/.vitepress/theme/components/Card.vue index 015bf1d6..b79833d3 100644 --- a/docs/.vitepress/theme/components/Card.vue +++ b/docs/.vitepress/theme/components/Card.vue @@ -33,6 +33,7 @@ const customSvgIcons = { `, coolify: ``, + github: ``, // Add more icons as needed }; diff --git a/docs/.vitepress/theme/components/TabNav.vue b/docs/.vitepress/theme/components/TabNav.vue new file mode 100644 index 00000000..46b2d433 --- /dev/null +++ b/docs/.vitepress/theme/components/TabNav.vue @@ -0,0 +1,42 @@ + + + diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts index 22166cfd..c92fb1d0 100644 --- a/docs/.vitepress/theme/index.ts +++ b/docs/.vitepress/theme/index.ts @@ -12,6 +12,7 @@ import ResponsePanel from "./components/ResponsePanel.vue"; import Card from "./components/Card.vue"; import CardGroup from "./components/CardGroup.vue"; import CookieConsent from "./components/CookieConsent.vue"; +import TabNav from "./components/TabNav.vue"; /** * Adds 'api-page' class to hide the aside on API reference pages @@ -110,6 +111,7 @@ export default { extends: DefaultTheme, Layout() { return h(DefaultTheme.Layout, null, { + "layout-top": () => h(TabNav), "layout-bottom": () => h(CookieConsent), }); }, diff --git a/docs/.vitepress/theme/style.css b/docs/.vitepress/theme/style.css index df1dc05e..b294648f 100644 --- a/docs/.vitepress/theme/style.css +++ b/docs/.vitepress/theme/style.css @@ -93,45 +93,13 @@ } /* ================================================ - SATOSHI FONT + INTER VARIABLE FONT ================================================ */ @font-face { - font-family: "Satoshi"; - src: - url("/fonts/Satoshi/Satoshi-Light.woff2") format("woff2"), - url("/fonts/Satoshi/Satoshi-Light.woff") format("woff"); - font-weight: 300; - font-style: normal; - font-display: swap; -} - -@font-face { - font-family: "Satoshi"; - src: - url("/fonts/Satoshi/Satoshi-Regular.woff2") format("woff2"), - url("/fonts/Satoshi/Satoshi-Regular.woff") format("woff"); - font-weight: 400; - font-style: normal; - font-display: swap; -} - -@font-face { - font-family: "Satoshi"; - src: - url("/fonts/Satoshi/Satoshi-Medium.woff2") format("woff2"), - url("/fonts/Satoshi/Satoshi-Medium.woff") format("woff"); - font-weight: 500; - font-style: normal; - font-display: swap; -} - -@font-face { - font-family: "Satoshi"; - src: - url("/fonts/Satoshi/Satoshi-Bold.woff2") format("woff2"), - url("/fonts/Satoshi/Satoshi-Bold.woff") format("woff"); - font-weight: 700; + font-family: "Inter"; + src: url("/fonts/Inter/Inter-roman.var.woff2") format("woff2-variations"); + font-weight: 100 900; font-style: normal; font-display: swap; } @@ -187,12 +155,79 @@ /* Fonts */ --vp-font-family-base: - "Satoshi", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; + "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; + --vp-font-family-heading: + "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; --vp-font-family-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; } +/* ================================================ + TYPOGRAPHY OPTIMIZATION + ================================================ */ + +/* Enable Inter's OpenType features for better readability */ +body { + font-feature-settings: "cv01", "cv02", "cv03", "cv04", "ss01", "ss03"; +} + +/* Headings use Inter with weight hierarchy and tight tracking */ +.vp-doc h1, +.vp-doc h2, +.vp-doc h3, +.vp-doc h4, +.vp-doc h5, +.vp-doc h6, +.VPNavBar .title, +.VPHero .name, +.VPHero .tagline { + font-family: var(--vp-font-family-heading); +} + +.vp-doc h1, +.VPHero .name { + font-weight: 700; + letter-spacing: -0.025em; + line-height: 1.2; +} + +.vp-doc h2, +.VPHero .tagline { + font-weight: 650; + letter-spacing: -0.02em; + line-height: 1.3; +} + +.vp-doc h3 { + font-weight: 600; + letter-spacing: -0.015em; + line-height: 1.35; +} + +.vp-doc h4, +.vp-doc h5, +.vp-doc h6 { + font-weight: 600; + letter-spacing: -0.01em; + line-height: 1.4; +} + +/* Body text: optimized spacing for readability at 16px */ +.vp-doc p, +.vp-doc li { + line-height: 1.75; + letter-spacing: -0.011em; + word-spacing: 0.01em; +} + +/* Navbar title: match heading style */ +.VPNavBar .title { + font-weight: 600; + letter-spacing: -0.015em; +} + + /* Dark mode */ .dark { --vp-c-bg: #0a0a0a; @@ -581,85 +616,378 @@ div[class*="language-"] > span.lang { } /* ================================================ - SEARCH BOX WIDTH IN HEADER + NAVBAR TWEAKS ================================================ */ -/* Make the header search box wider */ -.DocSearch.DocSearch-Button { - justify-content: space-between !important; +/* Center search area in desktop navbar and make the input wider. */ +@media (min-width: 960px) { + .VPNavBarSearch.search { +.VPNavBarSearch.search #docsearch { + width: 100%; + max-width: 320px; + } justify-content: center; + flex: 1 1 520px; + min-width: 300px; + max-width: 520px; + margin-left: auto; + margin-right: auto; + padding-left: 0 !important; + } + + .VPNavBarSearch.search #local-search, + .VPNavBarSearch.search #docsearch { + width: 100%; + max-width: 320px; + } + + .VPNavBarSearch.search .DocSearch.DocSearch-Button { + width: 100% !important; + } } -@media (min-width: 768px) { +/* Keep Sign in as a simple CTA without changing navbar height behavior. */ +.VPNavBarMenuLink.VPLink[href*="sign-in"], +a.VPLink.VPNavBarMenuLink[href*="sign-in"] { + display: inline-flex; + align-items: center; + align-self: center; + margin-left: 8px; + margin-top: 0 !important; + margin-bottom: 0 !important; + padding: 0 12px !important; + height: 32px; + line-height: 32px; + border-radius: 6px; + background: var(--vp-c-brand-1); + color: #ffffff !important; + font-weight: 500; + text-decoration: none !important; +} + +.VPNavBarMenuLink.VPLink[href*="sign-in"]:hover, +a.VPLink.VPNavBarMenuLink[href*="sign-in"]:hover { + background: var(--vp-c-brand-2); + text-decoration: none !important; +} + +/* Use mobile nav pattern on tablet widths to prevent header overflow. */ +@media (min-width: 768px) and (max-width: 959px) { + .VPNavBarMenu { + display: none !important; + } + + .VPNavBarHamburger { + display: flex !important; + } + + .VPNavScreen { + display: block !important; + } + + .VPNavBarSearch { + flex-grow: 1 !important; + padding-left: 12px !important; + } + .DocSearch.DocSearch-Button { - width: 230px !important; + width: min(100%, 240px) !important; } } -@media (min-width: 1024px) { - .DocSearch.DocSearch-Button { - width: 310px !important; +/* ================================================ + TAB NAVIGATION BAR + ================================================ */ + +:root { + --tab-nav-height: 44px; +} + +.tab-nav { + position: fixed; + top: var(--vp-nav-height); + left: 0; + right: 0; + z-index: var(--vp-z-index-nav); + height: var(--tab-nav-height); + background: var(--vp-c-bg); + border-bottom: 1px solid var(--vp-c-divider); +} + +.tab-nav-wrapper { + height: 100%; + padding: 0 8px 0 24px; +} + +@media (min-width: 768px) { + .tab-nav-wrapper { + padding: 0 32px; + } +} + +.tab-nav-container { + display: flex; + margin: 0 auto; + max-width: calc(var(--vp-layout-max-width) - 64px); + height: 100%; +} + +.tab-nav-content { + flex-grow: 1; + min-width: 0; +} + +@media (min-width: 960px) { + .Layout:has(.VPContent.has-sidebar) .tab-nav-wrapper { + padding: 0; + } + + .Layout:has(.VPContent.has-sidebar) .tab-nav-container { + max-width: 100%; + } + + .Layout:has(.VPContent.has-sidebar) .tab-nav-content { + padding-left: 32px; + padding-right: 32px; } } +@media (min-width: 1440px) { + .Layout:has(.VPContent.has-sidebar) .tab-nav-content { + padding-left: max(32px, calc((100% - (var(--vp-layout-max-width) - 64px)) / 2)); + padding-right: calc((100vw - var(--vp-layout-max-width)) / 2 + 32px); + } +} + +@media (max-width: 959px) { + .tab-nav { + display: none; + } +} + +.tab-nav-inner { + width: 100%; + height: 100%; + display: flex; + align-items: center; + gap: 32px; + overflow-x: auto; + scrollbar-width: none; +} + +.tab-nav-inner::-webkit-scrollbar { + display: none; +} + +.tab-nav-link { + display: inline-flex; + align-items: center; + height: 100%; + font-size: 14px; + font-weight: 500; + color: var(--vp-c-text-2); + text-decoration: none !important; + padding: 0; + border-bottom: 2px solid transparent; + transition: + color 0.2s ease, + border-color 0.2s ease; + line-height: 1; +} + +.tab-nav-link:hover { + color: var(--vp-c-text-1); + text-decoration: none !important; +} + +.tab-nav-link.active { + color: var(--vp-c-brand-1); + border-bottom-color: var(--vp-c-brand-1); +} + /* ================================================ - SIGN IN BUTTON STYLING + TAB NAV - LAYOUT OFFSET OVERRIDES ================================================ */ -/* Target the Sign in link using multiple class combinations */ -.VPNavBarMenuLink.VPLink[href*="sign-in"], -a.VPLink.VPNavBarMenuLink[href*="sign-in"], -.VPNavBarMenu .VPLink[href="https://app.plane.so/sign-in"] { - background: #006399 !important; +/* Push content down to account for tab nav */ +@media (min-width: 960px) { + .VPContent { + padding-top: calc(var(--vp-nav-height) + var(--tab-nav-height)) !important; + } +} + +/* Adjust sidebar internal padding */ +@media (min-width: 960px) { + .VPSidebar { + padding-top: calc(var(--vp-nav-height) + var(--tab-nav-height)) !important; + } +} + +/* Adjust local nav (mobile breadcrumb bar at 960-1280px) */ +@media (min-width: 960px) { + .VPLocalNav { + top: calc(var(--vp-nav-height) + var(--tab-nav-height)) !important; + } +} + +/* ================================================ + HIDE SECTION NAV LINKS ON DESKTOP (TAB BAR REPLACES THEM) + ================================================ */ + +@media (min-width: 960px) { + .VPNavBarMenuLink.VPLink[href="/self-hosting/overview"], + a.VPLink.VPNavBarMenuLink[href="/self-hosting/overview"], + .VPNavBarMenuLink.VPLink[href="/api-reference/introduction"], + a.VPLink.VPNavBarMenuLink[href="/api-reference/introduction"], + .VPNavBarMenuLink.VPLink[href*="/dev-tools/"], + a.VPLink.VPNavBarMenuLink[href*="/dev-tools/"] { + display: none !important; + } +} + +/* ================================================ + HOME PAGE STYLES + ================================================ */ + +/* Hero Section */ +.home-hero { + padding: 80px 24px 64px; + text-align: center; + border-bottom: 1px solid var(--vp-c-divider); +} + +@media (max-width: 768px) { + .home-hero { + padding: 48px 20px 40px; + } +} + +.home-hero-content { + max-width: 640px; + margin: 0 auto; +} + +.home-hero-title { + font-family: var(--vp-font-family-heading) !important; + font-size: 48px !important; + font-weight: 700 !important; + line-height: 1.15 !important; + letter-spacing: -0.02em; + color: var(--vp-c-text-1) !important; + margin: 0 0 16px !important; + padding: 0 !important; + border: none !important; +} + +@media (max-width: 768px) { + .home-hero-title { + font-size: 36px !important; + } +} + +.home-hero-tagline { + font-size: 18px; + line-height: 1.6; + color: var(--vp-c-text-2); + margin: 0 0 32px; + max-width: 540px; + margin-left: auto; + margin-right: auto; +} + +@media (max-width: 768px) { + .home-hero-tagline { + font-size: 16px; + margin-bottom: 24px; + } +} + +.home-hero-actions { + display: flex; + gap: 12px; + justify-content: center; + flex-wrap: wrap; +} + +.home-btn-primary { + display: inline-flex; + align-items: center; + padding: 10px 24px; + font-size: 15px; + font-weight: 500; color: #ffffff !important; - padding: 6px 14px !important; - margin-top: 15px !important; - margin-bottom: 15px !important; - border-radius: 6px !important; - font-weight: 500 !important; - font-size: 14px !important; - transition: all 0.2s ease !important; - line-height: normal !important; + background: var(--vp-c-brand-1); + border-radius: 8px; text-decoration: none !important; - display: inline-flex !important; - align-items: center !important; - vertical-align: middle !important; -} - -/* Hide the external link arrow icon */ -.VPNavBarMenuLink.VPLink[href*="sign-in"] .vp-external-link-icon, -a.VPLink.VPNavBarMenuLink[href*="sign-in"] .vp-external-link-icon, -.VPNavBarMenu .VPLink[href="https://app.plane.so/sign-in"] .vp-external-link-icon, -.VPNavBarMenuLink.VPLink[href*="sign-in"] svg, -a.VPLink.VPNavBarMenuLink[href*="sign-in"] svg, -.VPNavBarMenuLink.VPLink[href*="sign-in"] .VPImage, -a.VPLink.VPNavBarMenuLink[href*="sign-in"] .VPImage { - display: none !important; + transition: all 0.2s ease; } -/* Also hide the icon using ::after if it's a pseudo-element */ -.VPNavBarMenuLink.VPLink[href*="sign-in"]::after, -a.VPLink.VPNavBarMenuLink[href*="sign-in"]::after { - display: none !important; - content: none !important; +.home-btn-primary:hover { + background: #0078b8; + box-shadow: 0 2px 8px rgba(0, 99, 153, 0.25); + text-decoration: none !important; } -.VPNavBarMenuLink.VPLink[href*="sign-in"]:hover, -a.VPLink.VPNavBarMenuLink[href*="sign-in"]:hover { - background: #0078b8 !important; - transform: translateY(-1px) !important; - box-shadow: 0 2px 8px rgba(0, 99, 153, 0.25) !important; +.home-btn-secondary { + display: inline-flex; + align-items: center; + padding: 10px 24px; + font-size: 15px; + font-weight: 500; + color: var(--vp-c-brand-1) !important; + border: 1px solid var(--vp-c-brand-1); + border-radius: 8px; text-decoration: none !important; + transition: all 0.2s ease; } -/* Dark mode variant */ -.dark .VPNavBarMenuLink.VPLink[href*="sign-in"], -.dark a.VPLink.VPNavBarMenuLink[href*="sign-in"] { - background: #006399 !important; - color: #ffffff !important; +.home-btn-secondary:hover { + background: var(--vp-c-brand-soft); + text-decoration: none !important; +} + +/* Sections */ +.home-section { + padding: 64px 24px; +} + +@media (max-width: 768px) { + .home-section { + padding: 40px 20px; + } +} + +.home-section-alt { + background: var(--vp-c-bg-soft); +} + +.home-section-inner { + max-width: 1152px; + margin: 0 auto; +} + +.home-section-title { + font-family: var(--vp-font-family-heading) !important; + font-size: 28px !important; + font-weight: 700 !important; + color: var(--vp-c-text-1) !important; + margin: 0 0 8px !important; + padding: 0 !important; + border: none !important; + letter-spacing: -0.01em; +} + +.home-section-description { + font-size: 16px; + color: var(--vp-c-text-2); + margin: 0 0 24px; + line-height: 1.6; +} + +/* Spacing between section title and card group */ +.home-section-title + .card-group { + margin-top: 24px; } -.dark .VPNavBarMenuLink.VPLink[href*="sign-in"]:hover, -.dark a.VPLink.VPNavBarMenuLink[href*="sign-in"]:hover { - background: #0078b8 !important; - box-shadow: 0 2px 8px rgba(0, 99, 153, 0.35) !important; +.home-section-description + .card-group { + margin-top: 0; } diff --git a/docs/index.md b/docs/index.md index b78340ba..a1c78aac 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,80 +1,75 @@ --- -layout: home +layout: page title: Plane Developer Documentation - API Reference & Self-Hosting Guides description: Build integrations with Plane's REST API and deploy on your infrastructure. Complete guides for self-hosting with Docker, Kubernetes, webhooks, and OAuth apps. keywords: plane developer docs, plane api, self-hosting plane, kubernetes deployment, docker compose, plane webhooks, plane oauth, project management api -hero: - name: Developer docs - text: Build, deploy, and integrate - tagline: Everything you need to self-host Plane, integrate with the REST API, and build powerful custom workflows. - actions: - - theme: brand - text: Get Started - link: /self-hosting/overview - - theme: alt - text: API Reference - link: /api-reference/introduction - -features: - - icon: 🚀 - title: Self-hosting - details: Deploy Plane on your infrastructure with Docker, Kubernetes, or other methods. Complete guides for configuration, authentication, and management. - link: /self-hosting/overview - linkText: View deployment guides - - icon: 📡 - title: REST API - details: 180+ endpoints to manage projects, work items, cycles, modules, and more. - link: /api-reference/introduction - linkText: Explore API docs - - icon: 🔧 - title: Webhooks - details: Automate workflows with real-time webhooks for project events, work item updates, and team activities. - link: /dev-tools/intro-webhooks - linkText: Configure webhooks - - icon: 🔌 - title: OAuth Apps - details: Build custom integrations using OAuth 2.0. Complete guides for app registration, token management, and API access. - link: /dev-tools/build-plane-app/overview - linkText: Build an app - - icon: 🤖 - title: MCP Server - details: Integrate Plane with AI agents using Model Context Protocol for intelligent project management automation. - link: /dev-tools/mcp-server - linkText: Setup MCP --- -## Quick start guides - -
- -
- -### Deploy with Docker - -Get Plane running in minutes with Docker Compose - -[Docker Compose](/self-hosting/methods/docker-compose) - +
+
+

Plane Developer Platform

+

Build integrations, deploy self-hosted instances, and extend Plane with APIs, webhooks, and AI agents.

+ +
-
- -### Configure Your Instance - -Set up authentication and connect external services to your Plane deployment. - -[Instance Admin](/self-hosting/govern/instance-admin) • [Configure SSO](/self-hosting/govern/authentication) - +
+
+

Explore the docs

+ + + Deploy Plane on your infrastructure with Docker, Kubernetes, or Podman. Full control over your data and configuration. + + + 180+ REST API endpoints to manage projects, work items, cycles, modules, and more. Complete with code examples. + + + Create OAuth apps, set up webhooks, build AI agents, and connect Plane to your tools with MCP Server. + + +
-
- -### Manage instance - -Keep your instance up-to-date with the latest features and security patches. - -[Update guide](/self-hosting/manage/upgrade-plane) • [Manage licenses](/self-hosting/manage/manage-licenses/activate-pro-and-business) - +
+
+

Popular guides

+

Jump into the most common workflows to get up and running quickly.

+ + + Get Plane running in minutes with Docker Compose. + + + Register and configure an OAuth 2.0 application. + + + Automate workflows with real-time event notifications. + + + Connect Plane to AI agents with Model Context Protocol. + + +
+
+
+

Developer resources

+ + + Explore the source code, report issues, and contribute. + + + Join the Discord community for support and discussions. + + + Official client libraries for Python and JavaScript. + + + User guides and product documentation for Plane. + + +
diff --git a/docs/public/fonts/Satoshi/Satoshi-Bold.woff b/docs/public/fonts/Satoshi/Satoshi-Bold.woff deleted file mode 100644 index bba8257f..00000000 Binary files a/docs/public/fonts/Satoshi/Satoshi-Bold.woff and /dev/null differ diff --git a/docs/public/fonts/Satoshi/Satoshi-Bold.woff2 b/docs/public/fonts/Satoshi/Satoshi-Bold.woff2 deleted file mode 100644 index 0a8db7a4..00000000 Binary files a/docs/public/fonts/Satoshi/Satoshi-Bold.woff2 and /dev/null differ diff --git a/docs/public/fonts/Satoshi/Satoshi-Medium.woff b/docs/public/fonts/Satoshi/Satoshi-Medium.woff deleted file mode 100644 index cef3226e..00000000 Binary files a/docs/public/fonts/Satoshi/Satoshi-Medium.woff and /dev/null differ diff --git a/docs/public/fonts/Satoshi/Satoshi-Medium.woff2 b/docs/public/fonts/Satoshi/Satoshi-Medium.woff2 deleted file mode 100644 index ffd0ac96..00000000 Binary files a/docs/public/fonts/Satoshi/Satoshi-Medium.woff2 and /dev/null differ diff --git a/docs/public/fonts/Satoshi/Satoshi-Regular.woff b/docs/public/fonts/Satoshi/Satoshi-Regular.woff deleted file mode 100644 index 03ac1952..00000000 Binary files a/docs/public/fonts/Satoshi/Satoshi-Regular.woff and /dev/null differ diff --git a/docs/public/fonts/Satoshi/Satoshi-Regular.woff2 b/docs/public/fonts/Satoshi/Satoshi-Regular.woff2 deleted file mode 100644 index 81c40ab0..00000000 Binary files a/docs/public/fonts/Satoshi/Satoshi-Regular.woff2 and /dev/null differ