diff --git a/.a2a/agent.dsl.json b/.a2a/agent.dsl.json index d234a6d..c215ef4 100644 --- a/.a2a/agent.dsl.json +++ b/.a2a/agent.dsl.json @@ -137,10 +137,12 @@ "version": "0.1.0", "entrypoint": "agent:Robertseares", "frontend": { - "type": "static-spa", + "type": "server-rendered", + "framework": "nextjs", "path": "frontend", "build": "npm run build", - "dist": "out", + "start": "node server.js", + "port": 3000, "mount": "/", "auth": "inherit" } diff --git a/a2a.yaml b/a2a.yaml index 051c2c0..ffed103 100644 --- a/a2a.yaml +++ b/a2a.yaml @@ -19,10 +19,11 @@ expose: # url: DATABASE_URL frontend: - type: static-spa + type: server-rendered + framework: nextjs path: frontend build: npm run build - dist: out + start: node server.js + port: 3000 mount: / auth: inherit - diff --git a/frontend/next.config.mjs b/frontend/next.config.mjs index 161470e..fafdb7a 100644 --- a/frontend/next.config.mjs +++ b/frontend/next.config.mjs @@ -1,6 +1,11 @@ +import { dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + const nextConfig = { - output: "export", - trailingSlash: true, + output: "standalone", + outputFileTracingRoot: __dirname, }; export default nextConfig; diff --git a/frontend/package.json b/frontend/package.json index af83ad0..b169e3a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -4,8 +4,8 @@ "version": "0.1.0", "scripts": { "dev": "next dev --hostname 0.0.0.0 --port 3000", - "build": "next build", - "start": "next start" + "build": "next build && node prepare-standalone.mjs", + "start": "node start-standalone.mjs" }, "dependencies": { "next": "^15.3.0", diff --git a/frontend/prepare-standalone.mjs b/frontend/prepare-standalone.mjs new file mode 100644 index 0000000..12733ca --- /dev/null +++ b/frontend/prepare-standalone.mjs @@ -0,0 +1,48 @@ +import { cpSync, existsSync, mkdirSync, readdirSync } from "node:fs"; +import { join } from "node:path"; + +const standalone = ".next/standalone"; +const staticSource = ".next/static"; +const publicSource = "public"; + +function copyDir(source, target) { + if (!existsSync(source)) { + return; + } + mkdirSync(target, { recursive: true }); + cpSync(source, target, { recursive: true }); +} + +function serverDirs() { + if (!existsSync(standalone)) { + return []; + } + const dirs = []; + if (existsSync(join(standalone, "server.js"))) { + dirs.push(standalone); + } + for (const entry of readdirSync(standalone, { withFileTypes: true })) { + if (!entry.isDirectory()) { + continue; + } + const candidate = join(standalone, entry.name); + if (existsSync(join(candidate, "server.js"))) { + dirs.push(candidate); + } + } + return dirs; +} + +for (const dir of serverDirs()) { + copyDir(staticSource, join(dir, ".next/static")); + copyDir(publicSource, join(dir, "public")); +} + +if (!existsSync(join(standalone, "server.js"))) { + const nested = serverDirs().find((dir) => dir !== standalone); + if (nested) { + cpSync(nested, standalone, { recursive: true }); + copyDir(staticSource, join(standalone, ".next/static")); + copyDir(publicSource, join(standalone, "public")); + } +} diff --git a/frontend/start-standalone.mjs b/frontend/start-standalone.mjs new file mode 100644 index 0000000..5d3d368 --- /dev/null +++ b/frontend/start-standalone.mjs @@ -0,0 +1,23 @@ +import { spawnSync } from "node:child_process"; +import { existsSync } from "node:fs"; + +const candidates = [ + ".next/standalone/server.js", + ".next/standalone/frontend/server.js", +]; +const server = candidates.find((path) => existsSync(path)); + +if (!server) { + throw new Error("Next standalone server.js not found; run npm run build first"); +} + +const result = spawnSync(process.execPath, [server], { + stdio: "inherit", + env: { + ...process.env, + HOSTNAME: process.env.HOSTNAME || "127.0.0.1", + PORT: process.env.PORT || "3000", + }, +}); + +process.exit(result.status ?? 1);