Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions v1/frontend/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ ACCOUNT_URL=
# in dev: postgresql://username:password@127.0.0.1:26257/devboxdb?connection_limit=50&pool_timeout=20
# in prod: postgresql://username:password@cockroachdb-global.cockroach-operator-system:26257/devboxdb?connection_limit=50&pool_timeout=20
DATABASE_URL=
# database provider for prisma runtime/migration routing
# values: cockroachdb (default) | postgresql
DATABASE_PROVIDER="cockroachdb"
# url for template retag
# in dev: http://127.0.0.1:8092
# in prod: http://devbox-service.devbox-system.svc.cluster.local:8092
Expand All @@ -64,6 +67,10 @@ GPU_ENABLE= "false"
ENABLE_IMPORT_FEATURE="false"
# enable web IDE feature, default is false
ENABLE_WEBIDE_FEATURE="false"
# IDE options in IDE button, comma-separated. Leave empty to show all.
# Available: vscode, webide, cursor, vscodeInsiders, windsurf, kiro, qoder, lingma, trae, traeCN, codebuddy, codebuddyCN, toolbox, gateway
# Note: webide also requires ENABLE_WEBIDE_FEATURE="true".
ENABLED_IDES=''
# advanced config features (each can be enabled independently)
# enable environment variables and configmap features, default is false
ENABLE_ADVANCED_ENV_AND_CONFIGMAP="false"
Expand Down
60 changes: 60 additions & 0 deletions v1/frontend/AGENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Devbox Provider Agent Notes

## Scope

This directory is the Devbox provider in the Sealos frontend workspace. It owns
the DevBox list, create/edit flow, detail page, template conversion UI, release
and deployment actions, and provider-side API routes under `app/api`.

## Working Rules

- Keep changes scoped to `frontend/providers/devbox` unless the task clearly
crosses a shared package boundary.
- Do not execute database writes or migrations unless the user explicitly asks.
- For production or test cloud images, build `linux/amd64` by default.
- For 70-cluster work, use `KUBECONFIG=/Users/mlhiter/.kube/70` and namespace
`devbox-frontend` unless the user gives a different target.
- The deployed image path uses the monorepo root `frontend/Dockerfile` with
`--build-arg name=devbox --build-arg path=providers/devbox`.
- The deployment has both `devbox-frontend-init` and `devbox-frontend`
containers. Inspect both image tags when verifying a rollout.
- Use the Codex in-app Browser for local browser verification.

## Verification

```bash
pnpm ts-lint
git diff --check
```

The package has no `test` script as of 2026-05-19, so generic test autodetection
that runs `npm test` will fail. Do not report that as a product regression; call
out the missing test script separately.

## Important Paths

- `app/[lang]/(platform)/(home)/page.tsx` - DevBox list entry.
- `app/[lang]/(platform)/devbox/create/page.tsx` - create/edit page shell.
- `app/[lang]/(platform)/devbox/create/components/Network.tsx` - network form,
public domain toggle, and custom domain drawer entry.
- `components/drawers/CustomAccessDrawer.tsx` - custom domain verification UX.
- `app/api/platform/authCname/route.ts` - CNAME verification endpoint.
- `app/api/platform/authDomainChallenge/route.ts` - fallback ownership
challenge verification endpoint.
- `utils/json2Yaml.ts` - form-to-Kubernetes manifest generation.
- `services/backend/kubernetes.ts` - Kubernetes client setup.
- `services/request.ts` - frontend request wrapper and auth headers.
- `services/db/init.ts` - Prisma client routing by `DATABASE_PROVIDER`.

## Custom Domain Notes

Custom domain verification first checks CNAME via `/api/platform/authCname`.
If that fails, it tries `/api/platform/authDomainChallenge`. A successful drawer
verification only updates the form field; the user still needs to click the
outer `update`/`变更` button to save the network configuration.

For issue `labring-sigs/sealos-issues#171`, the reported "click confirm and
nothing happens" path was caused by dynamic DNS errors such as
`queryCname ENOTFOUND <domain>` being treated as translation keys. Keep dynamic
DNS errors out of `next-intl` lookup paths; map known DNS codes to stable i18n
keys and show unknown messages as plain text.
36 changes: 36 additions & 0 deletions v1/frontend/DESIGN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Devbox Design Notes

Devbox is an operational product surface, not a marketing page. The interface
should be compact, predictable, and optimized for repeated configuration and
inspection.

## UI Principles

- Preserve the existing card and form structure when tuning layout. Prefer small
spacing and sizing improvements over broad redesigns.
- Keep status values in English unless the task explicitly asks for localization.
- Use concrete feedback for asynchronous actions. A button that validates or
mutates state must show loading, success, and failure states.
- Error copy should explain what the user can do next. Raw infrastructure
errors can appear only as fallback detail, not as the primary message.
- Keep dense configuration controls aligned and stable. Labels, buttons, and
dynamic text should not resize the surrounding network/resource form rows.
- Use `sonner` toasts for current provider UI feedback unless a component is
already bound to a different established local pattern.

