Imported from ViewComfy/ViewComfy (
AGENTS.md). Install upstream withnpx skills add ViewComfy/ViewComfy. Copyright stays with the author.
AGENTS.md (ViewComfy)
This file is for agentic coding assistants operating in this repo. It summarizes how to build/lint/typecheck, how the project is structured, and the local code conventions/rules to follow.
Project overview
- Next.js App Router project (
app/) with React 19 + TypeScript (strict). - UI is largely shadcn/ui + Radix primitives (
components/ui/). - Shared helpers live in
lib/, app-specific logic inapp/. - Path alias: import from
@/*maps to repo root (seetsconfig.json). - OpenAPI-generated client in
src/generated/with Clerk authentication (see below).
Quick commands
Install
npm install
# or (CI-style)
npm ci
Dev
npm run dev
Note: dev runs next dev with Node inspector enabled.
Build / start
npm run build
npm run start
Lint
npm run lint
npm run lint-fix
Lint a single file
npx eslint "components/ui/button.tsx"
# fix only that file
npx eslint "components/ui/button.tsx" --fix
Typecheck (no emit)
There is no typecheck script yet; use tsc directly:
npx tsc -p tsconfig.json --noEmit
Tests
- There is currently no
testscript and no test runner dependency inpackage.json. - Treat
npm run lint+npx tsc -p tsconfig.json --noEmit+npm run buildas the local verification suite.
CI / Docker builds
GitHub Actions primarily build Docker images (see .github/workflows/*):
viewcomfy-nextjs-build.yml→Dockerfileviewcomfy-editor-modal-build.yml→ViewComfy-modal.dockerfileviewcomfy-playground-modal-build copy.yml→ViewComfy-modal.dockerfile
Local Docker (minimal):
docker build -t viewcomfy .
docker run -it --name viewcomfy-container -p 3000:3000 viewcomfy
Cursor rules in this repo (MUST FOLLOW)
Cursor rules are stored in .cursor/rules/ and marked alwaysApply: true.
If these conflict with your personal defaults, prefer the Cursor rules.
.cursor/rules/front-end-cursor-rules.mdc
Key requirements (interpret in a React/Next.js context):
- Fully implement requested functionality; no TODOs/placeholders.
- Prefer readable, DRY code with early returns.
- Accessibility: keyboard nav, ARIA labels/roles, focus states.
- Components: use
React.forwardReffor interactive UI; define props interfaces; use CVA variants; setdisplayName. - Styling: Tailwind + shadcn tokens/CSS vars; use
cn(); support dark mode via CSS variables. - Handlers: name event handlers with
handle*(e.g.,handleClick).
.cursor/rules/view-comfy-json-rules.mdc
These rules apply when editing view_comfy.json / “ViewComfy JSON” structures:
view_comfy.jsoncontainsworkflows[]entries with:viewComfyJSON(safe to edit; controls UI)workflowApiJSON(DO NOT EDIT)
- Never touch
workflowApiJSON; only modifyviewComfyJSON. - When moving/removing inputs, move/remove the entire object (not partial).
- For
valueType: "select",options[]is required (label/value pairs).
Code style (pragmatic, repo-aligned)
This repo contains a mix of formatting styles across files. Follow these rules:
- Avoid drive-by formatting changes; keep existing file style unless you are already making substantial edits in that file.
- Use ESLint to catch issues (
npm run lint) andnpm run lint-fixfor safe auto-fixes.
Imports
Preferred order (match common shadcn/ui patterns in components/ui/*):
- React imports (
import * as React from "react") when needed. - External libraries (Radix, zod, zustand, etc.).
- Internal absolute imports via alias (
@/lib/...,@/app/...). - Relative imports (
./...).
Guidelines:
- Use type-only imports where it improves clarity (
import type { X } ...). - Prefer
@/alias over deep relative paths.
Formatting
- Use Tailwind utility classes; prefer
cn()for conditional composition. - Prefer small, composable functions and early returns.
- Keep JSX readable: avoid deeply nested ternaries in render.
Types
- TypeScript is
strict: true(tsconfig.json). Don’t weaken types. - Prefer:
interfacefor object-shaped props and API shapes.typefor unions/literals (type Status = "a" | "b").
- This repo often prefixes interfaces with
I(e.g.,IComfyUIError). Keep consistency within the file/module you touch. - ESLint allows
any, but preferunknown+ narrowing in new code. @ts-ignoreis only allowed with a description (seeeslint.config.mjs).
Naming
- Components:
PascalCase(e.g.,WorkflowSidebar). - Hooks:
useSomething. - Booleans:
isLoading,hasError,canEdit. - Handlers:
handleClick,handleSubmit,handleKeyDown. - Files/folders: follow existing naming in the area you’re editing.
Error handling patterns
Prefer existing patterns instead of inventing new ones:
- API routes often return typed JSON errors via
ErrorResponseFactory(app/models/errors.ts) andNextResponse.json(...). - For workflow/Comfy errors, use
ComfyWorkflowErrorand/orComfyErrorHandler(app/helpers/comfy-error-handler.ts). - When catching
unknown, convert to a structured response rather than returning raw strings (except for simple endpoints liketext-proxy).
Next.js / App Router conventions
- Mark client components explicitly with
'use client'. - Keep server-only code in route handlers (
app/api/**/route.ts) and services that run server-side. - Be careful with environment variables:
NEXT_PUBLIC_*is safe for client bundles.- Non-
NEXT_PUBLIC_*should stay server-side.
OpenAPI Client & Authentication
The project uses an OpenAPI-generated TypeScript client in src/generated/.
How Authentication Works
Authentication is configured at runtime (not in generated files) so it survives regeneration:
-
src/generated/auth-config.ts(NOT generated, manually maintained)- Contains
initializeOpenAPIAuth()function - Sets up Clerk JWT authentication for all API calls
- Contains
-
Integration in
components/auth/authenticated-wrapper.tsx- Calls
useInitializeOpenAPIAuth()hook on mount - Automatically injects Bearer tokens into all OpenAPI service calls
- Calls
-
Usage - Simply use the generated services:
import { AppsService } from '@/src/generated'; // Automatically authenticated via OpenAPI.TOKEN resolver const data = await AppsService.listAppsApiAppsGet(projectId); -
With SWR - Use directly in hooks:
const { data, error, isLoading } = useSWR( projectId ? ["api-apps", projectId] : null, () => AppsService.listAppsApiAppsGet(projectId!), );
Regenerating OpenAPI Client
When regenerating (e.g., npx openapi-typescript-codegen ...):
✅ Keep these files (not regenerated):
src/generated/auth-config.tssrc/generated/README.md
✅ Safe to regenerate:
src/generated/core/src/generated/models/src/generated/services/src/generated/index.ts
After regeneration:
- Authentication continues to work automatically ✅
- No manual changes needed in generated files ✅
- See
src/generated/README.mdfor details
Before you open a PR
Run the closest available checks:
npm run lint && npx tsc -p tsconfig.json --noEmit && npm run build
Design Philosophy
This project targets designers and creatives - prioritize beautiful, tasteful UI.