├── .env.example ├── vercel.json ├── public ├── favicon.ico ├── og-image.png ├── favicon-16x16.png ├── favicon-32x32.png ├── apple-touch-icon.png ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── robots.txt └── manifest.json ├── .gitignore ├── src ├── lib │ ├── utils.ts │ └── meta-tags.ts ├── components │ ├── ui │ │ ├── skeleton.tsx │ │ ├── label.tsx │ │ ├── textarea.tsx │ │ ├── collapsible.tsx │ │ ├── separator.tsx │ │ ├── input.tsx │ │ ├── checkbox.tsx │ │ ├── empty-state.tsx │ │ ├── toggle.tsx │ │ ├── progress.tsx │ │ ├── alert.tsx │ │ ├── tooltip.tsx │ │ ├── card.tsx │ │ ├── button.tsx │ │ ├── tabs.tsx │ │ ├── toast.tsx │ │ ├── form.tsx │ │ ├── dialog.tsx │ │ ├── sheet.tsx │ │ └── select.tsx │ ├── Footer.tsx │ ├── ThemeProvider.tsx │ ├── MetaTags.tsx │ ├── templates │ │ └── TemplateCard.tsx │ ├── Header.tsx │ ├── ConversionDialog.tsx │ ├── CodeEditor.tsx │ ├── SidebarUI.tsx │ └── compose-builder │ │ ├── ServiceListSidebar.tsx │ │ ├── VolumeForm.tsx │ │ └── NetworkForm.tsx ├── reportWebVitals.ts ├── hooks │ ├── use-mobile.ts │ ├── use-search-params.ts │ ├── useEditorSize.ts │ ├── useSelectionState.ts │ ├── useYamlValidation.ts │ ├── useConversionDialog.ts │ ├── useVpnConfig.ts │ ├── useNetworkVolumeManager.ts │ └── useTemplateStore.ts ├── types │ ├── vpn.ts │ ├── vpn-configs.ts │ └── compose.ts ├── main.tsx ├── routes │ ├── __root.tsx │ └── $.tsx ├── utils │ ├── clipboard.ts │ ├── default-configs.ts │ ├── env-generator.ts │ ├── validation.ts │ ├── converters.ts │ ├── yaml-comments.ts │ └── vpn-generator.ts ├── routeTree.gen.ts └── styles.css ├── .cta.json ├── .dockerignore ├── nginx.conf ├── components.json ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ └── bug_report.yml └── workflows │ └── docker-build-push.yml ├── Dockerfile ├── vite.config.ts ├── tsconfig.json ├── docker-compose.yml ├── index.html └── package.json /.env.example: -------------------------------------------------------------------------------- 1 | VITE_ENV=prod 2 | VITE_SELF_HOSTED=true -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "rewrites": [{ "source": "/(.*)", "destination": "/" }] 3 | } 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhftechnology/Dock-Dploy/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/og-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhftechnology/Dock-Dploy/HEAD/public/og-image.png -------------------------------------------------------------------------------- /public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhftechnology/Dock-Dploy/HEAD/public/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhftechnology/Dock-Dploy/HEAD/public/favicon-32x32.png -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhftechnology/Dock-Dploy/HEAD/public/apple-touch-icon.png -------------------------------------------------------------------------------- /public/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhftechnology/Dock-Dploy/HEAD/public/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhftechnology/Dock-Dploy/HEAD/public/android-chrome-512x512.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | count.txt 7 | .env 8 | .nitro 9 | .tanstack 10 | /cloudflare/ 11 | /.wrangler/ 12 | /docker/docker-compose.yml 13 | -------------------------------------------------------------------------------- /src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from 'clsx' 2 | import { twMerge } from 'tailwind-merge' 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Allow: / 4 | 5 | # Disallow API and backend routes 6 | Disallow: /api/ 7 | Disallow: /backend/ 8 | Disallow: /src/ 9 | 10 | # Allow main pages 11 | Allow: / 12 | Allow: /docker/compose-builder -------------------------------------------------------------------------------- /.cta.json: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "Dock-Dploy", 3 | "mode": "file-router", 4 | "typescript": true, 5 | "tailwind": true, 6 | "packageManager": "npm", 7 | "git": true, 8 | "version": 1, 9 | "framework": "react-cra", 10 | "chosenAddOns": ["biome", "shadcn"] 11 | } 12 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | dist-ssr 4 | .DS_Store 5 | *.local 6 | .env 7 | .git 8 | .gitignore 9 | .github 10 | README.md 11 | .vscode 12 | .idea 13 | *.log 14 | npm-debug.log* 15 | yarn-debug.log* 16 | yarn-error.log* 17 | .tanstack 18 | count.txt 19 | .nitro 20 | /cloudflare/ 21 | /.wrangler/ 22 | /docker/docker-compose.yml 23 | 24 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 3000; 3 | server_name localhost; 4 | 5 | root /usr/share/nginx/html; 6 | index index.html; 7 | 8 | location / { 9 | try_files $uri $uri/ /index.html; 10 | } 11 | 12 | location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { 13 | expires 1y; 14 | add_header Cache-Control "public, immutable"; 15 | } 16 | } -------------------------------------------------------------------------------- /src/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import {cn} from "../../lib/utils" 2 | 3 | function Skeleton({className, ...props}: React.ComponentProps<"div">) { 4 | return ( 5 |
10 | ) 11 | } 12 | 13 | export {Skeleton} 14 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Dock-Dploy", 3 | "name": "Build Docker Compose Files", 4 | "icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}], 5 | "start_url": ".", 6 | "display": "standalone", 7 | "theme_color": "#000000", 8 | "background_color": "#ffffff" 9 | } 10 | -------------------------------------------------------------------------------- /src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | const reportWebVitals = (onPerfEntry?: () => void) => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({onCLS, onINP, onFCP, onLCP, onTTFB}) => { 4 | onCLS(onPerfEntry) 5 | onINP(onPerfEntry) 6 | onFCP(onPerfEntry) 7 | onLCP(onPerfEntry) 8 | onTTFB(onPerfEntry) 9 | }) 10 | } 11 | } 12 | 13 | export default reportWebVitals 14 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "", 8 | "css": "src/styles.css", 9 | "baseColor": "zinc", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: New Feature request 4 | url: https://github.com/hhftechnology/Dock-Dploy/discussions/new?category=request-feature 5 | about: For feature/script requests, please use the Discussions section. 6 | - name: 🤔 Questions and Help 7 | url: https://forum.hhf.technology/c/help/85 8 | about: For suggestions or questions, please use the Our forums. 9 | - name: Discord 10 | url: https://discord.gg/HDCt9MjyMJ 11 | about: Join our Discord server to chat with other users in the hhf community. -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Build stage 2 | FROM node:18-alpine AS builder 3 | 4 | WORKDIR /app 5 | 6 | # Copy package files 7 | COPY package*.json ./ 8 | 9 | # Install dependencies 10 | RUN npm ci 11 | 12 | # Copy source code 13 | COPY . . 14 | 15 | # Build the application 16 | RUN npm run build 17 | 18 | # Production stage 19 | FROM nginx:alpine 20 | 21 | # Copy nginx configuration 22 | COPY nginx.conf /etc/nginx/conf.d/default.conf 23 | 24 | # Copy built files from builder stage 25 | COPY --from=builder /app/dist /usr/share/nginx/html 26 | 27 | # Expose port 3000 28 | EXPOSE 3000 29 | 30 | # Start nginx 31 | CMD ["nginx", "-g", "daemon off;"] 32 | 33 | -------------------------------------------------------------------------------- /src/hooks/use-mobile.ts: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | const MOBILE_BREAKPOINT = 768 4 | 5 | export function useIsMobile() { 6 | const [isMobile, setIsMobile] = React.useState(undefined) 7 | 8 | React.useEffect(() => { 9 | const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) 10 | const onChange = () => { 11 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 12 | } 13 | mql.addEventListener("change", onChange) 14 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 15 | return () => mql.removeEventListener("change", onChange) 16 | }, []) 17 | 18 | return !!isMobile 19 | } 20 | -------------------------------------------------------------------------------- /src/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import * as LabelPrimitive from "@radix-ui/react-label" 3 | 4 | import { cn } from "../../lib/utils" 5 | 6 | function Label({ 7 | className, 8 | ...props 9 | }: React.ComponentProps) { 10 | return ( 11 | 19 | ) 20 | } 21 | 22 | export { Label } 23 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import viteReact from "@vitejs/plugin-react"; 3 | import { resolve } from "node:path"; 4 | import { fileURLToPath } from "node:url"; 5 | 6 | import { TanStackRouterVite } from "@tanstack/router-plugin/vite"; 7 | import tailwindcss from "@tailwindcss/vite"; 8 | 9 | // Fix __dirname for ESM 10 | const __filename = fileURLToPath(import.meta.url); 11 | const __dirname = resolve(__filename, ".."); 12 | 13 | export default defineConfig({ 14 | plugins: [ 15 | TanStackRouterVite({ autoCodeSplitting: true }), 16 | viteReact(), 17 | tailwindcss(), 18 | ], 19 | resolve: { 20 | alias: { 21 | "@": resolve(__dirname, "./src"), 22 | }, 23 | }, 24 | }); 25 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["**/*.ts", "**/*.tsx"], 3 | "compilerOptions": { 4 | "target": "ES2022", 5 | "jsx": "react-jsx", 6 | "module": "ESNext", 7 | "lib": ["ES2022", "DOM", "DOM.Iterable"], 8 | "types": ["vite/client"], 9 | 10 | /* Bundler mode */ 11 | "moduleResolution": "bundler", 12 | "allowImportingTsExtensions": true, 13 | "verbatimModuleSyntax": true, 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "skipLibCheck": true, 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true, 22 | "noUncheckedSideEffectImports": true, 23 | "baseUrl": ".", 24 | "paths": { 25 | "@/*": ["src/*"] 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "../../lib/utils" 4 | 5 | function Textarea({ className, ...props }: React.ComponentProps<"textarea">) { 6 | return ( 7 |