Frontend
Step 1. Install the Node Version Manager (NVM) if it's not already installed. Running this command will put the nvm binary in your home directory. So if you need or want to un-install it (to install a new version), just delete the .nvm folder in your home directory.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.5/install.sh | bash
Step 2. Copy, paste, and run the commands printed in the previous step.
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
Step 3. Use NVM to install the latest copy of Node.js (aka Node), the Node Package Manager (NPM), and Node Package Execute (NPX). If you're having any issues installing the latest version of Node, NPM, or NPX, verify you have the correct certificates installed locally.
nvm install node
Step 4. To confirm what version of Node is installed, enter the command below.
node --version
You should get output similar to below.
v26.3.0
Step 5. To confirm what version of NPM and NPX are installed, enter the command below.
npm --version
You should get output similar to below.
11.16.0
Step 6. Create a directory called frontend.
mkdir frontend
Step 7. Change your working directory to the directory you just created.
cd frontend
Step 8. Use NPX and the create-next-app tool to create a Next.js project called squidfall within the frontend directory. Next.js is a framework for building React-based apps. React is a JavaScript library for building user interfaces out of reusable components (i.e., JavaScript functions that return JavaScript XML, otherwise known as JSX).
npx create-next-app@latest squidfall
If you haven't installed the create-next-app tool before, npx will prompt you for permission before installing and then running it.
Need to install the following packages:
create-next-app@16.2.9
Ok to proceed? (y) y
When prompted, press enter to accept the settings create-next-app uses for Next.js projects by default.
? Would you like to use the recommended Next.js defaults? › - Use arrow-keys. Return to submit.
❯ Yes, use recommended defaults - TypeScript, ESLint, No React Compiler, Tailwind CSS, No src/ directory, App Router, AGENTS.md
No, reuse previous settings
No, customize settings
Step 9. Change your working directory to the Next.js project create-next-app just created for you.
cd squidfall
Step 10. Add the runtime and React components for Co-Pilot Kit to your Next.js project.
npm install @copilotkit/runtime @copilotkit/react-core @copilotkit/react-ui
Step 11. In the frontend/squidfall/ directory, create a api and copilotkit directory.
mkdir -p app/api/copilotkit
Step 12. In the frontend/squidfall/app/api/copilot/ directory path you just created, add a file called route.tsx and add the content below to it.
import {
CopilotRuntime,
ExperimentalEmptyAdapter,
copilotRuntimeNextJSAppRouterEndpoint,
} from "@copilotkit/runtime";
import { LangGraphHttpAgent } from "@copilotkit/runtime/langgraph";
import { NextRequest } from "next/server";
const serviceAdapter = new ExperimentalEmptyAdapter();
const runtime = new CopilotRuntime({
agents: {
squidfall: new LangGraphHttpAgent({
url: process.env.LANGGRAPH_DEPLOYMENT_URL || "http://localhost:8001/api/v1",
}),
}
});
export const POST = async (req: NextRequest) => {
const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({
runtime,
serviceAdapter,
endpoint: "/api/copilotkit",
});
return handleRequest(req);
};
Step 13. In the frontend/squidfall/app directory, open the file called layout.tsx and replace its content with the code below.
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import { CopilotKit } from "@copilotkit/react-core";
import "@copilotkit/react-ui/v2/styles.css";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "Squidfall",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html
lang="en"
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
>
<body className="min-h-full flex flex-col">
<CopilotKit runtimeUrl="/api/copilotkit" agent="squidfall">
{children}
</CopilotKit>
</body>
</html>
);
}
Step 14. In the frontend/squidfall/app directory, open the file called page.tsx and replace its content with the code below.
import { CopilotSidebar } from "@copilotkit/react-core/v2";
export default function Home() {
return (
<main>
<h1>Squidfall</h1>
<CopilotSidebar />
</main>
);
}
Step 15. In the frontend/squidfall directory, open the file called next.config.ts and replace its contents with the code below.
const nextConfig = {
output: "standalone",
};
export default nextConfig;
Step 16. In the frontend directory, create a file called .env and add the content below to it.
export LANGGRAPH_DEPLOYMENT_URL="http://squidfall-inference:8001/api/v1"
Step 17. In the frontend directory, create a file called Dockerfile and add the content below it. Feel free to modify the image.authors label.
FROM node:lts-alpine3.24 AS stage_1
ARG LANGGRAPH_DEPLOYMENT_URL
ENV LANGGRAPH_DEPLOYMENT_URL=${LANGGRAPH_DEPLOYMENT_URL}
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
WORKDIR /home/squidfall/
COPY squidfall/ .
RUN echo "[*] LANGGRAPH_DEPLOYMENT_URL has been set to '$LANGGRAPH_DEPLOYMENT_URL'" &&\
npm install && npm run build
FROM node:lts-alpine3.24
LABEL image.authors="Victor Fernandez III, @cyberphor"
WORKDIR /home/squidfall/
COPY --from=stage_1 /home/squidfall/.next/standalone/ .
COPY --from=stage_1 /home/squidfall/.next/static/ .next/static/
COPY --from=stage_1 /home/squidfall/public/ public/
ENV PORT=3000
EXPOSE 3000
USER node
CMD ["node", "server.js"]
Step 18. From the root of the repository, run the command below to build the container using the Dockerfile you just created.
make DOCKER_COMPOSE_PROFILE=frontend
Step 19. Run the command below to start the container you just created.
make DOCKER_COMPOSE_PROFILE=frontend start
Step 20. Run the command below to confirm the container has started.
make DOCKER_COMPOSE_PROFILE=frontend status
Step 21. If the container has started, open your browser to http://localhost interact with it.
Step 22. Run the command below to stop the container.
make DOCKER_COMPOSE_PROFILE=frontend stop