# yaml-language-server: $schema=https://schema.zeabur.app/template.json
apiVersion: zeabur.com/v1
kind: Template
metadata:
    name: ExcaliDash
spec:
    description: |
        A self-hosted dashboard and organizer for Excalidraw with live collaboration, persistent storage, and optional multi-user authentication.
    coverImage: https://raw.githubusercontent.com/ZimengXiong/ExcaliDash/main/readme-assets/dashboard.png
    icon: https://raw.githubusercontent.com/ZimengXiong/ExcaliDash/main/readme-assets/logoExcaliDash.png
    variables:
        - key: PUBLIC_DOMAIN
          type: DOMAIN
          name: Domain
          description: The domain to access your ExcaliDash instance.
    tags:
        - Tool
        - Collaboration
        - Drawing
        - Self-hosted
    readme: |
        # ExcaliDash

        A self-hosted dashboard and organizer for [Excalidraw](https://github.com/excalidraw/excalidraw) with live collaboration features.

        ## Features

        - **Persistent storage** for all your drawings
        - **Real-time collaboration** with live presence
        - **Multi-user authentication** with local login or OIDC (optional)
        - **Scoped sharing** — internal and external sharing controls
        - **Search** your drawings instantly
        - **Drag-and-drop** drawings into collections
        - **Export / import** in non-proprietary `.excalidraw` format

        ## Getting Started

        After deployment, open your domain in the browser. On first launch you will be guided through a one-time admin bootstrap flow. Check the backend service logs for the one-time setup code:

        ```
        [BOOTSTRAP SETUP] One-time admin setup code ...
        ```

        ## Auth Modes

        | `AUTH_MODE`       | Behaviour                                      |
        | ----------------- | ---------------------------------------------- |
        | `local` (default) | Native email/password login only               |
        | `hybrid`          | Native login plus OIDC                         |
        | `oidc_enforced`   | OIDC-only (local register / login disabled)    |

        ## Links

        - [GitHub](https://github.com/ZimengXiong/ExcaliDash)
        - [Release Notes](https://github.com/ZimengXiong/ExcaliDash/releases)
    services:
        - name: excalidash-backend
          icon: https://raw.githubusercontent.com/ZimengXiong/ExcaliDash/main/readme-assets/logoExcaliDash.png
          template: PREBUILT_V2
          spec:
            id: excalidash-backend
            source:
                image: zimengxiong/excalidash-backend:latest
            ports:
                - id: web
                  port: 8000
                  type: HTTP
            volumes:
                - id: data
                  dir: /app/prisma
            env:
                AUTH_MODE:
                    default: local
                BACKEND_HOST:
                    default: ${CONTAINER_HOSTNAME}
                    expose: true
                CSRF_SECRET:
                    default: ${PASSWORD}
                DATABASE_URL:
                    default: file:/app/prisma/dev.db
                ENFORCE_HTTPS_REDIRECT:
                    default: "false"
                FRONTEND_URL:
                    default: https://${PUBLIC_DOMAIN}.zeabur.app
                JWT_SECRET:
                    default: ${PASSWORD}
                NODE_ENV:
                    default: production
                PORT:
                    default: "8000"
                TRUST_PROXY:
                    default: "1"
        - name: excalidash-frontend
          icon: https://raw.githubusercontent.com/ZimengXiong/ExcaliDash/main/readme-assets/logoExcaliDash.png
          template: PREBUILT_V2
          spec:
            id: excalidash-frontend
            source:
                image: zimengxiong/excalidash-frontend:latest
            ports:
                - id: web
                  port: 80
                  type: HTTP
            configs:
                - path: /etc/nginx/nginx.conf.template
                  template: |
                    events {
                        worker_connections 1024;
                    }

                    http {
                        include /etc/nginx/mime.types;
                        default_type application/octet-stream;

                        map $http_x_forwarded_proto $forwarded_proto {
                            default $scheme;
                            ~*^https(?:,|$) https;
                            ~*^http(?:,|$) http;
                        }

                        sendfile on;
                        keepalive_timeout 65;
                        gzip on;
                        gzip_vary on;
                        gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

                        client_max_body_size 50M;

                        server {
                            listen 80;
                            server_name localhost;
                            root /usr/share/nginx/html;
                            index index.html;

                            add_header X-Frame-Options "DENY" always;
                            add_header X-Content-Type-Options "nosniff" always;
                            add_header Referrer-Policy "strict-origin-when-cross-origin" always;
                            add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
                            add_header Content-Security-Policy "default-src 'self'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; script-src 'self' https://unpkg.com https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com https://unpkg.com https://cdn.jsdelivr.net data:; img-src 'self' data: blob: https:; connect-src 'self' https: ws: wss:;" always;

                            location /api/ {
                                proxy_pass http://excalidash-backend:8000/;
                                proxy_http_version 1.1;
                                proxy_set_header Upgrade $http_upgrade;
                                proxy_set_header Connection 'upgrade';
                                proxy_set_header Host $host;
                                proxy_cache_bypass $http_upgrade;
                                proxy_set_header X-Real-IP $remote_addr;
                                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                                proxy_set_header X-Forwarded-Proto $forwarded_proto;
                                proxy_buffering on;
                                proxy_buffer_size 4k;
                                proxy_buffers 8 4k;
                                proxy_busy_buffers_size 8k;
                                client_body_buffer_size 128k;
                                proxy_connect_timeout 300s;
                                proxy_send_timeout 300s;
                                proxy_read_timeout 300s;
                            }

                            location /socket.io/ {
                                proxy_pass http://excalidash-backend:8000/socket.io/;
                                proxy_http_version 1.1;
                                proxy_set_header Upgrade $http_upgrade;
                                proxy_set_header Connection 'upgrade';
                                proxy_set_header Host $host;
                                proxy_cache_bypass $http_upgrade;
                                proxy_set_header X-Real-IP $remote_addr;
                                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                                proxy_set_header X-Forwarded-Proto $forwarded_proto;
                                proxy_read_timeout 3600s;
                                proxy_send_timeout 3600s;
                            }

                            location / {
                                try_files $uri $uri/ /index.html;
                            }

                            location = /index.html {
                                add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
                                expires -1;
                                try_files /index.html =404;
                            }

                            location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
                                expires 1y;
                                add_header Cache-Control "public, immutable";
                            }
                        }
                    }
                  permission: null
                  envsubst: null
          domainKey: PUBLIC_DOMAIN
localization:
    zh-CN:
        description: |
            自托管的 Excalidraw 仪表板与管理工具，支持实时协作、持久化存储，以及可选的多用户认证功能。
        variables:
            - key: PUBLIC_DOMAIN
              type: DOMAIN
              name: 域名
              description: 用于访问 ExcaliDash 的域名。
        readme: |
            # ExcaliDash

            一个自托管的 [Excalidraw](https://github.com/excalidraw/excalidraw) 仪表板与管理工具，支持实时协作功能。

            ## 功能特色

            - **持久化存储** — 所有绘图内容均可永久保存
            - **实时协作** — 支持多人同步编辑与实时在线状态
            - **多用户认证** — 支持本地账号登录或 OIDC（可选）
            - **范围化分享** — 控制内部与外部分享权限
            - **搜索** — 快速搜索你的绘图
            - **拖放排序** — 将绘图拖放至收藏集中管理
            - **导出/导入** — 使用非专有的 `.excalidraw` 格式备份数据

            ## 快速开始

            部署完成后，在浏览器打开你的域名，首次启动将引导你完成一次性管理员设置流程。请查看后端服务日志以获取设置码：

            ```
            [BOOTSTRAP SETUP] One-time admin setup code ...
            ```

            ## 认证模式

            | `AUTH_MODE`       | 行为                                 |
            | ----------------- | ------------------------------------ |
            | `local`（默认）   | 仅支持本地 Email/密码登录            |
            | `hybrid`          | 本地登录加上 OIDC                    |
            | `oidc_enforced`   | 仅 OIDC（禁用本地注册与登录）        |

            ## 相关链接

            - [GitHub](https://github.com/ZimengXiong/ExcaliDash)
            - [版本说明](https://github.com/ZimengXiong/ExcaliDash/releases)
    zh-TW:
        description: |
            自架的 Excalidraw 儀表板與管理工具，支援即時協作、持久化儲存，以及可選的多使用者驗證功能。
        variables:
            - key: PUBLIC_DOMAIN
              type: DOMAIN
              name: 網域
              description: 用於存取 ExcaliDash 的網域。
        readme: |
            # ExcaliDash

            一個自架的 [Excalidraw](https://github.com/excalidraw/excalidraw) 儀表板與管理工具，支援即時協作功能。

            ## 功能特色

            - **持久化儲存** — 所有繪圖內容皆可永久保存
            - **即時協作** — 支援多人同步編輯與即時在線狀態
            - **多使用者驗證** — 支援本地帳號登入或 OIDC（可選）
            - **範圍化分享** — 控制內部與外部分享權限
            - **搜尋** — 快速搜尋你的繪圖
            - **拖放排序** — 將繪圖拖放至收藏集中管理
            - **匯出/匯入** — 使用非專有的 `.excalidraw` 格式備份資料

            ## 開始使用

            部署完成後，在瀏覽器開啟你的網域，首次啟動將引導你完成一次性管理員設定流程。請查看後端服務日誌以取得設定碼：

            ```
            [BOOTSTRAP SETUP] One-time admin setup code ...
            ```

            ## 驗證模式

            | `AUTH_MODE`       | 行為                                 |
            | ----------------- | ------------------------------------ |
            | `local`（預設）   | 僅支援本地 Email/密碼登入            |
            | `hybrid`          | 本地登入加上 OIDC                    |
            | `oidc_enforced`   | 僅 OIDC（停用本地註冊與登入）        |

            ## 相關連結

            - [GitHub](https://github.com/ZimengXiong/ExcaliDash)
            - [版本說明](https://github.com/ZimengXiong/ExcaliDash/releases)
