diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..e52bb850 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,88 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +This is the official documentation repository for Coolify, built with VitePress. The documentation covers installation, usage, troubleshooting, and API reference for Coolify - an open-source self-hostable alternative to Heroku/Netlify/Vercel. + +## Development Commands + +**Package Manager**: The project uses pnpm as specified in package.json, but contributors are encouraged to use bun for local development as mentioned in the README. + +### Core Commands +```bash +# Install dependencies +bun install # or npm install + +# Start development server +bun run dev # or npm run dev +# Serves on localhost:5173/docs/ + +# Build for production +bun run build # or npm run build + +# Preview production build +bun run preview # or npm run preview + +# Convert OpenAPI YAML to JSON +bun run transform-openapi # or npm run transform-openapi +``` + +### VitePress Commands +- `vitepress dev docs` - Start development server +- `vitepress build docs` - Build documentation +- `vitepress preview docs` - Preview built documentation + +## Architecture & Structure + +### Content Organization +- **docs/**: Main documentation content directory + - **get-started/**: Installation, introduction, concepts + - **applications/**: Framework-specific guides (Django, Laravel, Next.js, etc.) + - **services/**: Individual service documentation (200+ services) + - **databases/**: Database-specific guides + - **knowledge-base/**: Advanced topics, how-tos, troubleshooting + - **api-reference/**: Auto-generated API documentation + - **troubleshoot/**: Common issues and solutions + +### Technical Stack +- **VitePress 1.6.3**: Static site generator +- **Vue 3.5.13**: Component framework +- **TailwindCSS 3.2.4**: Styling +- **TypeScript**: Type checking via tsx +- **OpenAPI Integration**: Auto-generated API docs from openapi.yml + +### Key Configuration Files +- **docs/.vitepress/config.mts**: Main VitePress configuration + - Sidebar structure with 200+ service pages + - Custom theme components and aliases + - OpenAPI integration via vitepress-openapi + - Markdown plugins (tabs, containers, group icons) +- **package.json**: Dependencies and npm scripts +- **tailwind.config.js**: TailwindCSS configuration +- **scripts/convert-openapi.ts**: YAML to JSON converter for OpenAPI spec + +### Custom Components & Plugins +- **ZoomableImage**: For documentation images (all images must be .webp format in docs/public/) +- **Custom VitePress theme**: Overrides default components (VPNavBar, VPSidebar, etc.) +- **vitepress-plugin-llms**: LLM integration +- **vitepress-plugin-tabs**: Tabbed content +- **vitepress-plugin-group-icons**: Code group icons +- **vitepress-openapi**: API documentation generation + +### Contribution Workflow +- **Main branch**: Production +- **Next branch**: Development branch for contributions +- **Pull requests**: Must target the `next` branch, not `main` +- **Images**: Must be .webp format, stored in docs/public/ +- **Content**: Use ZoomableImage component for images +- **Package managers**: Bun preferred for development, avoid committing lockfiles from other managers + +### Development Notes +- The documentation uses a complex sidebar structure with 400+ pages +- Custom markdown containers (success blocks, etc.) +- SSH syntax highlighting support via custom Shiki configuration +- Carbon Ads integration +- Analytics via Plausible +- Custom OpenAPI spec processing from YAML to JSON \ No newline at end of file diff --git a/bun.lockb b/bun.lockb index 48ef452d..9a63324f 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index d251176c..11756f99 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -21,6 +21,15 @@ bundledLanguages['ssh'] = { path: join(dirname(fileURLToPath(import.meta.url)), '../../node_modules/shiki/languages/ssh-config.tmLanguage.json') } +const serviceUrl = 'https://raw.githubusercontent.com/coollabsio/coolify/v4.x/templates/service-templates.json' +const serviceData = await fetch(serviceUrl).then(res => res.json()) +const services = Object.keys(serviceData).map((key: string) => { + return { + text: key, + link: `/services/${key.toLowerCase().replace(/ /g, '-')}` + } +}) + // https://vitepress.dev/reference/site-config export default defineConfig({ lang: 'en-US', @@ -61,7 +70,6 @@ export default defineConfig({ }, logo: '/coolify-logo-transparent.png', nav: [ - { text: 'Services', link: '/services/overview' }, { text: 'Coolify Cloud', link: 'https://coolify.io/pricing/' }, { text: 'Resources', @@ -173,6 +181,18 @@ export default defineConfig({ } ], }, + { + text: 'Services', + collapsed: true, + link: '/services/overview', + items: [ + { + text: 'Overview & Quick Deploy', + link: '/services/overview', + items: services + } + ], + }, { text: 'Databases', collapsed: true, diff --git a/docs/.vitepress/plugins/vitepress-plugin-coolbot.ts b/docs/.vitepress/plugins/vitepress-plugin-coolbot.ts index 2757b404..a303acb6 100644 --- a/docs/.vitepress/plugins/vitepress-plugin-coolbot.ts +++ b/docs/.vitepress/plugins/vitepress-plugin-coolbot.ts @@ -44,7 +44,7 @@ export default function coolbotPlugin(options: coolbotPluginOptions = {}): Plugi }; return { - name: 'vitepress-plugin-CoolBot', + name: 'vitepress-plugin-coolbot', async closeBundle() { try { @@ -87,7 +87,6 @@ export default function coolbotPlugin(options: coolbotPluginOptions = {}): Plugi } } - // Write the file map const mapPath = resolve(convertedDir, 'llms-text.json'); writeFileSync(mapPath, JSON.stringify(fileMap, null, 2), 'utf-8'); diff --git a/docs/.vitepress/theme/components/CoolIcon.vue b/docs/.vitepress/theme/components/CoolIcon.vue new file mode 100644 index 00000000..bb85466a --- /dev/null +++ b/docs/.vitepress/theme/components/CoolIcon.vue @@ -0,0 +1,48 @@ + + + + diff --git a/docs/.vitepress/theme/components/Services/DeployModal.vue b/docs/.vitepress/theme/components/Services/DeployModal.vue new file mode 100644 index 00000000..88daeef7 --- /dev/null +++ b/docs/.vitepress/theme/components/Services/DeployModal.vue @@ -0,0 +1,1229 @@ + + + diff --git a/docs/.vitepress/theme/components/Services/List.vue b/docs/.vitepress/theme/components/Services/List.vue index 96d2305b..702e25de 100644 --- a/docs/.vitepress/theme/components/Services/List.vue +++ b/docs/.vitepress/theme/components/Services/List.vue @@ -1,80 +1,299 @@ - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/docs/.vitepress/theme/components/Services/Modal.vue b/docs/.vitepress/theme/components/Services/Modal.vue new file mode 100644 index 00000000..760600dd --- /dev/null +++ b/docs/.vitepress/theme/components/Services/Modal.vue @@ -0,0 +1,261 @@ + + + + + \ No newline at end of file diff --git a/docs/.vitepress/theme/composables/coolfetch.ts b/docs/.vitepress/theme/composables/coolfetch.ts new file mode 100644 index 00000000..7fd1daa5 --- /dev/null +++ b/docs/.vitepress/theme/composables/coolfetch.ts @@ -0,0 +1,363 @@ +import { ref } from "vue"; + +export const useCoolFetch = (services) => { + const serviceList = services + const baseUrl = ref('') + const apiToken = ref('') + const coolifyCloudUrl = 'https://app.coolify.io' + const connection = ref(false) + const connected = ref(false) + const status = ref('') + const projectStatus = ref('') + const serviceStatus = ref('') + const deployStatus = ref('') + + const searchServiceTemplate = (template_name: string) => { + try { + if (!template_name) { + return undefined + } + + let override = '' + if (template_name == 'ollama') { + override = 'ollama-with-open-webui' + } + + // Try exact match first + if (serviceList[override ? override : template_name.toLowerCase()]) { + return serviceList[override ? override : template_name.toLowerCase()] + } + + // Try case-insensitive match + const templateKey = Object.keys(override ? serviceList[override] : serviceList).find( + key => key.toLowerCase() === (override ? override : template_name.toLowerCase()) + ) + + if (templateKey) { + return override ? serviceList[override] : serviceList[templateKey] + } + return undefined + } catch (error) { + // console.warn('Error fetching service template:', error) + throw error + } + } + + const coolfetch = (url: string, options: RequestInit) => { + return fetch(`${baseUrl.value}${url}`, { + ...options, + headers: { + 'Authorization': `Bearer ${apiToken.value}`, + 'Agent': 'Coolify.io Docs', + 'Content-Type': 'application/json' + } + }) + } + + const connect = async (domain: string, apiKey: string) => { + try{ + status.value = 'pending' + baseUrl.value = domain ? domain : coolifyCloudUrl + apiToken.value = apiKey + const response = await coolfetch( + `/api/v1/servers`, + { + method: 'GET' + } + ) + + // Check if response is ok (status 200-299) + if (!response.ok) { + status.value = 'error' + if (response.status === 401) { + return new Error('401 Unauthorized - Invalid API key') + } else if (response.status === 403) { + return new Error('403 Forbidden - Insufficient permissions') + } else { + return new Error(`HTTP ${response.status} - ${response.statusText}`) + } + } + + status.value = 'success' + const data = await response.json() + if (data.success) { + connection.value = true + return data + } + return data + } catch (error) { + status.value = 'error' + if (error instanceof Error) { + return error + } + return new Error('Failed to connect') + } + } + + const createProject = async (name: string, description: string) => { + projectStatus.value = 'pending' + try { + const response = await coolfetch(`/api/v1/projects`, { + method: 'POST', + body: JSON.stringify({ + name, + description + }) + }) + + // Check if response is ok (status 200-299) + if (!response.ok) { + projectStatus.value = 'error' + if (response.status === 401) { + return new Error('401 Unauthorized - Invalid API key') + } else if (response.status === 403) { + return new Error('403 Forbidden - Insufficient permissions') + } else { + return new Error(`HTTP ${response.status} - ${response.statusText}`) + } + } + + const data = await response.json() + if (data.uuid) { + projectStatus.value = 'success' + return data.uuid + } else { + // console.error('Unexpected response structure:', data) + return new Error('Invalid response structure from API') + } + + } catch (error) { + projectStatus.value = 'error' + // console.error('Error creating project:', error) + if (error instanceof Error) { + return error + } + return new Error('Failed to create project') + } + } + + const createService = async (server_uuid: string, project_uuid: string, template_name: string, environment_name?: string) => { + serviceStatus.value = 'pending' + try { + const templateConfig = searchServiceTemplate(template_name) + const { slogan, compose } = templateConfig + + const response = await coolfetch(`/api/v1/services`, { + method: 'POST', + body: JSON.stringify({ + "name": template_name, + "description": slogan, + "project_uuid": project_uuid, + "environment_name": environment_name || "production", + "server_uuid": server_uuid, + "environment_uuid": environment_name || "production", + "destination_uuid": "production", + "instant_deploy": true, + "docker_compose_raw": compose + }) + }) + + // Check if response is ok (status 200-299) + if (!response.ok) { + serviceStatus.value = 'error' + if (response.status === 401) { + return new Error('401 Unauthorized - Invalid API key') + } else if (response.status === 403) { + return new Error('403 Forbidden - Insufficient permissions') + } else { + return new Error(`HTTP ${response.status} - ${response.statusText}`) + } + } + + const data = await response.json() + if (data.uuid && data.domains.length > 0) { + serviceStatus.value = 'success' + return data + } + + return new Error('Failed to create service') + } catch (error) { + serviceStatus.value = 'error' + // console.error('Error creating service:', error) + if (error instanceof Error) { + return error + } + return new Error('Failed to create service') + } + } + + const fetchProjects = async () => { + try { + const response = await coolfetch('/api/v1/projects', { + method: 'GET' + }) + + if (!response.ok) { + if (response.status === 401) { + return new Error('401 Unauthorized - Invalid API key') + } else if (response.status === 403) { + return new Error('403 Forbidden - Insufficient permissions') + } else { + return new Error(`HTTP ${response.status} - ${response.statusText}`) + } + } + + const data = await response.json() + return data + } catch (error) { + if (error instanceof Error) { + return error + } + return new Error('Failed to fetch projects') + } + } + + const fetchProjectDetails = async (projectUuid: string) => { + try { + const response = await coolfetch(`/api/v1/projects/${projectUuid}`, { + method: 'GET' + }) + + if (!response.ok) { + if (response.status === 401) { + return new Error('401 Unauthorized - Invalid API key') + } else if (response.status === 403) { + return new Error('403 Forbidden - Insufficient permissions') + } else { + return new Error(`HTTP ${response.status} - ${response.statusText}`) + } + } + + const data = await response.json() + return data + } catch (error) { + if (error instanceof Error) { + return error + } + return new Error('Failed to fetch project details') + } + } + + const fetchVersion = async () => { + try { + const response = await coolfetch('/api/v1/version', { + method: 'GET' + }) + + if (!response.ok) { + if (response.status === 401) { + return new Error('401 Unauthorized - Invalid API key') + } else if (response.status === 403) { + return new Error('403 Forbidden - Insufficient permissions') + } else { + return new Error(`HTTP ${response.status} - ${response.statusText}`) + } + } + + const version = await response.text() + return version + } catch (error) { + if (error instanceof Error) { + return error + } + return new Error('Failed to fetch version') + } + } + + const deploy = async (server_uuid: string, template_name: string, project_uuid?: string, environment_name?: string) => { + const templateConfig = searchServiceTemplate(template_name.toLowerCase()) + + if (!templateConfig) { + return new Error(`Template '${template_name}' not found`) + } + + const { slogan, compose } = templateConfig + if (!template_name || !slogan) { + return new Error('Template name and description are required') + } + + // Use provided project or create new one + let finalProjectUuid = project_uuid + if (!finalProjectUuid) { + finalProjectUuid = await createProject(template_name, slogan) + + if (!finalProjectUuid) { + return new Error('Failed to create project') + } + } + + const service = await createService(server_uuid, finalProjectUuid, template_name, environment_name) + const domain = service.domains.filter(domain => domain !== null)[0] + + apiToken.value = '' + baseUrl.value = '' + connection.value = false + connected.value = false + status.value = '' + projectStatus.value = '' + serviceStatus.value = '' + deployStatus.value = '' + + return { + url: domain, + serviceUuid: service.uuid, + projectUuid: finalProjectUuid, + environmentName: environment_name || 'production', + environmentUuid: service.environment_uuid || environment_name || 'production' + } + } + + const checkServiceHealth = async (serviceUrl: string): Promise => { + try { + const controller = new AbortController() + const timeoutId = setTimeout(() => controller.abort(), 10000) // 10 second timeout + + // Path overrides for common endpoints + const endpointsToTry = [ + '/' // Root path + ] + + for (const endpoint of endpointsToTry) { + try { + const url = `${serviceUrl}${endpoint}` + const response = await fetch(url, { + method: 'GET', + signal: controller.signal + }) + + // Check if the response is successful (2xx status codes) + // Also accept 3xx redirects as healthy (service is responding) + if (response.ok || (response.status >= 300 && response.status < 400)) { + clearTimeout(timeoutId) + return true + } + } catch (endpointError) { + // Continue to next endpoint if this one fails + continue + } + } + + clearTimeout(timeoutId) + return false + } catch (error) { + // If the request fails (network error, timeout, etc.), the service is not healthy + return false + } + } + + return { + connect, + connected, + status, + projectStatus, + serviceStatus, + deployStatus, + createProject, + createService, + fetchProjects, + fetchProjectDetails, + fetchVersion, + deploy, + checkServiceHealth + } +} \ No newline at end of file diff --git a/docs/.vitepress/theme/style.css b/docs/.vitepress/theme/style.css index 5aa526e7..1076145a 100644 --- a/docs/.vitepress/theme/style.css +++ b/docs/.vitepress/theme/style.css @@ -138,7 +138,7 @@ --vp-custom-block-success-text: #4ade80; /* Custom Block Colors - Light Mode */ - + /* Primary/Brand - Purple */ --vp-custom-block-tip-border: #7937f3; --vp-custom-block-tip-text: #7937f3; @@ -197,11 +197,9 @@ :root { --vp-home-hero-name-color: transparent; - --vp-home-hero-name-background: -webkit-linear-gradient( - 120deg, - #9A54FC 0%, - #9A54FC - ); + --vp-home-hero-name-background: -webkit-linear-gradient(120deg, + #9A54FC 0%, + #9A54FC); } @media (min-width: 640px) { @@ -247,10 +245,11 @@ --vp-c-text-1: #F2F2F2; --vp-c-text-2: #9A989D; --vp-c-text-3: #9A989D; - + /* Lighter code background in dark mode */ - --vp-code-bg: #161b22 !important; /* Darker background in dark mode */ - + --vp-code-bg: #161b22 !important; + /* Darker background in dark mode */ + --vp-custom-block-tip-border: #0C4C69; --vp-custom-block-tip-text: #A7D2E8; --vp-custom-block-tip-bg: #0B2029; @@ -267,13 +266,13 @@ --vp-badge-success-text: #86efac; --vp-badge-success-bg: rgba(54, 211, 153, 0.16); - + --vp-badge-info-text: #7dd3fc; --vp-badge-info-bg: rgba(66, 184, 231, 0.16); - + --vp-custom-block-success-text: var(--vp-badge-success-text); --vp-custom-block-success-bg: var(--vp-badge-success-bg); - + --vp-custom-block-info-text: var(--vp-badge-info-text); --vp-custom-block-info-bg: var(--vp-badge-info-bg); @@ -284,7 +283,7 @@ --vp-c-brand-soft: rgba(179, 146, 240, 0.16); /* Custom Block Colors - Dark Mode */ - + /* Primary/Brand - Purple */ --vp-custom-block-tip-border: #9664f3; --vp-custom-block-tip-text: #9664f3; @@ -312,7 +311,8 @@ /* Enhanced code highlighting, especially for Safari */ --vp-code-color: #F2F2F2; - --vp-code-bg: #161b22 !important; /* Darker background in dark mode */ + --vp-code-bg: #161b22 !important; + /* Darker background in dark mode */ } /* Container padding override - updated for reasonable width layout */ @@ -374,6 +374,7 @@ width: var(--vp-sidebar-width) !important; height: var(--vp-nav-height) !important; background-color: transparent !important; + border-bottom: 0px !important; } @media (min-width: 1440px) { @@ -390,7 +391,7 @@ align-items: center !important; } -.VPSidebar .search > * { +.VPSidebar .search>* { flex: 1 !important; } @@ -402,7 +403,7 @@ align-items: center !important; } -.VPSidebar .search :deep(*) > * { +.VPSidebar .search :deep(*)>* { flex: 1 !important; } @@ -442,15 +443,16 @@ height: 0.6em !important; background-color: transparent !important; } - + & ::-webkit-scrollbar-track { background-color: var(--vp-c-bg-soft) !important; } - + & ::-webkit-scrollbar-thumb { border-radius: 0.6em !important; background-color: var(--vp-c-divider) !important; } + & ::-webkit-scrollbar-thumb:hover { background-color: var(--vp-c-text-3) !important; } @@ -460,13 +462,13 @@ /* Search component styling */ .VPLocalSearchBox { width: 100% !important; - + & .search-box { width: 100% !important; display: flex !important; } - & .search-box > .DocSearch-Button { + & .search-box>.DocSearch-Button { width: 100% !important; justify-content: space-between !important; } @@ -505,7 +507,7 @@ align-items: center !important; } -.VPSidebar .VPNavBarSearch > * { +.VPSidebar .VPNavBarSearch>* { width: 100% !important; display: flex !important; justify-content: space-between !important; @@ -540,15 +542,18 @@ /* Ensure proper layout on XL and larger screens */ @media (min-width: 1280px) { .VPDoc.has-sidebar:not(.has-aside) .content-container { - max-width: calc(100% - 272px) !important; /* Account for left sidebar only */ + max-width: calc(100% - 272px) !important; + /* Account for left sidebar only */ } - + .VPDoc:not(.has-sidebar).has-aside .content-container { - max-width: calc(100% - 256px) !important; /* Account for right sidebar only */ + max-width: calc(100% - 256px) !important; + /* Account for right sidebar only */ } - + .VPDoc:not(.has-sidebar):not(.has-aside) .content-container { - max-width: 1100px !important; /* Wider max width for no sidebars */ + max-width: 1100px !important; + /* Wider max width for no sidebars */ } } @@ -562,11 +567,25 @@ } /* Custom styling for links inside custom blocks/callouts */ -.custom-block.tip a { border-bottom-color: var(--vp-custom-block-tip-text); } -.custom-block.info a { border-bottom-color: var(--vp-custom-block-info-text); } -.custom-block.warning a { border-bottom-color: var(--vp-custom-block-warning-text); } -.custom-block.danger a { border-bottom-color: var(--vp-custom-block-danger-text); } -.custom-block.success a { border-bottom-color: var(--vp-custom-block-success-text); } +.custom-block.tip a { + border-bottom-color: var(--vp-custom-block-tip-text); +} + +.custom-block.info a { + border-bottom-color: var(--vp-custom-block-info-text); +} + +.custom-block.warning a { + border-bottom-color: var(--vp-custom-block-warning-text); +} + +.custom-block.danger a { + border-bottom-color: var(--vp-custom-block-danger-text); +} + +.custom-block.success a { + border-bottom-color: var(--vp-custom-block-success-text); +} /* Exception for navigation and sidebar links if needed */ .vp-doc .nav-link a, @@ -629,10 +648,10 @@ code:hover { } /* Copy button styling - both for main and nested code blocks */ -.vp-doc div[class*='language-'] > button.copy, -.vp-doc div[class*='language-'] > button.copy-code, -.vp-doc :deep(div[class*='language-']) > button.copy, -.vp-doc :deep(div[class*='language-']) > button.copy-code { +.vp-doc div[class*='language-']>button.copy, +.vp-doc div[class*='language-']>button.copy-code, +.vp-doc :deep(div[class*='language-'])>button.copy, +.vp-doc :deep(div[class*='language-'])>button.copy-code { position: absolute; top: 8px; right: 8px; @@ -650,48 +669,51 @@ code:hover { } /* Show button on hover or when copied - for both main and nested */ -.vp-doc div[class*='language-']:hover > button.copy, -.vp-doc div[class*='language-']:hover > button.copy-code, -.vp-doc div[class*='language-'] > button.copy.copied, -.vp-doc div[class*='language-'] > button.copy-code.copied, -.vp-doc :deep(div[class*='language-']:hover) > button.copy, -.vp-doc :deep(div[class*='language-']:hover) > button.copy-code, -.vp-doc :deep(div[class*='language-']) > button.copy.copied, -.vp-doc :deep(div[class*='language-']) > button.copy-code.copied { +.vp-doc div[class*='language-']:hover>button.copy, +.vp-doc div[class*='language-']:hover>button.copy-code, +.vp-doc div[class*='language-']>button.copy.copied, +.vp-doc div[class*='language-']>button.copy-code.copied, +.vp-doc :deep(div[class*='language-']:hover)>button.copy, +.vp-doc :deep(div[class*='language-']:hover)>button.copy-code, +.vp-doc :deep(div[class*='language-'])>button.copy.copied, +.vp-doc :deep(div[class*='language-'])>button.copy-code.copied { opacity: 1; } -.vp-doc div[class*='language-'] > button.copy:hover, -.vp-doc div[class*='language-'] > button.copy-code:hover, -.vp-doc :deep(div[class*='language-']) > button.copy:hover, -.vp-doc :deep(div[class*='language-']) > button.copy-code:hover { +.vp-doc div[class*='language-']>button.copy:hover, +.vp-doc div[class*='language-']>button.copy-code:hover, +.vp-doc :deep(div[class*='language-'])>button.copy:hover, +.vp-doc :deep(div[class*='language-'])>button.copy-code:hover { background-color: var(--vp-c-bg-soft); } /* Success state styling */ -.vp-doc div[class*='language-'] > button.copy.copied, -.vp-doc div[class*='language-'] > button.copy-code.copied, -.vp-doc :deep(div[class*='language-']) > button.copy.copied, -.vp-doc :deep(div[class*='language-']) > button.copy-code.copied { - background-color: rgba(34, 197, 94, 0.1); /* Light green background */ - color: rgb(34, 197, 94); /* Green text */ +.vp-doc div[class*='language-']>button.copy.copied, +.vp-doc div[class*='language-']>button.copy-code.copied, +.vp-doc :deep(div[class*='language-'])>button.copy.copied, +.vp-doc :deep(div[class*='language-'])>button.copy-code.copied { + background-color: rgba(34, 197, 94, 0.1); + /* Light green background */ + color: rgb(34, 197, 94); + /* Green text */ } /* Hide the original icon when copied */ -.vp-doc [class*='language-'] > button.copy.copied > span, -.vp-doc [class*='language-'] > button.copy-code.copied > span, -.vp-doc :deep([class*='language-']) > button.copy.copied > span, -.vp-doc :deep([class*='language-']) > button.copy-code.copied > span { +.vp-doc [class*='language-']>button.copy.copied>span, +.vp-doc [class*='language-']>button.copy-code.copied>span, +.vp-doc :deep([class*='language-'])>button.copy.copied>span, +.vp-doc :deep([class*='language-'])>button.copy-code.copied>span { display: none; } /* Show checkmark icon when copied */ -.vp-doc [class*='language-'] > button.copy.copied::after, -.vp-doc [class*='language-'] > button.copy-code.copied::after, -.vp-doc :deep([class*='language-']) > button.copy.copied::after, -.vp-doc :deep([class*='language-']) > button.copy-code.copied::after { +.vp-doc [class*='language-']>button.copy.copied::after, +.vp-doc [class*='language-']>button.copy-code.copied::after, +.vp-doc :deep([class*='language-'])>button.copy.copied::after, +.vp-doc :deep([class*='language-'])>button.copy-code.copied::after { content: '✓'; - color: rgb(34, 197, 94); /* Green checkmark */ + color: rgb(34, 197, 94); + /* Green checkmark */ font-size: 1.2em; } @@ -705,7 +727,8 @@ code:hover { top: -32px; left: 50%; transform: translateX(-50%); - background: rgb(20 184 166); /* Teal color */ + background: rgb(20 184 166); + /* Teal color */ color: white; padding: 4px 12px; border-radius: 9999px; @@ -718,11 +741,15 @@ code:hover { } @keyframes copyLabel { - 0%, 100% { + + 0%, + 100% { opacity: 0; transform: translateX(-50%) translateY(5px); } - 20%, 80% { + + 20%, + 80% { opacity: 1; transform: translateX(-50%) translateY(0); } @@ -741,9 +768,10 @@ code:hover { } /* Adjust copy button position when language indicator is present */ -.vp-doc div[class*='language-'] > button.copy, -.vp-doc div[class*='language-'] > button.copy-code { - right: 40px; /* Give space for language indicator */ +.vp-doc div[class*='language-']>button.copy, +.vp-doc div[class*='language-']>button.copy-code { + right: 40px; + /* Give space for language indicator */ } /* Custom Block Colors - Light Mode */ @@ -806,7 +834,7 @@ code:hover { /* Reset webkit styles for code blocks */ .vp-doc [class*='language-'] code { - + -webkit-text-fill-color: initial !important; } @@ -899,8 +927,10 @@ code:hover { .token.prolog, .token.doctype, .token.cdata { - font-weight: 400 !important; /* Normal weight for entire comment */ - opacity: 0.7; /* Slightly dim the comments */ + font-weight: 400 !important; + /* Normal weight for entire comment */ + opacity: 0.7; + /* Slightly dim the comments */ } /* Make specific tokens slightly bolder */ @@ -915,17 +945,17 @@ code:hover { } /* Markdown Labels like NODE_ENV */ -:not(pre) > code { +:not(pre)>code { background-color: rgba(40, 44, 52, 0) !important; - color: rgba(185, 185, 185, 0.795) !important; + color: rgba(185, 185, 185, 0.795) !important; -webkit-text-fill-color: rgba(95, 95, 95, 0.795) !important; font-weight: 600 !important; padding: 4px 4px !important; border-radius: 6px !important; font-size: 0.7em !important; border: 1px solid rgba(185, 185, 185, 0.795) !important; - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), - 0 0 1px rgba(255, 255, 255, 0.05) !important; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), + 0 0 1px rgba(255, 255, 255, 0.05) !important; margin: 0 3px !important; /* text-transform: uppercase !important; */ letter-spacing: 0.02em !important; @@ -933,23 +963,24 @@ code:hover { } /* Dark mode adjustments */ -.dark :not(pre) > code { +.dark :not(pre)>code { background-color: rgb(50, 50, 60) !important; color: #ffffff !important; -webkit-text-fill-color: #ffffff !important; border-color: rgba(255, 255, 255, 0.2) !important; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3), - 0 0 3px rgba(255, 255, 255, 0.1) !important; + 0 0 3px rgba(255, 255, 255, 0.1) !important; } /* Safari-specific enhancements for inline code */ @supports (-webkit-hyphens:none) { - :not(pre) > code { + :not(pre)>code { transform: translateZ(0); backface-visibility: hidden; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; - backdrop-filter: blur(8px); /* Subtle blur effect behind code */ + backdrop-filter: blur(8px); + /* Subtle blur effect behind code */ } } @@ -974,8 +1005,11 @@ pre[class*='language-'] *:hover { /* Remove all the other hover prevention blocks since they're now consolidated above */ @media (prefers-color-scheme: dark) { - p code:hover, li code:hover, - .custom-block p code:hover, .custom-block li p code:hover { + + p code:hover, + li code:hover, + .custom-block p code:hover, + .custom-block li p code:hover { background-color: var(--vp-c-brand-1) !important; color: white !important; -webkit-text-fill-color: white !important; @@ -991,11 +1025,23 @@ pre[class*='language-'] *:hover { /* Override Shiki theme colors for light mode */ .shiki.github-light { - --shiki-light-keyword: #cf222e !important; /* red */ - --shiki-light-string: #0a3069 !important; /* dark blue for strings */ - --shiki-light-function: #8250df !important; /* purple */ - --shiki-light-number: #0550ae !important; /* blue */ - --shiki-light-boolean: #0550ae !important; /* blue */ - --shiki-light-comment: #6e7781 !important; /* gray */ - --shiki-light-property: #953800 !important; /* brown */ + --shiki-light-keyword: #cf222e !important; + /* red */ + --shiki-light-string: #0a3069 !important; + /* dark blue for strings */ + --shiki-light-function: #8250df !important; + /* purple */ + --shiki-light-number: #0550ae !important; + /* blue */ + --shiki-light-boolean: #0550ae !important; + /* blue */ + --shiki-light-comment: #6e7781 !important; + /* gray */ + --shiki-light-property: #953800 !important; + /* brown */ +} + + +.input { + @apply w-full text-sm p-2 border-2 rounded dark:bg-coolgray-100 bg-gray-100 focus:border-coollabs focus:outline-none focus:ring-2 focus:ring-coollabs } \ No newline at end of file diff --git a/docs/_data/missing.md b/docs/_data/missing.md new file mode 100644 index 00000000..fe6932ac --- /dev/null +++ b/docs/_data/missing.md @@ -0,0 +1,108 @@ +[ ] Umami +[ ] Activepieces +[ ] Actual Budget +[ ] Affine +[ ] Apprise API +[ ] Appsmith +[ ] Appwrite +[ ] Authentik +[ ] Baby Buddy +[ ] Browserless +[ ] BudgE +[ ] Bugsink +[ ] Changedetection +[ ] Chaskiq +[ ] Chatwoot +[ ] Checkmate +[ ] ClassicPress +[ ] CloudBeaver +[ ] Cloudflared +[ ] Cockpit +[ ] Code Server +[ ] Dashboard +[ ] Directus +[ ] Docker Registry +[ ] Docmost +[ ] Docuseal +[ ] DokuWiki +[ ] Dozzle +[ ] Duplicati +[ ] Emby +[ ] Emby Stat +[ ] Evolution API +[ ] Fider +[ ] Filebrowser +[ ] Firefly III +[ ] Forgejo +[ ] Formbricks +[ ] Ghost +[ ] Gitea +[ ] GitLab +[ ] Glance +[ ] Glances +[ ] GlitchTip +[ ] Gotenberg +[ ] Grafana +[ ] Grocy +[ ] Heimdall +[ ] Homepage +[ ] Immich +[ ] Invoice Ninja +[ ] Jellyfin +[ ] Jenkins +[ ] Kimai +[ ] Kuzzle +[ ] Label Studio +[ ] Langfuse +[ ] Listmonk +[ ] LiteLLM +[ ] Logto +[ ] Mailpit +[ ] MediaWiki +[ ] Meilisearch +[ ] Metabase +[ ] Metube +[ ] Minecraft +[ ] MinIO +[ ] Mixpost +[ ] Moodle +[ ] Mosquitto +[ ] Neon WS Proxy +[ ] Next Image Transformation +[ ] Nextcloud +[ ] Nexus +[ ] NocoDB +[ ] Odoo +[ ] Openblocks +[ ] Outline +[ ] Pairdrop +[ ] Penpot +[ ] phpMyAdmin +[ ] Plane +[ ] Plunk +[ ] Pocketbase +[ ] Portainer +[ ] PostHog +[ ] Prefect +[ ] RabbitMQ +[ ] Rocket.Chat +[ ] Shlink +[ ] Slash +[ ] Snapdrop +[ ] Soketi +[ ] Stirling PDF +[ ] Supabase +[ ] Superset +[ ] Syncthing +[ ] Tolgee +[ ] Trigger +[ ] Unstructured +[ ] Uptime Kuma +[ ] Vaultwarden +[ ] Vikunja +[ ] Weaviate +[ ] Weblate +[ ] Whoogle +[ ] Windmill +[ ] WordPress +[ ] Zipline \ No newline at end of file diff --git a/docs/_data/services.js b/docs/_data/services.js new file mode 100644 index 00000000..2cdd7209 --- /dev/null +++ b/docs/_data/services.js @@ -0,0 +1,1178 @@ +export const services = [ + { + name: 'Umami', + icon: '/logo.svg', + description: 'A lightweight, open-source web analytics tool that prioritizes user privacy by not using cookies.', + category: 'Analytics' + }, + { + name: 'Plausible', + icon: '/images/services/plausible.svg', + description: 'A lightweight, open-source web analytics tool that prioritizes user privacy by not using cookies.', + category: 'Analytics' + }, + { + name: 'Activepieces', + icon: '/logo.svg', + description: 'Open source no-code business automation.', + category: 'Automation' + }, + { + name: 'Actual Budget', + icon: '/logo.svg', + description: 'A local-first personal finance tool based on zero-based budgeting.', + category: 'Finance' + }, + { + name: 'Affine', + icon: '/logo.svg', + description: 'Open-source knowledge base and workspace combining docs, whiteboards, and databases.', + category: 'Productivity' + }, + { + name: 'AnythingLLM', + icon: '/images/services/anythingllm.svg', + description: 'An open-source LLM client that empowers developers to build and scale workflows quickly.', + category: 'AI' + }, + { + name: 'Apprise API', + icon: '/logo.svg', + description: 'RESTful API for Apprise notification library.', + category: 'Development' + }, + { + name: 'Appsmith', + icon: '/logo.svg', + description: 'A low-code application platform for building internal tools.', + category: 'Development' + }, + { + name: 'Appwrite', + icon: '/logo.svg', + description: 'A backend-as-a-service platform that simplifies the web & mobile app development.', + category: 'Development' + }, + { + name: 'Argilla', + icon: '/images/services/argilla.svg', + description: 'An open-source platform for building, training, and evaluating conversational AI models.', + category: 'AI' + }, + { + name: 'Audiobookshelf', + icon: '/images/services/audiobookshelf.svg', + description: 'Self-hosted audiobook and podcast server.', + category: 'Media' + }, + { + name: 'Authentik', + icon: '/logo.svg', + description: 'An open-source Identity Provider, focused on flexibility and versatility.', + category: 'Security' + }, + { + name: 'Baby Buddy', + icon: '/logo.svg', + description: 'It helps parents track their baby\'s daily activities, growth, and health with ease.', + category: 'Health' + }, + { + name: 'Beszel', + icon: '/images/services/beszel.svg', + description: 'Lightweight server monitoring hub with historical data, docker stats, and alerts.', + category: 'Monitoring' + }, + { + name: 'Bitcoin Core', + icon: '/images/services/bitcoin.svg', + description: 'Bitcoin Core full node software.', + category: 'Crypto' + }, + { + name: 'BookStack', + icon: '/images/services/bookstack.png', + description: 'Self-hosted wiki-style documentation platform.', + category: 'Documentation' + }, + { + name: 'Browserless', + icon: '/logo.svg', + description: 'Headless Chrome as a service.', + category: 'Development' + }, + { + name: 'BudgE', + icon: '/logo.svg', + description: 'A budgeting personal finance app.', + category: 'Finance' + }, + { + name: 'Budibase', + icon: '/images/services/budibase.svg', + description: 'Low-code platform for building internal tools and business apps.', + category: 'Development' + }, + { + name: 'Bugsink', + icon: '/logo.svg', + description: 'Self-hosted Error Tracking', + category: 'Development' + }, + { + name: 'Cal.com', + icon: '/images/services/calcom.png', + description: 'Open-source Calendly alternative for scheduling meetings.', + category: 'Productivity' + }, + { + name: 'Calibre-web', + icon: '/images/services/calibre-web.svg', + description: 'Web app for browsing, reading and downloading eBooks from a Calibre database.', + category: 'Media' + }, + { + name: 'Castopod', + icon: '/images/services/castopod.svg', + description: 'Open-source podcast hosting platform.', + category: 'Media' + }, + { + name: 'Changedetection', + icon: '/logo.svg', + description: 'Website change detection monitor and notifications.', + category: 'Monitoring' + }, + { + name: 'Chaskiq', + icon: '/logo.svg', + description: 'Open source customer engagement platform.', + category: 'Business' + }, + { + name: 'Chatwoot', + icon: '/logo.svg', + description: 'Open-source customer engagement suite.', + category: 'Business' + }, + { + name: 'Checkmate', + icon: '/logo.svg', + description: 'Website monitoring and uptime service.', + category: 'Monitoring' + }, + { + name: 'ClassicPress', + icon: '/logo.svg', + description: 'A business-focused CMS with a strong community.', + category: 'CMS' + }, + { + name: 'CloudBeaver', + icon: '/logo.svg', + description: 'Universal database tool with web interface.', + category: 'Development' + }, + { + name: 'Cloudflared', + icon: '/logo.svg', + description: 'Cloudflare Tunnel client.', + category: 'Networking' + }, + { + name: 'Cockpit', + icon: '/logo.svg', + description: 'Web-based server administration interface.', + category: 'Administration' + }, + { + name: 'Code Server', + icon: '/logo.svg', + description: 'Run VS Code on any machine anywhere and access it in the browser.', + category: 'Development' + }, + { + name: 'ConvertX', + icon: '/images/services/convertx.png', + description: 'File conversion service supporting multiple formats.', + category: 'Utilities' + }, + { + name: 'Convex', + icon: '/images/services/convex.svg', + description: 'Backend platform for web developers.', + category: 'Development' + }, + { + name: 'Cryptgeon', + icon: '/images/services/cryptgeon.png', + description: 'Secure note sharing service with self-destructing messages.', + category: 'Security' + }, + { + name: 'CyberChef', + icon: '/images/services/cyberchef.jpeg', + description: 'Data analysis and manipulation tool for cybersecurity.', + category: 'Security' + }, + { + name: 'Dashboard', + icon: '/logo.svg', + description: 'A simple dashboard for your server.', + category: 'Administration' + }, + { + name: 'Dashy', + icon: '/images/services/dashy.png', + description: 'Customizable homepage dashboard for self-hosted services.', + category: 'Administration' + }, + { + name: 'Deno KV', + icon: '/images/services/deno-looking-up.svg', + description: 'Deno\'s built-in key-value database service.', + category: 'Development' + }, + { + name: 'Directus', + icon: '/logo.svg', + description: 'An open-source headless CMS and API for custom databases.', + category: 'CMS' + }, + { + name: 'Docker Registry', + icon: '/logo.svg', + description: 'A Docker registry to store and manage your Docker images.', + category: 'Development' + }, + { + name: 'Docmost', + icon: '/logo.svg', + description: 'Open-source document collaboration platform.', + category: 'Documentation' + }, + { + name: 'Documenso', + icon: '/images/services/documenso.png', + description: 'Open-source DocuSign alternative for document signing.', + category: 'Business' + }, + { + name: 'Docuseal', + icon: '/logo.svg', + description: 'Open source DocuSign alternative.', + category: 'Business' + }, + { + name: 'DokuWiki', + icon: '/logo.svg', + description: 'A simple to use and highly versatile Open Source wiki software that doesn\'t require a database.', + category: 'Documentation' + }, + { + name: 'Dolibarr', + icon: '/images/services/dolibarr.png', + description: 'Open-source ERP and CRM software.', + category: 'Business' + }, + { + name: 'Dozzle', + icon: '/logo.svg', + description: 'Realtime log viewer for docker containers.', + category: 'Development' + }, + { + name: 'Drupal', + icon: '/images/services/drupal.svg', + description: 'Open-source content management system.', + category: 'CMS' + }, + { + name: 'Duplicati', + icon: '/logo.svg', + description: 'A free backup client that securely stores encrypted, incremental, compressed backups on cloud storage services and remote file servers.', + category: 'Backup' + }, + { + name: 'Easy Appointments', + icon: '/images/services/easyappointments.png', + description: 'Open-source appointment scheduler.', + category: 'Business' + }, + { + name: 'Emby', + icon: '/logo.svg', + description: 'A media server to organize, play, and stream audio and video to a variety of devices.', + category: 'Media' + }, + { + name: 'Emby Stat', + icon: '/logo.svg', + description: 'A simple and easy-to-use Emby statistics dashboard.', + category: 'Media' + }, + { + name: 'Evolution API', + icon: '/logo.svg', + description: 'WhatsApp API service for automation.', + category: 'Automation' + }, + { + name: 'Faraday', + icon: '/images/services/faraday.png', + description: 'Collaborative penetration testing and vulnerability management platform.', + category: 'Security' + }, + { + name: 'Fider', + icon: '/logo.svg', + description: 'An open platform to collect and organize customer feedback.', + category: 'Business' + }, + { + name: 'Filebrowser', + icon: '/logo.svg', + description: 'A file manager for the web.', + category: 'File Management' + }, + { + name: 'FileFlows', + icon: '/images/services/fileflows.svg', + description: 'A automatic file processing service.', + category: 'File Management' + }, + { + name: 'Firefly III', + icon: '/logo.svg', + description: 'A personal finances manager.', + category: 'Finance' + }, + { + name: 'Firefox', + icon: '/images/services/firefox.png', + description: 'Firefox browser in a container.', + category: 'Browser' + }, + { + name: 'Flipt', + icon: '/images/services/flipt.svg', + description: 'Open-source feature flag management platform.', + category: 'Development' + }, + { + name: 'Flowise', + icon: '/images/services/flowise.svg', + description: 'Drag & drop UI to build your customized LLM flow.', + category: 'AI' + }, + { + name: 'Forgejo', + icon: '/logo.svg', + description: 'A self-hosted Git service fork of Gitea.', + category: 'Development' + }, + { + name: 'Formbricks', + icon: '/logo.svg', + description: 'A form builder for static sites.', + category: 'Development' + }, + { + name: 'FoundryVTT', + icon: '/images/services/foundryvtt.png', + description: 'Virtual tabletop for tabletop role-playing games.', + category: 'Gaming' + }, + { + name: 'FreeScout', + icon: '/images/services/freescout.png', + description: 'Help desk and customer support application.', + category: 'Business' + }, + { + name: 'FreshRSS', + icon: '/images/services/FreshRSS-logo.png', + description: 'Free, self-hostable RSS feed aggregator.', + category: 'RSS' + }, + { + name: 'Ghost', + icon: '/logo.svg', + description: 'A professional publishing platform.', + category: 'CMS' + }, + { + name: 'Gitea', + icon: '/logo.svg', + description: 'A painless self-hosted Git service.', + category: 'Development' + }, + { + name: 'GitLab', + icon: '/logo.svg', + description: 'DevOps lifecycle tool.', + category: 'Development' + }, + { + name: 'Glance', + icon: '/logo.svg', + description: 'All-in-one Home Server Dashboard.', + category: 'Administration' + }, + { + name: 'Glances', + icon: '/logo.svg', + description: 'Cross-platform system monitoring tool.', + category: 'Monitoring' + }, + { + name: 'GlitchTip', + icon: '/logo.svg', + description: 'An open-source error tracking tool.', + category: 'Development' + }, + { + name: 'Gotenberg', + icon: '/logo.svg', + description: 'A Docker-powered stateless API for PDF files.', + category: 'Development' + }, + { + name: 'Grafana', + icon: '/logo.svg', + description: 'The open platform for beautiful analytics and monitoring.', + category: 'Monitoring' + }, + { + name: 'Grocy', + icon: '/logo.svg', + description: 'A self-hosted groceries & household management solution for your home.', + category: 'Home' + }, + { + name: 'Heimdall', + icon: '/logo.svg', + description: 'An elegant solution to organize all your web applications.', + category: 'Administration' + }, + { + name: 'HeyForm', + icon: '/images/services/heyform.svg', + description: 'Open-source form builder for conversational forms.', + category: 'Development' + }, + { + name: 'Hoarder', + icon: '/images/services/hoarder.png', + description: 'Self-hosted bookmark manager with AI-powered tagging.', + category: 'Bookmarks' + }, + { + name: 'Homarr', + icon: '/images/services/homarr.png', + description: 'Customizable browser homepage and dashboard.', + category: 'Administration' + }, + { + name: 'Homepage', + icon: '/logo.svg', + description: 'A modern homepage for your server.', + category: 'Administration' + }, + { + name: 'Hoppscotch', + icon: '/images/services/hoppscotch.png', + description: 'Open-source API development ecosystem.', + category: 'Development' + }, + { + name: 'Immich', + icon: '/logo.svg', + description: 'Self-hosted photo and video backup solution.', + category: 'Media' + }, + { + name: 'Infisical', + icon: '/images/services/infisical.svg', + description: 'Open source secret management platform.', + category: 'Security' + }, + { + name: 'Invoice Ninja', + icon: '/logo.svg', + description: 'Invoice management system.', + category: 'Business' + }, + { + name: 'IT Tools', + icon: '/images/services/it-tools.svg', + description: 'Collection of handy online tools for developers.', + category: 'Development' + }, + { + name: 'Jellyfin', + icon: '/logo.svg', + description: 'The Free Software Media System.', + category: 'Media' + }, + { + name: 'Jenkins', + icon: '/logo.svg', + description: 'Open-source automation server.', + category: 'Development' + }, + { + name: 'Joomla', + icon: '/images/services/Joomla!-Logo.svg', + description: 'Open-source content management system.', + category: 'CMS' + }, + { + name: 'Joplin', + icon: '/images/services/joplin.png', + description: 'Open-source note taking and to-do application.', + category: 'Productivity' + }, + { + name: 'Jupyter Notebook', + icon: '/images/services/jupyter.svg', + description: 'Interactive computing environment for Python.', + category: 'Development' + }, + { + name: 'Keycloak', + icon: '/images/services/keycloak.svg', + description: 'Open-source identity and access management solution.', + category: 'Security' + }, + { + name: 'Kimai', + icon: '/logo.svg', + description: 'An open-source time-tracking solution for teams of all sizes.', + category: 'Business' + }, + { + name: 'Kuzzle', + icon: '/logo.svg', + description: 'A powerful backend that enables you to build modern apps faster.', + category: 'Development' + }, + { + name: 'Label Studio', + icon: '/logo.svg', + description: 'Open source data labeling platform.', + category: 'AI' + }, + { + name: 'Langfuse', + icon: '/logo.svg', + description: 'Open source LLM engineering platform.', + category: 'AI' + }, + { + name: 'LibreOffice', + icon: '/images/services/libreoffice.svg', + description: 'Free and open-source office suite.', + category: 'Productivity' + }, + { + name: 'LibreTranslate', + icon: '/images/services/libretranslate.svg', + description: 'Free and open-source machine translation API.', + category: 'AI' + }, + { + name: 'Listmonk', + icon: '/logo.svg', + description: 'Self-hosted newsletter and mailing list manager.', + category: 'Marketing' + }, + { + name: 'LiteLLM', + icon: '/logo.svg', + description: 'Open source LLM Gateway to manage authentication, loadbalancing, and spend tracking across 100+ LLMs. All in the OpenAI format.', + category: 'AI' + }, + { + name: 'LiteQueen', + icon: '/images/services/litequeen.svg', + description: 'Lightweight service management platform.', + category: 'Administration' + }, + { + name: 'Logto', + icon: '/logo.svg', + description: 'Logto is an Auth0 alternative designed for modern apps and SaaS products.', + category: 'Security' + }, + { + name: 'Lowcoder', + icon: '/images/services/lowcoder.svg', + description: 'Open-source low-code platform for building internal tools.', + category: 'Development' + }, + { + name: 'Mailpit', + icon: '/logo.svg', + description: 'Self-hosted email and SMTP testing tool.', + category: 'Development' + }, + { + name: 'Martin', + icon: '/images/services/martin.png', + description: 'PostGIS vector tile server.', + category: 'Development' + }, + { + name: 'Mattermost', + icon: '/images/services/mattermost.svg', + description: 'Open-source messaging platform for teams.', + category: 'Communication' + }, + { + name: 'Mautic', + icon: '/images/services/mautic.svg', + description: 'Open-source marketing automation platform.', + category: 'Marketing' + }, + { + name: 'Maybe', + icon: '/images/services/maybe.svg', + description: 'Personal finance and wealth management application.', + category: 'Finance' + }, + { + name: 'Mealie', + icon: '/images/services/mealie.png', + description: 'Self-hosted recipe manager and meal planner.', + category: 'Home' + }, + { + name: 'MediaWiki', + icon: '/logo.svg', + description: 'A free and open-source wiki software package.', + category: 'Documentation' + }, + { + name: 'Meilisearch', + icon: '/logo.svg', + description: 'A powerful, fast, open-source, easy to use, and deploy search engine.', + category: 'Search' + }, + { + name: 'Metabase', + icon: '/logo.svg', + description: 'The simplest, fastest way to share data and analytics inside your company.', + category: 'Analytics' + }, + { + name: 'Metube', + icon: '/logo.svg', + description: 'A self-hosted video sharing platform.', + category: 'Media' + }, + { + name: 'MindsDB', + icon: '/images/services/mindsdb.svg', + description: 'Machine learning platform that brings AI to databases.', + category: 'AI' + }, + { + name: 'Minecraft', + icon: '/logo.svg', + description: 'Minecraft game server.', + category: 'Gaming' + }, + { + name: 'MinIO', + icon: '/logo.svg', + description: 'A high-performance, distributed object storage system.', + category: 'Storage' + }, + { + name: 'Mixpost', + icon: '/logo.svg', + description: 'Self-hosted social media management software (Buffer alternative).', + category: 'Social Media' + }, + { + name: 'Moodle', + icon: '/logo.svg', + description: 'Open-source learning platform.', + category: 'Education' + }, + { + name: 'Mosquitto', + icon: '/logo.svg', + description: 'Open-source MQTT broker.', + category: 'IoT' + }, + { + name: 'n8n', + icon: '/images/services/n8n.svg', + description: 'Workflow automation tool.', + category: 'Automation' + }, + { + name: 'Neon WS Proxy', + icon: '/logo.svg', + description: 'WebSocket proxy for Neon database.', + category: 'Development' + }, + { + name: 'Next Image Transformation', + icon: '/logo.svg', + description: 'Image transformation service for Next.js.', + category: 'Development' + }, + { + name: 'Nextcloud', + icon: '/logo.svg', + description: 'A safe home for all your data.', + category: 'Storage' + }, + { + name: 'Nexus', + icon: '/logo.svg', + description: 'A repository manager that allows you to store, manage, and distribute your software artifacts.', + category: 'Development' + }, + { + name: 'Nitropage', + icon: '/images/services/nitropage.svg', + description: 'Nitropage is an extensible, drag-and-drop website builder based on SolidStart, completely free and open source.', + category: 'Development' + }, + { + name: 'NocoDB', + icon: '/logo.svg', + description: 'Open Source Airtable Alternative.', + category: 'Database' + }, + { + name: 'NodeBB', + icon: '/images/services/nodebb.svg', + description: 'Node.js based forum software.', + category: 'Forum' + }, + { + name: 'Ntfy', + icon: '/images/services/ntfy.svg', + description: 'Simple HTTP-based pub-sub notification service.', + category: 'Notifications' + }, + { + name: 'Odoo', + icon: '/logo.svg', + description: 'Open source ERP and CRM.', + category: 'Business' + }, + { + name: 'Ollama', + icon: '/images/services/ollama.svg', + description: 'A lightweight and efficient server for running large language models (LLMs) on your local machine or in the cloud.', + category: 'AI' + }, + { + name: 'OneDev', + icon: '/images/services/onedev.svg', + description: 'Self-hosted Git server with integrated CI/CD and kanban.', + category: 'Development' + }, + { + name: 'Open WebUI', + icon: '/images/services/openwebui.svg', + description: 'User-friendly WebUI for LLMs, formerly Ollama WebUI.', + category: 'AI' + }, + { + name: 'Openblocks', + icon: '/logo.svg', + description: 'Open-source low code platform.', + category: 'Development' + }, + { + name: 'Organizr', + icon: '/images/services/organizr.png', + description: 'Homepage organizer for your server services.', + category: 'Administration' + }, + { + name: 'osTicket', + icon: '/images/services/osticket.png', + description: 'Open-source help desk ticketing system.', + category: 'Business' + }, + { + name: 'Outline', + icon: '/logo.svg', + description: 'Open-source collaboration tool.', + category: 'Productivity' + }, + { + name: 'Overseerr', + icon: '/images/services/overseerr.svg', + description: 'A request management and media discovery tool built to work with your existing Plex ecosystem.', + category: 'Media' + }, + { + name: 'ownCloud', + icon: '/images/services/owncloud.svg', + description: 'File synchronization and sharing platform.', + category: 'Storage' + }, + { + name: 'Pairdrop', + icon: '/logo.svg', + description: 'Local file sharing in your browser.', + category: 'File Sharing' + }, + { + name: 'Paperless', + icon: '/images/services/paperless.png', + description: 'Document management system that transforms physical documents into searchable online archives.', + category: 'Documentation' + }, + { + name: 'Paymenter', + icon: '/images/services/paymenter.svg', + description: 'Open-Source Billing, Built for Hosting Providers.', + category: 'Business' + }, + { + name: 'Penpot', + icon: '/logo.svg', + description: 'Open Source design & prototyping platform.', + category: 'Design' + }, + { + name: 'phpMyAdmin', + icon: '/logo.svg', + description: 'MySQL database management tool.', + category: 'Development' + }, + { + name: 'Plane', + icon: '/logo.svg', + description: 'Open source project planning tool.', + category: 'Project Management' + }, + { + name: 'Plex', + icon: '/images/services/plex.svg', + description: 'Media server software.', + category: 'Media' + }, + { + name: 'Plunk', + icon: '/logo.svg', + description: 'Self-hosted email marketing platform.', + category: 'Marketing' + }, + { + name: 'Pocketbase', + icon: '/logo.svg', + description: 'Open Source backend for your next SaaS and Mobile app.', + category: 'Development' + }, + { + name: 'Portainer', + icon: '/logo.svg', + description: 'Container management platform.', + category: 'Development' + }, + { + name: 'PostHog', + icon: '/logo.svg', + description: 'Open source product analytics.', + category: 'Analytics' + }, + { + name: 'Postiz', + icon: '/images/services/postiz.png', + description: 'Social media scheduling and analytics tool.', + category: 'Social Media' + }, + { + name: 'Prefect', + icon: '/logo.svg', + description: 'Open source workflow management platform.', + category: 'Development' + }, + { + name: 'PrivateBin', + icon: '/images/services/privatebin.svg', + description: 'Minimalist, open-source online pastebin.', + category: 'Development' + }, + { + name: 'Prowlarr', + icon: '/images/services/prowlarr.svg', + description: 'A free and open source BitTorrent client.', + category: 'Media' + }, + { + name: 'qBittorrent', + icon: '/images/services/qbittorrent.svg', + description: 'Free and open-source BitTorrent client.', + category: 'Media' + }, + { + name: 'Qdrant', + icon: '/images/services/qdrant.svg', + description: 'Open source, AI-native vector database.', + category: 'AI' + }, + { + name: 'RabbitMQ', + icon: '/logo.svg', + description: 'Open source message broker.', + category: 'Development' + }, + { + name: 'Radarr', + icon: '/images/services/radarr.svg', + description: 'A Media server software.', + category: 'Media' + }, + { + name: 'Rallly', + icon: '/images/services/rallly.svg', + description: 'Open-source meeting scheduling tool.', + category: 'Productivity' + }, + { + name: 'Reactive Resume', + icon: '/images/services/rxresume.svg', + description: 'A free and open source resume builder.', + category: 'Productivity' + }, + { + name: 'Readeck', + icon: '/images/services/readeck.svg', + description: 'Web article reader and bookmark manager.', + category: 'Productivity' + }, + { + name: 'Redlib', + icon: '/images/services/redlib.svg', + description: 'Private front-end for Reddit.', + category: 'Social Media' + }, + { + name: 'Rocket.Chat', + icon: '/logo.svg', + description: 'Open source team chat software.', + category: 'Communication' + }, + { + name: 'SearXNG', + icon: '/images/services/searxng.svg', + description: 'Open source search engine.', + category: 'Search' + }, + { + name: 'Shlink', + icon: '/logo.svg', + description: 'The open source URL shortener.', + category: 'Development' + }, + { + name: 'Slash', + icon: '/logo.svg', + description: 'Open-source, self-hosted links and notes manager.', + category: 'Productivity' + }, + { + name: 'Snapdrop', + icon: '/logo.svg', + description: 'Local file sharing in your browser.', + category: 'File Sharing' + }, + { + name: 'Soketi', + icon: '/logo.svg', + description: 'Open-source WebSocket server.', + category: 'Development' + }, + { + name: 'Sonarr', + icon: '/images/services/sonarr.svg', + description: 'A internet PVR for Usenet and Torrents.', + category: 'Media' + }, + { + name: 'Statusnook', + icon: '/images/services/statusnook.svg', + description: 'A status page system for your website.', + category: 'Monitoring' + }, + { + name: 'Stirling PDF', + icon: '/logo.svg', + description: 'Powerful PDF manipulation tool.', + category: 'Documentation' + }, + { + name: 'Strapi', + icon: '/images/services/strapi.svg', + description: 'Open-source headless CMS.', + category: 'CMS' + }, + { + name: 'Supabase', + icon: '/logo.svg', + description: 'Open source Firebase alternative.', + category: 'Development' + }, + { + name: 'Superset', + icon: '/logo.svg', + description: 'Open-source data visualization and exploration platform.', + category: 'Analytics' + }, + { + name: 'SuperTokens', + icon: '/images/services/supertokens.png', + description: 'Open-source authentication solution.', + category: 'Security' + }, + { + name: 'Syncthing', + icon: '/logo.svg', + description: 'Open Source Continuous File Synchronization.', + category: 'File Management' + }, + { + name: 'Teable', + icon: '/images/services/teable.png', + description: 'No-code database built on PostgreSQL.', + category: 'Database' + }, + { + name: 'Tolgee', + icon: '/logo.svg', + description: 'Open source localization platform.', + category: 'Development' + }, + { + name: 'Traccar', + icon: '/images/services/traccar.png', + description: 'Open-source GPS tracking platform.', + category: 'IoT' + }, + { + name: 'Transmission', + icon: '/images/services/transmission.png', + description: 'Fast, easy, and free BitTorrent client.', + category: 'Media' + }, + { + name: 'Trigger', + icon: '/logo.svg', + description: 'Open-source workflow automation tool.', + category: 'Automation' + }, + { + name: 'Unleash', + icon: '/images/services/unleash.svg', + description: 'Open-source feature management platform.', + category: 'Development' + }, + { + name: 'Unsend', + icon: '/images/services/unsend.svg', + description: 'Open-source email recall service.', + category: 'Email' + }, + { + name: 'Unstructured', + icon: '/logo.svg', + description: 'Open-source platform and tools to ingest and process unstructured documents for Retrieval Augmented Generation (RAG) and model fine-tuning.', + category: 'AI' + }, + { + name: 'Uptime Kuma', + icon: '/logo.svg', + description: 'A fancy self-hosted monitoring tool.', + category: 'Monitoring' + }, + { + name: 'Vaultwarden', + icon: '/logo.svg', + description: 'Unofficial Bitwarden compatible server.', + category: 'Security' + }, + { + name: 'Vikunja', + icon: '/logo.svg', + description: 'The open-source to-do app.', + category: 'Productivity' + }, + { + name: 'VvvebJs', + icon: '/images/services/vvveb.png', + description: 'Powerful website builder with drag and drop functionality.', + category: 'Development' + }, + { + name: 'Wakapi', + icon: '/images/services/wakapi.svg', + description: 'Open-source coding activity tracker.', + category: 'Development' + }, + { + name: 'Weaviate', + icon: '/logo.svg', + description: 'Open source, AI-native vector database.', + category: 'AI' + }, + { + name: 'Web Check', + icon: '/images/services/web-check.png', + description: 'All-in-one website analysis tool.', + category: 'Development' + }, + { + name: 'Weblate', + icon: '/logo.svg', + description: 'Web-based translation tool.', + category: 'Development' + }, + { + name: 'Whoogle', + icon: '/logo.svg', + description: 'Self-hosted, ad-free, privacy-respecting metasearch engine.', + category: 'Search' + }, + { + name: 'Wiki.js', + icon: '/images/services/wikijs.svg', + description: 'Modern and powerful wiki software built on Node.js.', + category: 'Documentation' + }, + { + name: 'Windmill', + icon: '/logo.svg', + description: 'Open-source developer platform.', + category: 'Development' + }, + { + name: 'WireGuard Easy', + icon: '/images/services/wireguard.svg', + description: 'Easy-to-use WireGuard VPN server.', + category: 'Security' + }, + { + name: 'WordPress', + icon: '/logo.svg', + description: 'Website and blogging platform.', + category: 'CMS' + }, + { + name: 'Zipline', + icon: '/logo.svg', + description: 'Next generation ShareX / File upload server', + category: 'File Management' + } +] \ No newline at end of file diff --git a/docs/public/images/services/n8n.svg b/docs/public/images/services/n8n.svg new file mode 100644 index 00000000..82f0a6da --- /dev/null +++ b/docs/public/images/services/n8n.svg @@ -0,0 +1 @@ +n8n \ No newline at end of file diff --git a/docs/public/images/team/serdar.webp b/docs/public/images/team/serdar.webp index 9931b6fc..bd89a1cb 100644 Binary files a/docs/public/images/team/serdar.webp and b/docs/public/images/team/serdar.webp differ diff --git a/docs/services/overview.md b/docs/services/overview.md index f2bcb142..b369f0a6 100644 --- a/docs/services/overview.md +++ b/docs/services/overview.md @@ -1,10 +1,7 @@ --- title: Overview -layout: doc +layout: page +aside: false --- -# Services - -This list only includes services that are available as one-click services in Coolify. - - \ No newline at end of file + \ No newline at end of file diff --git a/package.json b/package.json index ef8fa003..b11ee9c9 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "documentation-coolify", "version": "0.0.1", "devDependencies": { + "@iconify/vue": "^5.0.0", "@types/js-yaml": "4.0.9", "@types/node": "22.13.1", "autoprefixer": "10.4.20", @@ -30,12 +31,12 @@ "scripts": { "dev": "vitepress dev docs", "build": "vitepress build docs", - "preview": "vitepress preview docs", - "transform-openapi": "tsx scripts/convert-openapi.ts" + "preview": "vitepress preview docs" }, "dependencies": { "@vueuse/core": "12.5.0", "globe.gl": "2.39.7", + "motion-v": "^1.7.0", "vitepress-openapi": "0.0.3-alpha.78" }, "packageManager": "pnpm@10.6.3+sha512.bb45e34d50a9a76e858a95837301bfb6bd6d35aea2c5d52094fa497a467c43f5c440103ce2511e9e0a2f89c3d6071baac3358fc68ac6fb75e2ceb3d2736065e6" diff --git a/scripts/convert-openapi.ts b/scripts/convert-openapi.ts deleted file mode 100644 index 78e3634e..00000000 --- a/scripts/convert-openapi.ts +++ /dev/null @@ -1,25 +0,0 @@ -const yaml = require('js-yaml') -const fs = require('fs') -const path = require('path') - -const convertYamlToJson = () => { - try { - // Read the YAML file from the public folder - const yamlPath = path.resolve(__dirname, '../docs/public/openapi.yml') - const yamlContent = fs.readFileSync(yamlPath, 'utf8') - - // Parse YAML to JSON - const jsonContent = yaml.load(yamlContent) - - // Write JSON to public folder next to the YAML file - const jsonPath = path.resolve(__dirname, '../docs/public/openapi.json') - fs.writeFileSync(jsonPath, JSON.stringify(jsonContent, null, 2)) - - console.log('Successfully converted YAML to JSON') - console.log(`Output file: ${jsonPath}`) - } catch (error) { - console.error('Error converting YAML to JSON:', error) - } -} - -convertYamlToJson() \ No newline at end of file diff --git a/tailwind.config.js b/tailwind.config.js index 45feb3ca..1b45195b 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,7 +1,21 @@ +/** @type {import('tailwindcss').Config} */ module.exports = { content: [ './docs/.vitepress/**/*.{js,ts,vue}', './docs/**/*.md', ], darkMode: 'class', + theme: { + extend: { + colors: { + "coollabs": "#6b16ed", + "coollabs-100": "#7317ff", + "coolgray-100": "#181818", + "coolgray-200": "#202020", + "coolgray-300": "#242424", + "coolgray-400": "#282828", + "coolgray-500": "#323232", + } + } + } } \ No newline at end of file