mirror of
https://github.com/Dokploy/website.git
synced 2026-06-15 20:25:25 +02:00
Merge pull request #121 from Dokploy/feat/add-templates-ref
Feat/add templates ref
This commit is contained in:
@@ -14,6 +14,8 @@ RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --filter=./apps/d
|
|||||||
# Generate OpenAPI documentation from apps/docs/public/openapi.json
|
# Generate OpenAPI documentation from apps/docs/public/openapi.json
|
||||||
RUN pnpm --filter=./apps/docs run build:docs
|
RUN pnpm --filter=./apps/docs run build:docs
|
||||||
|
|
||||||
|
# Generate templates
|
||||||
|
RUN pnpm --filter=./apps/docs run generate-templates
|
||||||
# Deploy only the dokploy app
|
# Deploy only the dokploy app
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ _openapi:
|
|||||||
- depth: 2
|
- depth: 2
|
||||||
title: Registry test Registry
|
title: Registry test Registry
|
||||||
url: '#registry-test-registry'
|
url: '#registry-test-registry'
|
||||||
|
- depth: 2
|
||||||
|
title: Registry test Registry By Id
|
||||||
|
url: '#registry-test-registry-by-id'
|
||||||
structuredData:
|
structuredData:
|
||||||
headings:
|
headings:
|
||||||
- content: Registry create
|
- content: Registry create
|
||||||
@@ -35,9 +38,11 @@ _openapi:
|
|||||||
id: registry-one
|
id: registry-one
|
||||||
- content: Registry test Registry
|
- content: Registry test Registry
|
||||||
id: registry-test-registry
|
id: registry-test-registry
|
||||||
|
- content: Registry test Registry By Id
|
||||||
|
id: registry-test-registry-by-id
|
||||||
contents: []
|
contents: []
|
||||||
---
|
---
|
||||||
|
|
||||||
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
|
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
|
||||||
|
|
||||||
<APIPage document={"./public/openapi.json"} webhooks={[]} operations={[{"path":"/registry.create","method":"post"},{"path":"/registry.remove","method":"post"},{"path":"/registry.update","method":"post"},{"path":"/registry.all","method":"get"},{"path":"/registry.one","method":"get"},{"path":"/registry.testRegistry","method":"post"}]} showTitle={true} />
|
<APIPage document={"./public/openapi.json"} webhooks={[]} operations={[{"path":"/registry.create","method":"post"},{"path":"/registry.remove","method":"post"},{"path":"/registry.update","method":"post"},{"path":"/registry.all","method":"get"},{"path":"/registry.one","method":"get"},{"path":"/registry.testRegistry","method":"post"},{"path":"/registry.testRegistryById","method":"post"}]} showTitle={true} />
|
||||||
@@ -3,6 +3,9 @@ title: Settings
|
|||||||
full: true
|
full: true
|
||||||
_openapi:
|
_openapi:
|
||||||
toc:
|
toc:
|
||||||
|
- depth: 2
|
||||||
|
title: Settings get Web Server Settings
|
||||||
|
url: '#settings-get-web-server-settings'
|
||||||
- depth: 2
|
- depth: 2
|
||||||
title: Settings reload Server
|
title: Settings reload Server
|
||||||
url: '#settings-reload-server'
|
url: '#settings-reload-server'
|
||||||
@@ -93,6 +96,9 @@ _openapi:
|
|||||||
- depth: 2
|
- depth: 2
|
||||||
title: Settings get Ip
|
title: Settings get Ip
|
||||||
url: '#settings-get-ip'
|
url: '#settings-get-ip'
|
||||||
|
- depth: 2
|
||||||
|
title: Settings update Server Ip
|
||||||
|
url: '#settings-update-server-ip'
|
||||||
- depth: 2
|
- depth: 2
|
||||||
title: Settings get Open Api Document
|
title: Settings get Open Api Document
|
||||||
url: '#settings-get-open-api-document'
|
url: '#settings-get-open-api-document'
|
||||||
@@ -143,6 +149,8 @@ _openapi:
|
|||||||
url: '#settings-get-dokploy-cloud-ips'
|
url: '#settings-get-dokploy-cloud-ips'
|
||||||
structuredData:
|
structuredData:
|
||||||
headings:
|
headings:
|
||||||
|
- content: Settings get Web Server Settings
|
||||||
|
id: settings-get-web-server-settings
|
||||||
- content: Settings reload Server
|
- content: Settings reload Server
|
||||||
id: settings-reload-server
|
id: settings-reload-server
|
||||||
- content: Settings clean Redis
|
- content: Settings clean Redis
|
||||||
@@ -203,6 +211,8 @@ _openapi:
|
|||||||
id: settings-read-traefik-file
|
id: settings-read-traefik-file
|
||||||
- content: Settings get Ip
|
- content: Settings get Ip
|
||||||
id: settings-get-ip
|
id: settings-get-ip
|
||||||
|
- content: Settings update Server Ip
|
||||||
|
id: settings-update-server-ip
|
||||||
- content: Settings get Open Api Document
|
- content: Settings get Open Api Document
|
||||||
id: settings-get-open-api-document
|
id: settings-get-open-api-document
|
||||||
- content: Settings read Traefik Env
|
- content: Settings read Traefik Env
|
||||||
@@ -240,4 +250,4 @@ _openapi:
|
|||||||
|
|
||||||
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
|
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
|
||||||
|
|
||||||
<APIPage document={"./public/openapi.json"} webhooks={[]} operations={[{"path":"/settings.reloadServer","method":"post"},{"path":"/settings.cleanRedis","method":"post"},{"path":"/settings.reloadRedis","method":"post"},{"path":"/settings.reloadTraefik","method":"post"},{"path":"/settings.toggleDashboard","method":"post"},{"path":"/settings.cleanUnusedImages","method":"post"},{"path":"/settings.cleanUnusedVolumes","method":"post"},{"path":"/settings.cleanStoppedContainers","method":"post"},{"path":"/settings.cleanDockerBuilder","method":"post"},{"path":"/settings.cleanDockerPrune","method":"post"},{"path":"/settings.cleanAll","method":"post"},{"path":"/settings.cleanMonitoring","method":"post"},{"path":"/settings.saveSSHPrivateKey","method":"post"},{"path":"/settings.assignDomainServer","method":"post"},{"path":"/settings.cleanSSHPrivateKey","method":"post"},{"path":"/settings.updateDockerCleanup","method":"post"},{"path":"/settings.readTraefikConfig","method":"get"},{"path":"/settings.updateTraefikConfig","method":"post"},{"path":"/settings.readWebServerTraefikConfig","method":"get"},{"path":"/settings.updateWebServerTraefikConfig","method":"post"},{"path":"/settings.readMiddlewareTraefikConfig","method":"get"},{"path":"/settings.updateMiddlewareTraefikConfig","method":"post"},{"path":"/settings.getUpdateData","method":"post"},{"path":"/settings.updateServer","method":"post"},{"path":"/settings.getDokployVersion","method":"get"},{"path":"/settings.getReleaseTag","method":"get"},{"path":"/settings.readDirectories","method":"get"},{"path":"/settings.updateTraefikFile","method":"post"},{"path":"/settings.readTraefikFile","method":"get"},{"path":"/settings.getIp","method":"get"},{"path":"/settings.getOpenApiDocument","method":"get"},{"path":"/settings.readTraefikEnv","method":"get"},{"path":"/settings.writeTraefikEnv","method":"post"},{"path":"/settings.haveTraefikDashboardPortEnabled","method":"get"},{"path":"/settings.haveActivateRequests","method":"get"},{"path":"/settings.toggleRequests","method":"post"},{"path":"/settings.isCloud","method":"get"},{"path":"/settings.isUserSubscribed","method":"get"},{"path":"/settings.health","method":"get"},{"path":"/settings.setupGPU","method":"post"},{"path":"/settings.checkGPUStatus","method":"get"},{"path":"/settings.updateTraefikPorts","method":"post"},{"path":"/settings.getTraefikPorts","method":"get"},{"path":"/settings.updateLogCleanup","method":"post"},{"path":"/settings.getLogCleanupStatus","method":"get"},{"path":"/settings.getDokployCloudIps","method":"get"}]} showTitle={true} />
|
<APIPage document={"./public/openapi.json"} webhooks={[]} operations={[{"path":"/settings.getWebServerSettings","method":"get"},{"path":"/settings.reloadServer","method":"post"},{"path":"/settings.cleanRedis","method":"post"},{"path":"/settings.reloadRedis","method":"post"},{"path":"/settings.reloadTraefik","method":"post"},{"path":"/settings.toggleDashboard","method":"post"},{"path":"/settings.cleanUnusedImages","method":"post"},{"path":"/settings.cleanUnusedVolumes","method":"post"},{"path":"/settings.cleanStoppedContainers","method":"post"},{"path":"/settings.cleanDockerBuilder","method":"post"},{"path":"/settings.cleanDockerPrune","method":"post"},{"path":"/settings.cleanAll","method":"post"},{"path":"/settings.cleanMonitoring","method":"post"},{"path":"/settings.saveSSHPrivateKey","method":"post"},{"path":"/settings.assignDomainServer","method":"post"},{"path":"/settings.cleanSSHPrivateKey","method":"post"},{"path":"/settings.updateDockerCleanup","method":"post"},{"path":"/settings.readTraefikConfig","method":"get"},{"path":"/settings.updateTraefikConfig","method":"post"},{"path":"/settings.readWebServerTraefikConfig","method":"get"},{"path":"/settings.updateWebServerTraefikConfig","method":"post"},{"path":"/settings.readMiddlewareTraefikConfig","method":"get"},{"path":"/settings.updateMiddlewareTraefikConfig","method":"post"},{"path":"/settings.getUpdateData","method":"post"},{"path":"/settings.updateServer","method":"post"},{"path":"/settings.getDokployVersion","method":"get"},{"path":"/settings.getReleaseTag","method":"get"},{"path":"/settings.readDirectories","method":"get"},{"path":"/settings.updateTraefikFile","method":"post"},{"path":"/settings.readTraefikFile","method":"get"},{"path":"/settings.getIp","method":"get"},{"path":"/settings.updateServerIp","method":"post"},{"path":"/settings.getOpenApiDocument","method":"get"},{"path":"/settings.readTraefikEnv","method":"get"},{"path":"/settings.writeTraefikEnv","method":"post"},{"path":"/settings.haveTraefikDashboardPortEnabled","method":"get"},{"path":"/settings.haveActivateRequests","method":"get"},{"path":"/settings.toggleRequests","method":"post"},{"path":"/settings.isCloud","method":"get"},{"path":"/settings.isUserSubscribed","method":"get"},{"path":"/settings.health","method":"get"},{"path":"/settings.setupGPU","method":"post"},{"path":"/settings.checkGPUStatus","method":"get"},{"path":"/settings.updateTraefikPorts","method":"post"},{"path":"/settings.getTraefikPorts","method":"get"},{"path":"/settings.updateLogCleanup","method":"post"},{"path":"/settings.getLogCleanupStatus","method":"get"},{"path":"/settings.getDokployCloudIps","method":"get"}]} showTitle={true} />
|
||||||
@@ -35,7 +35,6 @@
|
|||||||
"applications",
|
"applications",
|
||||||
"docker-compose",
|
"docker-compose",
|
||||||
"databases",
|
"databases",
|
||||||
"templates",
|
|
||||||
"(examples)",
|
"(examples)",
|
||||||
"auto-deploy",
|
"auto-deploy",
|
||||||
"schedule-jobs",
|
"schedule-jobs",
|
||||||
|
|||||||
@@ -1,122 +0,0 @@
|
|||||||
---
|
|
||||||
title: Open Source Templates
|
|
||||||
description: Deploy open source templates with Dokploy
|
|
||||||
---
|
|
||||||
|
|
||||||
By default we include a set of templates, that you can use to spin up templates quickly. You can also create your own templates.
|
|
||||||
|
|
||||||
## Templates
|
|
||||||
|
|
||||||
The following templates are available (100):
|
|
||||||
|
|
||||||
- **Appwrite**: End-to-end backend server for Web, Mobile, Native, or Backend apps with user authentication, database, storage, and more.
|
|
||||||
- **Outline**: Self-hosted knowledge base and documentation platform.
|
|
||||||
- **Supabase**: The open-source Firebase alternative with a dedicated Postgres database for web, mobile, and AI applications.
|
|
||||||
- **Pocketbase**: Open-source backend for your next SaaS and Mobile app in 1 file.
|
|
||||||
- **Plausible**: Open-source, privacy-focused, self-hosted web analytics platform.
|
|
||||||
- **Calcom**: Open-source alternative to Calendly for creating scheduling and booking services.
|
|
||||||
- **Grafana**: Open-source platform for data visualization and monitoring.
|
|
||||||
- **Directus**: API-first, open-source headless CMS for building custom backends.
|
|
||||||
- **Baserow**: Open-source database management tool.
|
|
||||||
- **Budibase**: Open-source low-code platform for building forms, portals, and approval apps.
|
|
||||||
- **Ghost**: Professional publishing platform built on Node.js.
|
|
||||||
- **Uptime Kuma**: Free and open-source monitoring tool.
|
|
||||||
- **n8n**: Open-source low-code platform for automating workflows.
|
|
||||||
- **Wordpress**: Free and open-source CMS for publishing websites.
|
|
||||||
- **Odoo**: Free and open-source business management software.
|
|
||||||
- **Appsmith**: Open-source platform for building internal tools.
|
|
||||||
- **Excalidraw**: Open-source online diagramming tool.
|
|
||||||
- **Documenso**: Open-source alternative to DocuSign.
|
|
||||||
- **NocoDB**: Airtable alternative for databases.
|
|
||||||
- **Meilisearch**: Free and open-source search engine.
|
|
||||||
- **Phpmyadmin**: Web interface for MySQL/MariaDB management.
|
|
||||||
- **Rocketchat**: Open-source web chat platform.
|
|
||||||
- **Minio**: Open-source object storage server.
|
|
||||||
- **Metabase**: Open-source business intelligence tool.
|
|
||||||
- **Glitchtip**: Simple, open-source error tracking.
|
|
||||||
- **Open WebUI**: Open-source ChatGPT alternative.
|
|
||||||
- **Listmonk**: Self-hosted newsletter manager.
|
|
||||||
- **Double Zero**: Self-hostable SES dashboard.
|
|
||||||
- **Umami**: Privacy-focused analytics alternative.
|
|
||||||
- **Jellyfin**: Free software media system.
|
|
||||||
- **Teable**: No-code database with spreadsheet interface.
|
|
||||||
- **Zipline**: ShareX/file upload server.
|
|
||||||
- **Soketi**: Open-source WebSockets server.
|
|
||||||
- **Aptabase**: Self-hosted analytics platform.
|
|
||||||
- **Typebot**: Open-source chatbot builder.
|
|
||||||
- **Gitea**: Self-hosted software development service.
|
|
||||||
- **Roundcube**: Open-source webmail software.
|
|
||||||
- **File Browser**: Web-based file manager.
|
|
||||||
- **Tolgee**: Web-based localization platform.
|
|
||||||
- **Portainer**: Container management tool.
|
|
||||||
- **InfluxDB**: Time-series data platform.
|
|
||||||
- **Infisical**: Configuration and secrets manager.
|
|
||||||
- **Docmost**: Collaborative wiki software.
|
|
||||||
- **Vaultwarden**: Bitwarden-compatible server.
|
|
||||||
- **Hi.events**: Event management platform.
|
|
||||||
- **Windows/MacOS**: Dockerized operating systems.
|
|
||||||
- **Coder**: Cloud development environment.
|
|
||||||
- **Stirling PDF**: PDF tools suite.
|
|
||||||
- **Lobe Chat**: Modern AI chat framework.
|
|
||||||
- **Peppermint**: API development platform.
|
|
||||||
- **Windmill**: Workflow and internal apps platform.
|
|
||||||
- **Activepieces**: No-code automation tool.
|
|
||||||
- **InvoiceShelf**: Self-hosted invoicing system.
|
|
||||||
- **Postiz**: Content management platform.
|
|
||||||
- **Slash**: Bookmarking and link shortener.
|
|
||||||
- **Discord Tickets**: Support ticket bot.
|
|
||||||
- **Nextcloud AIO**: File storage and collaboration.
|
|
||||||
- **Blender**: 3D creation suite.
|
|
||||||
- **HeyForm**: Conversational form builder.
|
|
||||||
- **Chatwoot**: Customer engagement platform.
|
|
||||||
- **Discourse**: Modern forum software.
|
|
||||||
- **Immich**: Photo/video backup solution.
|
|
||||||
- **Twenty CRM**: Modern CRM alternative.
|
|
||||||
- **YOURLS**: URL shortening service.
|
|
||||||
- **Ryot**: Media tracking platform.
|
|
||||||
- **PhotoPrism**: AI-powered photos app.
|
|
||||||
- **Ontime**: Event rundown manager.
|
|
||||||
- **Trigger.dev**: Event-driven application platform.
|
|
||||||
- **Browserless**: Headless browser automation.
|
|
||||||
- **draw.io**: Diagramming application.
|
|
||||||
- **Kimai**: Time-tracking application.
|
|
||||||
- **Logto**: Identity management platform.
|
|
||||||
- **Penpot**: Open-source design tool.
|
|
||||||
- **Huly**: Project management platform.
|
|
||||||
- **Unsend**: Email service platform.
|
|
||||||
- **Langflow**: Low-code AI application builder.
|
|
||||||
- **Elasticsearch**: Search and analytics engine.
|
|
||||||
- **OneDev**: Git server with CI/CD.
|
|
||||||
- **Unifi Network**: Network management platform.
|
|
||||||
- **GLPI**: Service management software.
|
|
||||||
- **Checkmate**: Server monitoring tool.
|
|
||||||
- **Gotenberg**: PDF generation API.
|
|
||||||
- **Actual Budget**: Privacy-focused finance app.
|
|
||||||
- **Conduit/Conduwuit**: Matrix chat servers.
|
|
||||||
- **Cloudflared**: Cloudflare Tunnel daemon.
|
|
||||||
- **CouchDB**: Document-oriented database.
|
|
||||||
- **IT Tools**: Developer utilities collection.
|
|
||||||
- **Superset**: Data visualization platform.
|
|
||||||
- **Glance/Homarr**: Dashboard solutions.
|
|
||||||
- **ERPNext**: Open-source ERP software.
|
|
||||||
- **Maybe**: Finance tracking application.
|
|
||||||
- **Spacedrive**: Cross-platform file manager.
|
|
||||||
- **AList**: Multi-storage file manager.
|
|
||||||
- **Answer**: Q&A platform.
|
|
||||||
- **Shlink**: URL shortener.
|
|
||||||
- **Frappe HR**: HR & Payroll software.
|
|
||||||
- **Formbricks**: Survey platform.
|
|
||||||
- **Trilium**: Note-taking application.
|
|
||||||
- **Convex**: Reactive database platform.
|
|
||||||
|
|
||||||
For an up to date list of available template you can visit [Dokploy templates website](https://templates.dokploy.com/).
|
|
||||||
|
|
||||||
## Create your own template
|
|
||||||
|
|
||||||
We accept contributions to upload new templates to the dokploy repository.
|
|
||||||
|
|
||||||
Make sure to follow the guidelines for creating a template:
|
|
||||||
|
|
||||||
[Steps to create your own template](https://github.com/Dokploy/templates)
|
|
||||||
|
|
||||||
[^1]: Please note that if you're self-hosting a mail server you need port 25 to be open for SMTP (Mail Transmission Protocol that allows you to send and receive) to work properly. Some VPS providers like [Hetzner](https://docs.hetzner.com/cloud/servers/faq/#why-can-i-not-send-any-mails-from-my-server) block this port by default for new clients.
|
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"pages": ["core", "cli", "api"]
|
"pages": ["core", "cli", "api", "templates"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { APIPage } from "@/lib/source";
|
import { APIPage } from "@/lib/source";
|
||||||
import { Callout } from "fumadocs-ui/components/callout";
|
import { Callout } from "fumadocs-ui/components/callout";
|
||||||
import { ImageZoom } from "fumadocs-ui/components/image-zoom";
|
import { ImageZoom } from "fumadocs-ui/components/image-zoom";
|
||||||
|
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
|
||||||
import defaultMdxComponents from "fumadocs-ui/mdx";
|
import defaultMdxComponents from "fumadocs-ui/mdx";
|
||||||
import type { MDXComponents } from "mdx/types";
|
import type { MDXComponents } from "mdx/types";
|
||||||
|
|
||||||
@@ -9,6 +10,8 @@ export function getMDXComponents(components?: MDXComponents): MDXComponents {
|
|||||||
...defaultMdxComponents,
|
...defaultMdxComponents,
|
||||||
ImageZoom,
|
ImageZoom,
|
||||||
Callout,
|
Callout,
|
||||||
|
Tab,
|
||||||
|
Tabs,
|
||||||
APIPage,
|
APIPage,
|
||||||
...components,
|
...components,
|
||||||
p: ({ children }) => (
|
p: ({ children }) => (
|
||||||
|
|||||||
@@ -5,6 +5,14 @@ const withMDX = createMDX();
|
|||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const config = {
|
const config = {
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
|
images: {
|
||||||
|
remotePatterns: [
|
||||||
|
{
|
||||||
|
protocol: "https",
|
||||||
|
hostname: "templates.dokploy.com",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withMDX(config);
|
export default withMDX(config);
|
||||||
|
|||||||
@@ -9,7 +9,8 @@
|
|||||||
"types:check": "fumadocs-mdx && tsc --noEmit",
|
"types:check": "fumadocs-mdx && tsc --noEmit",
|
||||||
"postinstall": "fumadocs-mdx",
|
"postinstall": "fumadocs-mdx",
|
||||||
"fix-openapi": "node scripts/fix-openapi.mjs",
|
"fix-openapi": "node scripts/fix-openapi.mjs",
|
||||||
"build:docs": "npm run fix-openapi && node generate-docs.mjs"
|
"generate-templates": "node scripts/generate-templates.mjs",
|
||||||
|
"build:docs": "npm run fix-openapi && npm run generate-templates && node generate-docs.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@next/third-parties": "16.0.7",
|
"@next/third-parties": "16.0.7",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
193
apps/docs/scripts/generate-templates.mjs
Normal file
193
apps/docs/scripts/generate-templates.mjs
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
import fs from 'node:fs';
|
||||||
|
import path from 'node:path';
|
||||||
|
|
||||||
|
const TEMPLATES_URL = 'https://templates.dokploy.com/meta.json';
|
||||||
|
const BASE_BLUEPRINT_URL = 'https://templates.dokploy.com/blueprints';
|
||||||
|
const OUTPUT_DIR = './content/docs/templates';
|
||||||
|
|
||||||
|
async function fetchWithTimeout(url, options = {}, timeout = 10000) {
|
||||||
|
const controller = new AbortController();
|
||||||
|
const id = setTimeout(() => controller.abort(), timeout);
|
||||||
|
try {
|
||||||
|
const response = await fetch(url, {
|
||||||
|
...options,
|
||||||
|
signal: controller.signal
|
||||||
|
});
|
||||||
|
clearTimeout(id);
|
||||||
|
return response;
|
||||||
|
} catch (e) {
|
||||||
|
clearTimeout(id);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getTemplateFile(id, fileName) {
|
||||||
|
try {
|
||||||
|
const response = await fetchWithTimeout(`${BASE_BLUEPRINT_URL}/${id}/${fileName}`);
|
||||||
|
if (!response.ok) return null;
|
||||||
|
return await response.text();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error fetching ${fileName} for ${id}:`, error.message);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Normalize and indent code so it renders correctly inside MDX code blocks (preserves YAML/TOML formatting). */
|
||||||
|
function formatCodeForMdx(code) {
|
||||||
|
if (!code || !code.trim()) return '# Not available';
|
||||||
|
return code
|
||||||
|
.replace(/\r\n/g, '\n')
|
||||||
|
.trim()
|
||||||
|
.split('\n')
|
||||||
|
.map((line) => line.trimEnd())
|
||||||
|
.join('\n')
|
||||||
|
.split('\n')
|
||||||
|
.map(line => ` ${line}`)
|
||||||
|
.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Build Base64 payload for Dokploy import (same format as UI: compose + config as JSON, then base64). */
|
||||||
|
function templateToBase64(dockerCompose, config) {
|
||||||
|
const configObj = {
|
||||||
|
compose: dockerCompose || '',
|
||||||
|
config: config || '',
|
||||||
|
};
|
||||||
|
const jsonString = JSON.stringify(configObj, null, 2);
|
||||||
|
return Buffer.from(jsonString, 'utf-8').toString('base64');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateTemplates() {
|
||||||
|
try {
|
||||||
|
console.log('Fetching templates metadata...');
|
||||||
|
const response = await fetch(TEMPLATES_URL);
|
||||||
|
const templates = await response.json();
|
||||||
|
|
||||||
|
console.log(`Found ${templates.length} templates. Starting data collection...`);
|
||||||
|
|
||||||
|
if (!fs.existsSync(OUTPUT_DIR)) {
|
||||||
|
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const batchSize = 10;
|
||||||
|
for (let i = 0; i < templates.length; i += batchSize) {
|
||||||
|
const batch = templates.slice(i, i + batchSize);
|
||||||
|
console.log(`Processing batch ${i / batchSize + 1}/${Math.ceil(templates.length / batchSize)}...`);
|
||||||
|
|
||||||
|
await Promise.all(batch.map(async (template) => {
|
||||||
|
const composeYaml = await getTemplateFile(template.id, 'docker-compose.yml');
|
||||||
|
const templateToml = await getTemplateFile(template.id, 'template.toml');
|
||||||
|
const instructionsRaw = await getTemplateFile(template.id, 'instructions.md');
|
||||||
|
const hasRealInstructions =
|
||||||
|
instructionsRaw &&
|
||||||
|
instructionsRaw.trim().length > 0 &&
|
||||||
|
!/^\s*<!doctype/i.test(instructionsRaw.trim()) &&
|
||||||
|
!/^\s*<html\b/i.test(instructionsRaw.trim());
|
||||||
|
const instructionsSafe = hasRealInstructions
|
||||||
|
? instructionsRaw.trim().replace(/\$\{/g, '\\${')
|
||||||
|
: '';
|
||||||
|
const safeDescription = template.description.replace(/"/g, '\\"');
|
||||||
|
const safeName = template.name.replace(/"/g, '\\"');
|
||||||
|
const logoUrl = `${BASE_BLUEPRINT_URL}/${template.id}/${template.logo}`;
|
||||||
|
|
||||||
|
const mdxContent = `---
|
||||||
|
title: "${safeName}"
|
||||||
|
description: "${safeDescription}"
|
||||||
|
---
|
||||||
|
|
||||||
|
<ImageZoom
|
||||||
|
src="${logoUrl}"
|
||||||
|
alt="${template.name} logo"
|
||||||
|
width={100}
|
||||||
|
height={100}
|
||||||
|
className="my-8 rounded-xl"
|
||||||
|
/>
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
<Tabs items={["docker-compose.yml", "template.toml"]}>
|
||||||
|
<Tab value="docker-compose.yml">
|
||||||
|
\`\`\`yaml
|
||||||
|
${formatCodeForMdx(composeYaml)}
|
||||||
|
\`\`\`
|
||||||
|
</Tab>
|
||||||
|
<Tab value="template.toml">
|
||||||
|
\`\`\`toml
|
||||||
|
${formatCodeForMdx(templateToml)}
|
||||||
|
\`\`\`
|
||||||
|
</Tab>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
## Base64
|
||||||
|
|
||||||
|
To import this template in Dokploy: create a **Compose** service → **Advanced** → **Base64 import** and paste the content below:
|
||||||
|
|
||||||
|
\`\`\`text
|
||||||
|
${templateToBase64(composeYaml, templateToml)}
|
||||||
|
\`\`\`
|
||||||
|
${instructionsSafe ? `
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
${instructionsSafe}
|
||||||
|
` : ''}
|
||||||
|
|
||||||
|
## Links
|
||||||
|
${template.links.website ? `- [Website](${template.links.website})` : ''}
|
||||||
|
${template.links.github ? `- [Github](${template.links.github})` : ''}
|
||||||
|
${template.links.docs ? `- [Documentation](${template.links.docs})` : ''}
|
||||||
|
|
||||||
|
## Tags
|
||||||
|
${template.tags.map(tag => `\`${tag}\``).join(', ')}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Version: \`${template.version}\`
|
||||||
|
`;
|
||||||
|
fs.writeFileSync(path.join(OUTPUT_DIR, `${template.id}.mdx`), mdxContent);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate index.mdx
|
||||||
|
const indexContent = `---
|
||||||
|
title: Introduction
|
||||||
|
description: Browse our collection of ${templates.length}+ self-hosted open source templates
|
||||||
|
---
|
||||||
|
|
||||||
|
# Templates
|
||||||
|
|
||||||
|
Welcome to the Dokploy Templates collection. We currently have **${templates.length}+** pre-configured templates that you can deploy with a single click.
|
||||||
|
|
||||||
|
Our templates cover a wide range of categories, including:
|
||||||
|
- **Databases**: PostgreSQL, MySQL, MongoDB, Redis, and more.
|
||||||
|
- **CMS**: WordPress, Ghost, Straple, Directus.
|
||||||
|
- **Analytics**: Umami, Plausible, Ackee.
|
||||||
|
- **Development Tools**: Gitea, Jenkins, Woodpecker CI.
|
||||||
|
- **And much more!**
|
||||||
|
|
||||||
|
Explore the sidebar to find the template you need.
|
||||||
|
|
||||||
|
`;
|
||||||
|
fs.writeFileSync(path.join(OUTPUT_DIR, 'index.mdx'), indexContent);
|
||||||
|
|
||||||
|
// Update meta.json with all template IDs
|
||||||
|
const metaContent = {
|
||||||
|
title: "Templates",
|
||||||
|
description: `Browse our collection of ${templates.length}+ self-hosted open source templates`,
|
||||||
|
icon: "LayoutGrid",
|
||||||
|
root: true,
|
||||||
|
pages: [
|
||||||
|
"index",
|
||||||
|
"---Templates---",
|
||||||
|
...templates.map(t => t.id)
|
||||||
|
]
|
||||||
|
};
|
||||||
|
fs.writeFileSync(path.join(OUTPUT_DIR, 'meta.json'), JSON.stringify(metaContent, null, 2));
|
||||||
|
|
||||||
|
console.log('✓ Successfully generated template documentation');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error generating templates:', error);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generateTemplates();
|
||||||
Reference in New Issue
Block a user