Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
781e2b9
Updating theme
srinivaspendem Apr 23, 2026
550eb9a
Refactor documentation and improve sign-in link relocation logic
srinivaspendem Apr 23, 2026
b9b7b89
Enhance dark mode handling in theme by synchronizing document class w…
srinivaspendem Apr 23, 2026
6eede2d
Implement enhanced dark mode synchronization for header theme attribu…
srinivaspendem Apr 23, 2026
69f425d
Update documentation layout and enhance CSS for responsive design
srinivaspendem Apr 24, 2026
5732dc0
Merge branch 'master' of github.com:makeplane/docs into new-theme
srinivaspendem Apr 24, 2026
19ebb86
Refactor documentation description formatting and streamline header t…
srinivaspendem Apr 24, 2026
14e031f
fixed the bugs in the navbar and cards
srinivaspendem Apr 24, 2026
742a8ab
update padding in the right sidebar
srinivaspendem Apr 24, 2026
06aba7d
ci fix
srinivaspendem Apr 26, 2026
f141525
Merge branch 'master' of github.com:makeplane/docs into new-theme
srinivaspendem May 19, 2026
fb9e44d
Enhance documentation layout and styling
srinivaspendem May 19, 2026
9edb341
updating button colours
srinivaspendem May 20, 2026
df42801
text left
srinivaspendem May 20, 2026
01b9e28
Merge branch 'master' of github.com:makeplane/docs into new-theme
srinivaspendem Jun 9, 2026
b34a8df
ui updates
srinivaspendem Jun 9, 2026
604fae3
format update
srinivaspendem Jun 9, 2026
46a07f1
Add meta robots tag and update Vercel configuration for SEO
srinivaspendem Jun 9, 2026
42469e9
fix seo
srinivaspendem Jun 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"css.lint.unknownAtRules": "ignore",
"scss.lint.unknownAtRules": "ignore",
"less.lint.unknownAtRules": "ignore"
}
96 changes: 77 additions & 19 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/** @format */

import { copyFileSync, mkdirSync, readFileSync, readdirSync, statSync } from "fs";
import { dirname, join, relative, resolve } from "path";
import { defineConfig, type HeadConfig } from "vitepress";
import { extendConfig } from "@voidzero-dev/vitepress-theme/config";
import { tabsMarkdownPlugin } from "vitepress-plugin-tabs";

function loadEnvVar(key: string): string | undefined {
Expand Down Expand Up @@ -45,7 +48,7 @@ const searchConfig =
}
: { provider: "local" as const };