## Custom Domain UX

The custom domain drawer is a validation step inside the larger DevBox edit
form. A successful validation does not persist the Kubernetes network change by
itself, so the success feedback must tell the user to save the outer form.

DNS failure messages should use product language:

- domain not found
- CNAME record missing
- CNAME target mismatch
- timeout
- network unreachable

Avoid exposing raw `queryCname ENOTFOUND` or `queryCname ENODATA` as the only
visible explanation.
15 changes: 9 additions & 6 deletions v1/frontend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,9 @@ WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json pnpm-lock.yaml* ./
COPY prisma ./prisma
RUN if [ -f pnpm-lock.yaml ]; then \
pnpm install; \
else \
echo "Lockfile not found."; \
exit 1; \
fi
RUN \
[ -f pnpm-lock.yaml ] && pnpm install || \
(echo "Lockfile not found." && exit 1)

# Rebuild the source code only when needed
FROM node:current-alpine AS builder
Expand All @@ -26,6 +23,8 @@ COPY --from=deps /app/prisma/generated ./prisma/generated
# Uncomment the following line in case you want to disable telemetry during the build.
ENV NEXT_TELEMETRY_DISABLED 1
ENV NEXT_PUBLIC_MOCK_USER ''
ARG DEVBOX_COMMIT_HASH=source-unavailable
ENV NEXT_PUBLIC_DEVBOX_COMMIT_HASH=${DEVBOX_COMMIT_HASH}

RUN npm install -g pnpm && pnpm run build

Expand Down Expand Up @@ -59,6 +58,10 @@ COPY --from=builder /app/package.json ./package.json
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
# Next standalone includes prisma schemas/clients but not migrations.
# Keep both providers' migrations for initContainer migrate deploy.
COPY --from=builder --chown=nextjs:nodejs /app/prisma/cockroach/migrations ./providers/devbox/prisma/cockroach/migrations
COPY --from=builder --chown=nextjs:nodejs /app/prisma/postgresql/migrations ./providers/devbox/prisma/postgresql/migrations

USER nextjs

Expand Down
26 changes: 5 additions & 21 deletions v1/frontend/Makefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
SERVICE_NAME ?= ghcr.io/sealos-apps/devbox-v1-frontend
SERVICE_NAME=sealos-devbox
# Image URL to use all building/pushing image targets
IMG ?= $(SERVICE_NAME):latest
PNPM ?= pnpm
PNPM_INSTALL_FLAGS ?= --frozen-lockfile
CONTAINER_TOOL ?= docker
DOCKERFILE ?= Dockerfile
DOCKER_BUILD_ARGS ?=
BUILDX_BUILDER ?= devbox-builder
PLATFORMS ?= linux/amd64,linux/arm64

SHELL = /usr/bin/env bash -o pipefail
.SHELLFLAGS = -ec
Expand Down Expand Up @@ -56,28 +51,17 @@ verify: ## Run the standard frontend verification pipeline.
##@ Build

.PHONY: build
build: ## Build frontend application.
build: ## Build desktop-frontend binary.
$(PNPM) run build

.PHONY: dev
dev: ## Run the frontend in development mode.
$(PNPM) run dev

.PHONY: run
run: ## Run the frontend in production mode.
run: ## Run a dev service from host.
$(PNPM) run start

.PHONY: docker-build
docker-build: ## Build docker image for the frontend.
$(CONTAINER_TOOL) build $(DOCKER_BUILD_ARGS) -t ${IMG} -f $(DOCKERFILE) .

.PHONY: docker-buildx
docker-buildx: ## Build and push docker image for the frontend for cross-platform support.
- $(CONTAINER_TOOL) buildx create --name $(BUILDX_BUILDER)
$(CONTAINER_TOOL) buildx use $(BUILDX_BUILDER)
- $(CONTAINER_TOOL) buildx build --push $(DOCKER_BUILD_ARGS) --platform=$(PLATFORMS) --tag ${IMG} -f $(DOCKERFILE) .
- $(CONTAINER_TOOL) buildx rm $(BUILDX_BUILDER)

.PHONY: docker-push
docker-push: ## Push docker image for the frontend.
$(CONTAINER_TOOL) push ${IMG}
docker-build: ## Build docker image with the desktop-frontend.
docker build -t sealos-devbox:latest . --network host --build-arg DEVBOX_COMMIT_HASH=$$(git rev-parse --short=12 HEAD) --build-arg HTTP_PROXY=http://127.0.0.1:7890 --build-arg HTTPS_PROXY=http://127.0.0.1:7890
36 changes: 36 additions & 0 deletions v1/frontend/PRODUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Devbox Product Context

