2025-12-18 08:52:32 +01:00
import { defineConfig , HeadConfig } from 'vitepress' ;
2025-08-12 18:09:19 +02:00
import githubLinksPlugin from './plugins/github-links' ;
import { readFileSync } from 'fs' ;
import { resolve } from 'path' ;
import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs' ;
import {
groupIconMdPlugin ,
2025-09-10 17:57:52 +02:00
groupIconVitePlugin ,
localIconLoader
2025-08-12 18:09:19 +02:00
} from 'vitepress-plugin-group-icons' ;
import { team } from './team.ts' ;
2026-04-22 10:02:06 +02:00
import { adopters } from './adopters.ts' ;
2025-12-18 08:52:32 +01:00
import { taskDescription , taskName , ogUrl , ogImage } from './meta.ts' ;
2025-08-12 18:09:19 +02:00
import { fileURLToPath , URL } from 'node:url' ;
2026-04-15 16:39:20 -03:00
import llmstxt from 'vitepress-plugin-llms' ;
2025-08-12 18:09:19 +02:00
const version = readFileSync (
resolve ( __dirname , '../../internal/version/version.txt' ) ,
'utf8'
) . trim ( ) ;
const urlVersion =
process . env . NODE_ENV === 'development'
? {
current : 'https://taskfile.dev/' ,
next : 'http://localhost:3002/'
}
: {
current : 'https://taskfile.dev/' ,
next : 'https://next.taskfile.dev/'
} ;
// https://vitepress.dev/reference/site-config
export default defineConfig ( {
title : taskName ,
description : taskDescription ,
lang : 'en-US' ,
head : [
2026-01-25 14:16:23 +01:00
// Favicon ICO for legacy browsers (auto-discovery)
[ 'link' , { rel : 'icon' , href : '/favicon.ico' , sizes : '48x48' } ] ,
// Favicon SVG for modern browsers (scalable)
[ 'link' , { rel : 'icon' , href : '/img/logo.svg' , type : 'image/svg+xml' } ] ,
// Apple Touch Icon for iOS devices
[ 'link' , { rel : 'apple-touch-icon' , href : '/img/logo.png' } ] ,
2025-08-12 18:09:19 +02:00
[
'meta' ,
{ name : 'author' , content : ` ${ team . map ( ( c ) = > c . name ) . join ( ', ' ) } ` }
] ,
2025-12-18 08:52:32 +01:00
// Open Graph
[ 'meta' , { property : 'og:type' , content : 'website' } ] ,
2026-01-25 14:16:23 +01:00
[ 'meta' , { property : 'og:site_name' , content : 'Task' } ] ,
2025-12-18 08:52:32 +01:00
[ 'meta' , { property : 'og:image' , content : ogImage } ] ,
// Twitter Card
[ 'meta' , { name : 'twitter:card' , content : 'summary_large_image' } ] ,
[ 'meta' , { name : 'twitter:site' , content : '@taskfiledev' } ] ,
[ 'meta' , { name : 'twitter:image' , content : ogImage } ] ,
2025-08-12 18:09:19 +02:00
[
'meta' ,
{
name : 'keywords' ,
content :
'task runner, build tool, taskfile, yaml build tool, go task runner, make alternative, cross-platform build tool, makefile alternative, automation tool, ci cd pipeline, developer productivity, build automation, command line tool, go binary, yaml configuration'
}
] ,
2025-09-14 10:18:32 -03:00
[
"script" ,
{
defer : "" ,
2025-11-07 17:48:28 -03:00
src : "https://u.taskfile.dev/script.js" ,
2025-09-14 10:18:32 -03:00
"data-website-id" : "084030b0-0e3f-4891-8d2a-0c12c40f5933"
}
2026-01-25 14:16:23 +01:00
] ,
[
"script" ,
{ type : "application/ld+json" } ,
JSON . stringify ( {
"@context" : "https://schema.org" ,
"@type" : "WebSite" ,
"name" : "Task" ,
"url" : "https://taskfile.dev/"
} )
2025-08-12 17:58:44 -03:00
]
2025-08-12 18:09:19 +02:00
] ,
2025-12-18 08:52:32 +01:00
transformHead ( { pageData } ) {
const head : HeadConfig [ ] = [ ]
// Canonical URL dynamique
const canonicalUrl = ` https://taskfile.dev/ ${ pageData . relativePath
. replace ( /\.md$/ , '' )
. replace ( /index$/ , '' ) } `
head . push ( [ 'link' , { rel : 'canonical' , href : canonicalUrl } ] )
2026-01-24 20:44:53 -03:00
// Dynamic Open Graph and Twitter meta tags
2026-01-27 22:18:49 -03:00
const isHome = pageData . relativePath === 'index.md' ;
var pageTitle = pageData . frontmatter . title || pageData . title || taskName ;
if ( ! isHome ) {
pageTitle = ` ${ pageTitle } | ${ taskName } ` ;
}
2026-01-24 20:44:53 -03:00
const pageDescription = pageData . frontmatter . description || pageData . description || taskDescription
2026-01-27 22:18:49 -03:00
head . push ( [ 'meta' , { property : 'og:title' , content : pageTitle } ] )
2026-01-24 20:44:53 -03:00
head . push ( [ 'meta' , { property : 'og:description' , content : pageDescription } ] )
head . push ( [ 'meta' , { property : 'og:url' , content : canonicalUrl } ] )
2026-01-27 22:18:49 -03:00
head . push ( [ 'meta' , { name : 'twitter:title' , content : pageTitle } ] )
2026-01-24 20:44:53 -03:00
head . push ( [ 'meta' , { name : 'twitter:description' , content : pageDescription } ] )
2025-12-18 08:52:32 +01:00
// Noindex pour 404
if ( pageData . relativePath === '404.md' ) {
head . push ( [ 'meta' , { name : 'robots' , content : 'noindex, nofollow' } ] )
}
2026-04-22 10:02:06 +02:00
// Structured data for the adopters carousel on the homepage: an ItemList
// of Organization entities so search engines can surface Task's adopters
// directly in rich results.
if ( isHome ) {
head . push ( [
'script' ,
{ type : 'application/ld+json' } ,
JSON . stringify ( {
'@context' : 'https://schema.org' ,
'@type' : 'ItemList' ,
name : 'Organizations and projects using Task' ,
itemListOrder : 'https://schema.org/ItemListUnordered' ,
numberOfItems : adopters.length ,
itemListElement : adopters.map ( ( a , i ) = > ( {
'@type' : 'ListItem' ,
position : i + 1 ,
item : {
'@type' : 'Organization' ,
name : a.name ,
url : a.url ,
logo : a.img ,
sameAs : [ a . url ]
}
} ) )
} )
] )
}
// On the /adopters page, emit CollectionPage + ItemList (richer than the
// homepage snippet because it targets this specific URL) and FAQPage for
// the question block at the bottom of the page. Kept in sync by hand with
// components/Adopters.vue.
if ( pageData . relativePath === 'adopters.md' ) {
head . push ( [
'script' ,
{ type : 'application/ld+json' } ,
JSON . stringify ( {
'@context' : 'https://schema.org' ,
'@type' : 'CollectionPage' ,
name : 'Who uses Task' ,
url : 'https://taskfile.dev/adopters' ,
description :
'Organizations and open source projects that use Task as their build and release runner.' ,
mainEntity : {
'@type' : 'ItemList' ,
numberOfItems : adopters.length ,
itemListElement : adopters.map ( ( a , i ) = > ( {
'@type' : 'ListItem' ,
position : i + 1 ,
item : {
'@type' : 'Organization' ,
name : a.name ,
url : a.url ,
logo : a.img ,
description : a.description ,
sameAs : [ a . url ]
}
} ) )
}
} )
] )
head . push ( [
'script' ,
{ type : 'application/ld+json' } ,
JSON . stringify ( {
'@context' : 'https://schema.org' ,
'@type' : 'FAQPage' ,
mainEntity : [
{
'@type' : 'Question' ,
name : 'Is Task production-ready?' ,
acceptedAnswer : {
'@type' : 'Answer' ,
text : 'Yes. Task ships as a single static binary, has been in wide production use since 2018, and powers the release workflows of projects with millions of downloads including Arduino CLI, GoReleaser, FerretDB, and Gogs.'
}
} ,
{
'@type' : 'Question' ,
name : 'Who uses Task in enterprise?' ,
acceptedAnswer : {
'@type' : 'Answer' ,
text : 'Docker, Vercel, HashiCorp, Microsoft (Azure Sentinel), Google Cloud, AWS, and Anthropic are among the organizations that ship code with a Taskfile.yml. Task is also embedded end-to-end in Arduino’ s developer tooling stack across more than 70 repositories.'
}
} ,
{
'@type' : 'Question' ,
name : 'How is Task different from Make?' ,
acceptedAnswer : {
'@type' : 'Answer' ,
text : 'Task uses plain YAML instead of Make’ s tab-sensitive syntax, runs identically on Linux, macOS, and Windows, and provides built-in caching based on file fingerprints. It also comes with an ecosystem of editor and CI integrations that Make lacks by default.'
}
} ,
{
'@type' : 'Question' ,
name : 'Where can I find real-world Taskfile examples?' ,
acceptedAnswer : {
'@type' : 'Answer' ,
text : 'Every adopter listed above links directly to a public repository containing a production Taskfile.yml. Browsing those is the fastest way to see Task used in real codebases at different scales.'
}
}
]
} )
] )
}
2025-12-18 08:52:32 +01:00
return head
} ,
2025-08-12 18:09:19 +02:00
srcDir : 'src' ,
cleanUrls : true ,
markdown : {
config : ( md ) = > {
md . use ( githubLinksPlugin , {
baseUrl : 'https://github.com' ,
repo : 'go-task/task'
} ) ;
md . use ( tabsMarkdownPlugin ) ;
md . use ( groupIconMdPlugin ) ;
}
} ,
vite : {
2025-09-10 17:57:52 +02:00
plugins : [
2025-11-29 12:40:44 +01:00
llmstxt ( {
ignoreFiles : [
'index.md' ,
'team.md' ,
'donate.md' ,
'docs/styleguide.md' ,
'docs/contributing.md' ,
'docs/releasing.md' ,
'docs/changelog.md' ,
'blog/*'
]
} ) ,
2025-09-10 17:57:52 +02:00
groupIconVitePlugin ( {
customIcon : {
'.taskrc.yml' : localIconLoader (
import . meta . url ,
'./theme/icons/task.svg'
) ,
'Taskfile.yml' : localIconLoader (
import . meta . url ,
'./theme/icons/task.svg'
)
}
} )
] ,
2025-08-12 18:09:19 +02:00
resolve : {
alias : [
{
find : /^.*\/VPTeamMembersItem\.vue$/ ,
replacement : fileURLToPath (
new URL ( './components/VPTeamMembersItem.vue' , import . meta . url )
)
}
]
}
} ,
themeConfig : {
logo : '/img/logo.svg' ,
carbonAds : {
code : 'CESI65QJ' ,
placement : 'taskfiledev'
} ,
search : {
2025-08-12 18:52:47 +02:00
provider : 'algolia' ,
options : {
appId : '7IZIJ13AI7' ,
apiKey : '34b64ae4fc8d9da43d9a13d9710aaddc' ,
indexName : 'taskfile'
}
2025-08-12 18:09:19 +02:00
} ,
nav : [
{ text : 'Home' , link : '/' } ,
{
text : 'Docs' ,
link : '/docs/guide' ,
activeMatch : '^/docs'
} ,
{ text : 'Blog' , link : '/blog' , activeMatch : '^/blog' } ,
{ text : 'Donate' , link : '/donate' } ,
{ text : 'Team' , link : '/team' } ,
{
text : process.env.NODE_ENV === 'development' ? 'Next' : ` v ${ version } ` ,
items : [
{
items : [
{
text : ` v ${ version } ` ,
link : urlVersion.current
} ,
{
text : 'Next' ,
link : urlVersion.next
}
]
}
]
}
] ,
sidebar : {
'/blog/' : [
2026-01-24 20:25:14 -03:00
{
text : '2026' ,
collapsed : false ,
items : [
{
2026-04-14 22:47:45 -03:00
text : 'go tool task' ,
link : '/blog/go-tool-task'
} ,
{
text : 'New "if:" Control and Variable Prompt' ,
2026-01-24 20:25:14 -03:00
link : '/blog/if-and-variable-prompt'
}
]
} ,
2025-08-26 22:22:10 -03:00
{
text : '2025' ,
collapsed : false ,
items : [
{
text : 'Built-in Core Utilities' ,
link : '/blog/windows-core-utils'
}
]
} ,
2025-08-12 18:09:19 +02:00
{
text : '2024' ,
collapsed : false ,
items : [
{
text : 'Any Variables' ,
link : '/blog/any-variables'
}
]
} ,
{
text : '2023' ,
collapsed : false ,
items : [
{
text : 'Introducing Experiments' ,
link : '/blog/task-in-2023'
}
]
}
] ,
'/' : [
{
text : 'Installation' ,
link : '/docs/installation'
} ,
{
text : 'Getting Started' ,
link : '/docs/getting-started'
} ,
{
text : 'Guide' ,
link : '/docs/guide'
} ,
{
text : 'Reference' ,
collapsed : true ,
items : [
{
2025-08-18 21:43:36 +01:00
text : 'Taskfile Schema' ,
link : '/docs/reference/schema'
2025-08-12 18:09:19 +02:00
} ,
{
2025-08-18 21:43:36 +01:00
text : 'Environment' ,
link : '/docs/reference/environment'
} ,
{
text : 'Configuration' ,
link : '/docs/reference/config'
} ,
{
text : 'CLI' ,
link : '/docs/reference/cli'
2025-08-12 18:09:19 +02:00
} ,
{
text : 'Templating' ,
link : '/docs/reference/templating'
} ,
{
text : 'Package API' ,
link : '/docs/reference/package'
}
]
} ,
{
text : 'Experiments' ,
collapsed : true ,
link : '/docs/experiments/' ,
items : [
{
text : 'Env Precedence (#1038)' ,
link : '/docs/experiments/env-precedence'
} ,
{
text : 'Gentle Force (#1200)' ,
link : '/docs/experiments/gentle-force'
} ,
{
text : 'Remote Taskfiles (#1317)' ,
link : '/docs/experiments/remote-taskfiles'
}
]
} ,
{
text : 'Deprecations' ,
collapsed : true ,
link : '/docs/deprecations/' ,
items : [
{
text : 'Completion Scripts' ,
link : '/docs/deprecations/completion-scripts'
} ,
{
text : 'Template Functions' ,
link : '/docs/deprecations/template-functions'
} ,
{
text : 'Version 2 Schema (#1197)' ,
link : '/docs/deprecations/version-2-schema'
}
]
} ,
{
text : 'Taskfile Versions' ,
link : '/docs/taskfile-versions'
} ,
{
text : 'Integrations' ,
link : '/docs/integrations'
} ,
{
text : 'Community' ,
link : '/docs/community'
} ,
{
text : 'Style Guide' ,
link : '/docs/styleguide'
} ,
{
text : 'Contributing' ,
link : '/docs/contributing'
} ,
{
text : 'Releasing' ,
link : '/docs/releasing'
} ,
2026-04-15 20:34:38 +01:00
{
text : 'Security' ,
collapsed : true ,
link : '/docs/security/' ,
items : [
{
text : 'Incident Response Plan' ,
link : '/docs/security/incident-response-plan'
}
]
} ,
2025-08-12 18:09:19 +02:00
{
text : 'Changelog' ,
link : '/docs/changelog'
} ,
{
text : 'FAQ' ,
link : '/docs/faq'
}
] ,
// Hacky to disable sidebar for these pages
'/donate' : [ ] ,
2026-04-22 10:02:06 +02:00
'/team' : [ ] ,
'/adopters' : [ ]
2025-08-12 18:09:19 +02:00
} ,
socialLinks : [
{ icon : 'github' , link : 'https://github.com/go-task/task' } ,
{ icon : 'discord' , link : 'https://discord.gg/6TY36E39UK' } ,
{ icon : 'x' , link : 'https://twitter.com/taskfiledev' } ,
{ icon : 'bluesky' , link : 'https://bsky.app/profile/taskfile.dev' } ,
{ icon : 'mastodon' , link : 'https://fosstodon.org/@task' }
] ,
2026-01-27 21:45:17 -03:00
editLink : {
text : 'Edit this page on GitHub' ,
pattern : 'https://github.com/go-task/task/edit/main/website/src/:path'
} ,
2025-08-12 18:09:19 +02:00
footer : {
message :
'Built with <a target="_blank" href="https://www.netlify.com">Netlify</a>'
}
2025-08-12 21:59:07 +02:00
} ,
sitemap : {
2025-12-18 08:52:32 +01:00
hostname : 'https://taskfile.dev' ,
transformItems : ( items ) = > {
return items . map ( ( item ) = > ( {
. . . item ,
lastmod : new Date ( ) . toISOString ( )
} ) ) ;
}
2025-08-12 18:09:19 +02:00
}
} ) ;