export default defineConfig({
const config = defineConfig({
title: "Plane",
description: "Modern project management software",
cleanUrls: true,
Expand Down Expand Up @@ -102,13 +105,6 @@ export default defineConfig({
crossorigin: "anonymous",
},
],
[
"link",
{
rel: "stylesheet",
href: "https://fonts.googleapis.com/css2?family=Instrument+Sans:ital,wght@0,400..700;1,400..700&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=National+Park:wght@200..800&family=Noto+Sans:ital,wght@0,100..900;1,100..900&family=Nunito+Sans:ital,opsz,wght@0,6..12,200..1000;1,6..12,200..1000&family=PT+Sans:ital,wght@0,400;0,700;1,400;1,700&family=Raleway:ital,wght@0,100..900;1,100..900&family=Roboto:ital,wght@0,100..900;1,100..900&family=Work+Sans:ital,wght@0,100..900;1,100..900&display=swap",
},
],
[
"script",
{
Expand Down Expand Up @@ -192,14 +188,49 @@ export default defineConfig({
"project management, issue tracking, sprint management, agile, scrum, create projects, track sprints",
},
],
[
"meta",
{
name: "robots",
content: "index, follow",
},
],
/**
* SSG inlines OSSHeader with data-theme from server isDark. Tailwind `dark:…`
* keys off [data-theme*="dark"] on that wrapper, so the bar can stay dark
* until Vue hydrates. The built-in "check-dark-mode" also only add()s
* html.dark. Run in setTimeout(0) so it executes after that script, then
* clear stale data-theme as soon as the bar exists.
*/
[
"script",
{},
`!function(){setTimeout(function(){
var k="vitepress-theme-appearance";
var p=localStorage.getItem(k)||"dark";
var m=matchMedia("(prefers-color-scheme: dark)").matches;
var d=!p||p==="auto"?m:p==="dark";
document.documentElement.classList.toggle("dark",d);
function bar(n){
var h=document.querySelector(".docs-layout header");
if(h&&h.parentElement){
var w=h.parentElement;
if(d)w.setAttribute("data-theme","dark");else w.removeAttribute("data-theme");
return;
}
if(n<200&&document.readyState==="loading")requestAnimationFrame(function(){bar(n+1)});
}bar(0);
},0);}();`,
],
],

themeConfig: {
variant: "voidzero",
logo: {
light: "https://media.docs.plane.so/logo/new-logo-white.png",
dark: "https://media.docs.plane.so/logo/new-logo-dark.png",
},
siteTitle: "",
siteTitle: "Plane",

Comment on lines 227 to 234

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

@voidzero-dev/vitepress-theme themeConfig.variant supported values list

💡 Result:

The supported values for themeConfig.variant in @voidzero-dev/vitepress-theme are strings corresponding to VoidZero projects, such as "viteplus", "vite", "vitest". Additional likely values based on project context include "rolldown" and "oxc", as the theme is designed for Vite+, Vite, Vitest, Rolldown, and Oxc. The variant controls branding colors and styling via CSS selectors like :root[data-variant="vite"]. Users import specific variants like '@voidzero-dev/vitepress-theme/src/vite' in the theme entry.

Citations:


Change variant: "voidzero" to a supported value.

The @voidzero-dev/vitepress-theme package only supports variants: "vite", "viteplus", "vitest", "rolldown", and "oxc". The variant "voidzero" is not recognized and will cause incorrect theme rendering or build failures. Use one of the supported variants that matches your target project.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/.vitepress/config.ts` around lines 225 - 232, The themeConfig currently
sets variant: "voidzero", which is unsupported by `@voidzero-dev/vitepress-theme`;
update the variant property inside themeConfig to one of the supported values
("vite", "viteplus", "vitest", "rolldown", or "oxc") that best matches your
project (e.g., change variant in themeConfig from "voidzero" to "vite" or
another supported option) so the theme renders and builds correctly.

outline: {
level: [2, 3],
Expand All @@ -209,21 +240,25 @@ export default defineConfig({
search: searchConfig,

socialLinks: [
{ icon: "github", link: "https://github.com/makeplane/plane" },
{
icon: {
svg: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 9a2 2 0 0 1-2 2H6l-4 4V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2z"/><path d="M18 9h2a2 2 0 0 1 2 2v11l-4-4h-6a2 2 0 0 1-2-2v-1"/></svg>',
svg: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10 15L6.92474 18.1137C6.49579 18.548 6.28131 18.7652 6.09695 18.7805C5.93701 18.7938 5.78042 18.7295 5.67596 18.6076C5.55556 18.4672 5.55556 18.162 5.55556 17.5515V15.9916C5.55556 15.444 5.10707 15.0477 4.5652 14.9683V14.9683C3.25374 14.7762 2.22378 13.7463 2.03168 12.4348C2 12.2186 2 11.9605 2 11.4444V6.8C2 5.11984 2 4.27976 2.32698 3.63803C2.6146 3.07354 3.07354 2.6146 3.63803 2.32698C4.27976 2 5.11984 2 6.8 2H14.2C15.8802 2 16.7202 2 17.362 2.32698C17.9265 2.6146 18.3854 3.07354 18.673 3.63803C19 4.27976 19 5.11984 19 6.8V11M19 22L16.8236 20.4869C16.5177 20.2742 16.3647 20.1678 16.1982 20.0924C16.0504 20.0255 15.8951 19.9768 15.7356 19.9474C15.5558 19.9143 15.3695 19.9143 14.9969 19.9143H13.2C12.0799 19.9143 11.5198 19.9143 11.092 19.6963C10.7157 19.5046 10.4097 19.1986 10.218 18.8223C10 18.3944 10 17.8344 10 16.7143V14.2C10 13.0799 10 12.5198 10.218 12.092C10.4097 11.7157 10.7157 11.4097 11.092 11.218C11.5198 11 12.0799 11 13.2 11H18.8C19.9201 11 20.4802 11 20.908 11.218C21.2843 11.4097 21.5903 11.7157 21.782 12.092C22 12.5198 22 13.0799 22 14.2V16.9143C22 17.8462 22 18.3121 21.8478 18.6797C21.6448 19.1697 21.2554 19.5591 20.7654 19.762C20.3978 19.9143 19.9319 19.9143 19 19.9143V22Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',
},
link: "https://forum.plane.so",
},
{ icon: "github", link: "https://github.com/makeplane/plane" },
{ icon: "twitter", link: "https://twitter.com/planepowers" },
{ icon: "linkedin", link: "https://www.linkedin.com/company/planepowers/" },
{
icon: "linkedin",
link: "https://www.linkedin.com/company/planepowers/",
},
],

nav: [
{
text: "Sign in",
link: "https://app.plane.so/sign-in",
noIcon: true,
},
],

Expand Down Expand Up @@ -302,7 +337,10 @@ export default defineConfig({
text: "Search workspace",
link: "/workspaces-and-users/search-workspace",
},
{ text: "Personalize homepage", link: "/core-concepts/account/overview" },
{
text: "Personalize homepage",
link: "/core-concepts/account/overview",
},
{ text: "Power K", link: "/core-concepts/power-k" },
{
text: "Customize navigation",
Expand Down Expand Up @@ -377,7 +415,10 @@ export default defineConfig({
text: "Projects",
collapsed: true,
items: [
{ text: "Manage projects", link: "/core-concepts/projects/overview" },
{
text: "Manage projects",
link: "/core-concepts/projects/overview",
},
{
text: "Manage members",
link: "/core-concepts/projects/manage-project-members",
Expand Down Expand Up @@ -410,7 +451,10 @@ export default defineConfig({
text: "Work Items",
collapsed: true,
items: [
{ text: "Manage work items", link: "/core-concepts/issues/overview" },
{
text: "Manage work items",
link: "/core-concepts/issues/overview",
},
{
text: "Work item properties",
link: "/core-concepts/issues/properties",
Expand Down Expand Up @@ -498,7 +542,10 @@ export default defineConfig({
text: "Pages",
collapsed: true,
items: [
{ text: "Manage project pages", link: "/core-concepts/pages/overview" },
{
text: "Manage project pages",
link: "/core-concepts/pages/overview",
},
{
text: "Editor blocks",
link: "/core-concepts/pages/editor-blocks",
Expand All @@ -521,7 +568,10 @@ export default defineConfig({
text: "Time Tracking",
link: "/core-concepts/issues/time-tracking",
},
{ text: "Workflows and Approvals", link: "/workflows-and-approvals/workflows" },
{
text: "Workflows and Approvals",
link: "/workflows-and-approvals/workflows",
},
{ text: "Custom Relations", link: "/work-items/custom-relations" },
{
text: "Automations",
Expand Down Expand Up @@ -555,8 +605,14 @@ export default defineConfig({
text: "Page Inline Comments",
link: "/core-concepts/pages/inline-comments",
},
{ text: "Subscribers", link: "/communication-and-collaboration/subscribers" },
{ text: "Notifications", link: "/communication-and-collaboration/notifications" },
{
text: "Subscribers",
link: "/communication-and-collaboration/subscribers",
},
{
text: "Notifications",
link: "/communication-and-collaboration/notifications",
},
{ text: "Inbox", link: "/communication-and-collaboration/inbox" },
],
},
Expand Down Expand Up @@ -699,3 +755,5 @@ export default defineConfig({
},
},
});

export default extendConfig(config);
16 changes: 16 additions & 0 deletions docs/.vitepress/theme/Layout.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script setup lang="ts">
import { computed, useSlots } from "vue";
import VoidZeroTheme from "@voidzero-dev/vitepress-theme";

const BaseLayout = VoidZeroTheme.Layout;
const slots = useSlots();
const forwardSlotNames = computed(() => Object.keys(slots) as string[]);
</script>

<template>
<BaseLayout>
<template v-for="name in forwardSlotNames" :key="name" #[name]="data">
<slot :name="name" v-bind="data || {}" />
</template>
</BaseLayout>
</template>
64 changes: 54 additions & 10 deletions docs/.vitepress/theme/components/Card.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
<!-- @format -->

<script setup>
import { computed } from "vue";
import * as LucideIcons from "lucide-vue-next";

const props = defineProps({
title: String,
icon: String,
/** Doc path or full URL */
href: String,
/** Alias for `href` (common in markdown) */
link: String,
/** When set, used instead of the default slot for body text */
description: String,
/** Bottom link label (shown with →). Home feature cards only. */
cta: String,
});

const hasDestination = computed(() => Boolean((props.link || props.href || "").toString().trim()));

const resolvedHref = computed(() => {
const h = (props.link || props.href || "").toString().trim();
return h;
});

// Custom SVG icons for brands
Expand Down Expand Up @@ -44,18 +60,46 @@ const IconComponent = computed(() => {
</script>

<template>
<a :href="href" class="card-link">
<div v-if="icon" class="card-icon">
<!-- Render custom SVG if available -->
<component
:is="hasDestination ? 'a' : 'div'"
:href="hasDestination ? resolvedHref : undefined"
class="card-link"
:class="{ 'card-link--with-cta': cta }"
>
Comment on lines +63 to +68

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

External links open in same tab without rel="noopener".

The homepage uses link="https://developers.plane.so/self-hosting/overview" which is external. The rendered <a> lacks target and rel attributes, so external destinations open in the same tab (losing docs context) and miss rel="noopener noreferrer" hardening.

♻️ Proposed refinement
+<script setup>
+// ...existing code...
+const isExternal = computed(() => /^https?:\/\//i.test(resolvedHref.value));
+</script>

 <template>
   <component
     :is="hasDestination ? 'a' : 'div'"
     :href="hasDestination ? resolvedHref : undefined"
+    :target="hasDestination && isExternal ? '_blank' : undefined"
+    :rel="hasDestination && isExternal ? 'noopener noreferrer' : undefined"
     class="card-link"
     :class="{ 'card-link--with-cta': cta }"
   >
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/.vitepress/theme/components/Card.vue` around lines 63 - 68, The anchor
rendered by Card.vue uses hasDestination and resolvedHref but doesn't set
target/rel for external URLs; update the component rendering logic (using
hasDestination, resolvedHref and cta) to detect external links (e.g.,
resolvedHref startsWith('http') or origin !== current origin) and, only for
external destinations, set target="_blank" and rel="noopener noreferrer" on the
<a> element while leaving internal links unchanged.

<div v-if="icon" class="card-icon" aria-hidden="true">
<div v-if="customSvgIcons[icon]" v-html="customSvgIcons[icon]"></div>
<!-- Otherwise render Lucide icon -->
<component v-else :is="IconComponent" :size="24" />
<component v-else :is="IconComponent" :size="24" stroke-width="1.5" />
</div>
<h3 class="card-title">
{{ title }}
</h3>
<p class="card-description">
<h3 class="card-title">{{ title }}</h3>
<p v-if="description" class="card-description">
{{ description }}
</p>
<p v-else class="card-description">
<slot />
</p>
</a>
<span v-if="cta" class="card-cta">{{ cta }} →</span>
</component>
</template>

<style scoped>
.card-cta {
color: #006399 !important;
font-weight: 600;
}

.card-link:hover .card-cta {
color: #0078b8 !important;
}
</style>

<style>
html.dark .card-link .card-cta,
[data-theme="dark"] .card-link .card-cta {
color: #2893cc !important;
}

html.dark .card-link:hover .card-cta,
[data-theme="dark"] .card-link:hover .card-cta {
color: #3aa5d4 !important;
}
</style>
17 changes: 13 additions & 4 deletions docs/.vitepress/theme/components/CardGroup.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
<script setup>
defineProps({
import { computed } from "vue";

const props = defineProps({
cols: {
type: [Number, String],
default: 2,
},
/** Alias for `cols` (e.g. `<CardGroup columns="3">`) */
columns: {
type: [Number, String],
default: undefined,
},
});

const columnCount = computed(() => props.columns ?? props.cols);
</script>

<template>
<div
class="card-group"
:class="{
'card-group-2': cols == 2,
'card-group-3': cols == 3,
'card-group-4': cols == 4,
'card-group-2': columnCount == 2,
'card-group-3': columnCount == 3,
'card-group-4': columnCount == 4,
}"
>
<slot />
Expand Down
Loading
Loading