Devbox gives Sealos users a browser-managed development environment that can be
created from runtime templates, configured with resources and network access,
opened in IDEs, released, and deployed as an application.

## Primary Users

- Developers who need an on-demand cloud development environment.
- Template maintainers who convert existing DevBoxes into reusable templates.
- Platform operators who configure feature flags, runtime catalogs, pricing,
ingress domains, storage defaults, IDE availability, and database provider
settings for a region.

## Core Jobs

- Create a DevBox from a runtime/template with CPU, memory, GPU, storage, and
network settings.
- Open the DevBox in configured IDEs such as VS Code, Cursor, Web IDE, or other
enabled options.
- Edit an existing DevBox without rebuilding the mental model from YAML.
- Expose ports through generated public domains or user custom domains.
- Release a DevBox version and deploy it as an app.
- Convert a configured DevBox into a reusable template while reviewing
environment variables and ConfigMap defaults.

## Product Boundaries

- This provider owns the frontend and provider API surface. It does not own the
DevBox controller, runtime image internals, account service, monitor service,
registry service, or desktop shell.
- Provider-side changes can generate Kubernetes resources and patch existing
resources, but runtime behavior inside the user container belongs to the
runtime/controller layer.
- Database schema and migration execution must be explicit because this repo
supports both CockroachDB and PostgreSQL Prisma schemas.
30 changes: 29 additions & 1 deletion v1/frontend/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
# Devbox Frontend Provider

Devbox is the Sealos frontend provider for creating, editing, releasing, and
operating DevBox development environments. It is a Next.js app inside the
Sealos frontend workspace.

## How to dev

1. First,you should refer to `frontend/README.md` ’s `How to dev` part.

2. Then you should config your env.
1. Create a new file `.env.local` in frontend/providers/kubepanel directory.

1. Create a new file `.env.local` in `frontend/providers/devbox`.

> `SEALOS_DOMAIN` is anyone website you use in sealos.

Expand All @@ -26,6 +33,7 @@
> Why you should have that?
>
> If you open your own dev in `localhost:3000` directly,you cannot have sealos desktop border,which maybe influence your style.

1. This url:[website](https://cloud.sealos.run/?openapp=system-template%3FtemplateName%3Done-step-shortcuts)

2. ![image-20240423111024336](https://raw.githubusercontent.com/mlhiter/typora-images/master/202404231110609.png)
Expand All @@ -35,3 +43,23 @@
4. Then you can get your own dev in this.

![image-20240423111123308](https://raw.githubusercontent.com/mlhiter/typora-images/master/202404231111720.png)

## Useful commands

```bash
pnpm dev
pnpm build
pnpm ts-lint
pnpm gen-client
```

This workspace does not currently define a `test` script. Use `pnpm ts-lint` as
the focused typecheck until a real test command is added.

## More docs

- `AGENT.md` - agent operating notes for this provider.
- `docs/architecture.md` - module boundaries and request flow.
- `docs/runbook.md` - local verification and 70-cluster deployment notes.
- `docs/ia.md` - main pages and API route surfaces.
- `prisma/README.md` - Prisma schema and migration layout.
21 changes: 21 additions & 0 deletions v1/frontend/ROADMAP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Devbox Roadmap Notes

This file tracks practical product/engineering gaps visible from the current
provider code. It is not a release commitment.

## Near Term

- Add regression coverage for custom-domain verification feedback so dynamic DNS
errors cannot be routed through i18n lookup again.
- Add a real package `test` script or document a project-level test command so
automated check scripts do not fail after typecheck.
- Keep template conversion defaults explicit and reviewable for environment
variables and ConfigMaps.

## Operational Gaps

- The current provider documentation is still lighter than the feature surface.
Keep `docs/architecture.md`, `docs/runbook.md`, and `docs/ia.md` updated as
future API or workflow changes land.
- ConfigMap single-file mounts use `subPath` for file shape. No-restart hot
updates require runtime/controller-level design, not only provider UI changes.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const Empty = () => {
onClick={handleCreateDevbox}
>
<Image width={900} height={328} alt={'list-empty'} src={'/images/list-empty.svg'} />
<div className="absolute top-1/2 left-1/2 flex w-[292px] -translate-x-1/2 translate-y-1/10 flex-col items-center gap-1">
<div className="absolute top-1/2 left-1/2 flex w-[292px] -translate-x-1/2 translate-y-[10%] flex-col items-center gap-1">
<div className="text-2xl/8 font-medium">{t('create_your_first_devbox')}</div>
<div className="text-center text-sm/6 text-zinc-500">
{t('click_here_to_create_devbox')}
Expand Down
Loading