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
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ jobs:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 10.5.1
version: 11.5.2
- uses: actions/setup-node@v4
with:
node-version: "18.x"
node-version: "22.13.0"
cache: "pnpm"
- name: Install dependencies
run: pnpm install && cd frontend && pnpm install
Expand All @@ -43,10 +43,10 @@ jobs:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 10.5.1
version: 11.5.2
- uses: actions/setup-node@v4
with:
node-version: "18.x"
node-version: "22.13.0"
cache: "pnpm"
- name: Install dependencies
run: pnpm install && cd frontend && pnpm install
Expand Down
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
# ============================================================================

# ---------- Stage 1: base ----------
FROM node:20-alpine AS base
FROM node:22.13-alpine AS base
RUN apk add --no-cache libc6-compat openssl
RUN corepack enable pnpm

# ---------- Stage 2: deps ----------
FROM base AS deps
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
RUN pnpm install --frozen-lockfile
COPY frontend/package.json frontend/pnpm-lock.yaml ./frontend/
COPY frontend/package.json frontend/pnpm-lock.yaml frontend/pnpm-workspace.yaml ./frontend/
RUN cd frontend && pnpm install --frozen-lockfile --ignore-scripts

# ---------- Stage 3: builder ----------
Expand Down
6 changes: 4 additions & 2 deletions README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@

### 요구사항

- **Node.js** 18+
- **pnpm** 8+
- **Node.js** 22.13+
- **pnpm** 10+ (프로젝트는 pnpm 11.5.2를 고정 사용)
- 실행 중인 **LangGraph 서버** (`langgraph dev`)

### 설치 및 실행
Expand All @@ -69,6 +69,8 @@ pnpm launch

`pnpm launch`를 실행하면 대화형 설정 마법사가 시작됩니다: 실행 모드, 인증 모드, LangGraph 서버 URL, LangSmith API 키, 데이터베이스 마이그레이션, 서버 자동 시작.

pnpm을 사용할 수 없거나 고정 버전이 적용되지 않으면 `corepack enable` 실행 후 다시 시도하세요.

> 인증 모드별 상세 설정은 `examples/` 폴더의 예제를 참고하세요.

### 인증 모드
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ A Next.js web app for interacting with [LangGraph](https://github.com/langchain-

### Prerequisites

- **Node.js** 18+
- **pnpm** 8+
- **Node.js** 22.13+
- **pnpm** 10+ (the project pins pnpm 11.5.2)
- A running **LangGraph server** (`langgraph dev`)

### Installation
Expand All @@ -69,6 +69,8 @@ pnpm launch

`pnpm launch` runs an interactive setup wizard: run mode, auth mode, LangGraph server URL, LangSmith API key, database migration, and auto-start.

If pnpm is unavailable or does not use the pinned version, run `corepack enable` and retry.

> See `examples/` for per-mode configuration examples.

### Auth Modes
Expand Down
4 changes: 3 additions & 1 deletion docs/QUICK_START.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ The fastest way to get LangGraph Chat UI running locally with no authentication.

## Prerequisites

- Node.js 18+, pnpm 8+
- Node.js 22.13+, pnpm 10+ (the project pins pnpm 11.5.2)
- A LangGraph server running (e.g. `langgraph dev`)

## Steps
Expand All @@ -16,6 +16,8 @@ pnpm install
pnpm launch # interactive setup — select "standalone" mode
```

If pnpm is unavailable or does not use the pinned version, run `corepack enable` and retry.

Or manually:

```bash
Expand Down
1 change: 0 additions & 1 deletion frontend/.npmrc

This file was deleted.

5 changes: 4 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,8 @@
"overrides": {
"react-is": "^19.0.0-rc-69d4b800-20241021"
},
"packageManager": "pnpm@10.5.1"
"packageManager": "pnpm@11.5.2",
"engines": {
"node": ">=22.13.0"
}
}
14 changes: 14 additions & 0 deletions frontend/pnpm-workspace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
confirmModulesPurge: false

hoistPattern:
- "**"

allowBuilds:
"@parcel/watcher": true
"@prisma/client": true
"@prisma/engines": true
"@swc/core": true
esbuild: true
prisma: true
sharp: true
unrs-resolver: true
4 changes: 2 additions & 2 deletions frontend/scripts/prisma-generate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ if (schema !== originalSchema) {

// Run prisma generate
try {
execSync("npx prisma generate", {
execSync("pnpm exec prisma generate", {
stdio: "inherit",
cwd: resolve(__dirname, ".."),
});
} catch (e) {
console.warn(
"[prisma-generate] Failed to generate Prisma client. " +
"This is OK if you are using AUTH_MODE=none (no database required). " +
"If you need authentication, check your network/SSL settings and run: npx prisma generate",
"If you need authentication, check your network/SSL settings and run: pnpm exec prisma generate",
);

// Create stub .prisma/client so the bundler can resolve the module.
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"description": "Chat UI for LangGraph agents with multiple authentication modes",
"scripts": {
"prelaunch": "pnpm install",
"launch": "npx tsx scripts/setup.ts",
"launch": "tsx scripts/setup.ts",
"dev": "cd frontend && pnpm dev",
"build": "cd frontend && pnpm build",
"start": "cd frontend && pnpm start",
Expand All @@ -20,8 +20,9 @@
"picocolors": "^1.0.0",
"tsx": "^4.0.0"
},
"packageManager": "pnpm@11.5.2",
"engines": {
"node": ">=18.0.0"
"node": ">=22.13.0"
},
"license": "Apache-2.0"
}
4 changes: 4 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
confirmModulesPurge: false

allowBuilds:
esbuild: true
30 changes: 23 additions & 7 deletions scripts/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1068,8 +1068,8 @@ async function runSetup(config: SetupConfig) {
if (needsDatabase) {
s.start(t("settingUpDb"));
try {
await runAsync("npx", ["prisma", "generate"], { cwd: FRONTEND_DIR });
await runAsync("npx", ["prisma", "db", "push", "--skip-generate"], { cwd: FRONTEND_DIR });
await runAsync("pnpm", ["exec", "prisma", "generate"], { cwd: FRONTEND_DIR });
await runAsync("pnpm", ["exec", "prisma", "db", "push", "--skip-generate"], { cwd: FRONTEND_DIR });
s.stop(t("dbReady"));
} catch (error) {
s.stop(LANG === "ko" ? "데이터베이스 설정 실패" : "Failed to setup database");
Expand Down Expand Up @@ -1162,10 +1162,10 @@ async function runDevelopment(config: SetupConfig) {

p.log.info(pc.dim(t("pressCtrlC")));

// Run dev server with minimal output
// Run dev server and surface its logs so startup failures are actionable.
const devProcess = crossSpawn("pnpm", ["dev"], {
cwd: FRONTEND_DIR,
stdio: ["ignore", "ignore", "ignore"],
stdio: ["ignore", "inherit", "inherit"],
env: { ...process.env, NODE_NO_WARNINGS: "1" },
});

Expand All @@ -1174,6 +1174,14 @@ async function runDevelopment(config: SetupConfig) {
process.exit(1);
});

devProcess.on("close", (code, signal) => {
if (signal) {
p.log.error(`Development server exited with signal ${signal}`);
process.exit(1);
}
process.exit(code ?? 1);
});

// Handle exit
process.on("SIGINT", () => {
devProcess.kill();
Expand Down Expand Up @@ -1359,7 +1367,7 @@ ${pc.cyan(`tail -f ${logFile}`)}`,

const startProcess = crossSpawn("pnpm", ["start"], {
cwd: FRONTEND_DIR,
stdio: ["ignore", "ignore", "ignore"],
stdio: ["ignore", "inherit", "inherit"],
env: { ...process.env, NODE_NO_WARNINGS: "1" },
});

Expand All @@ -1368,6 +1376,14 @@ ${pc.cyan(`tail -f ${logFile}`)}`,
process.exit(1);
});

startProcess.on("close", (code, signal) => {
if (signal) {
p.log.error(`Production server exited with signal ${signal}`);
process.exit(1);
}
process.exit(code ?? 1);
});

process.on("SIGINT", () => {
startProcess.kill();
p.outro(pc.green(LANG === "ko" ? "서버가 중지되었습니다." : "Server stopped."));
Expand Down Expand Up @@ -1520,14 +1536,14 @@ function getEnvVarsForProduction(config: SetupConfig): string {
}

function createDockerfile() {
const dockerfile = `FROM node:20-alpine AS base
const dockerfile = `FROM node:22.13-alpine AS base

# Install dependencies only when needed
FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app

COPY package.json pnpm-lock.yaml* ./
COPY package.json pnpm-lock.yaml* pnpm-workspace.yaml* ./
RUN corepack enable pnpm && pnpm i --frozen-lockfile

# Rebuild the source code only when needed
Expand Down
Loading