DEV Community

Cover image for Project using CopilotKit with Next.js implementing chatbot and AutoSuggestion.
Saurav Kumar Mahato
Saurav Kumar Mahato

Posted on

Project using CopilotKit with Next.js implementing chatbot and AutoSuggestion.

WingPilot: Effortless Data Management With Suggestion

  • Simplify your data management experience with WingPilot, a versatile tool designed to streamline interaction with employee datasets. WingPilot offers intuitive features for discussing insights, adding new employees, and removing outdated information, all through a user-friendly chat interface powered by Copilot Kit.

Features of this project

1. Efficient Employee Data Management: Simplify Your Data Handling

WingPilot streamlines the management of employee data, offering a user-friendly interface for effortless interaction. Whether it's adding, deleting, or discussing insights, WingPilot ensures a smooth experience, reducing complexity and enhancing productivity.

2. Smart Record Creation with Suggestions: Streamline Data Entry

WingPilot integrates intelligent suggestions into the record creation process, providing users with helpful prompts to populate employee records accurately. By leveraging smart suggestions, WingPilot minimizes manual effort and ensures data completeness and accuracy.

TechStack

  • Next JS
  • TypeScript
  • Material UI (Tailwind)
  • CopilotKit

Package manager used

yarn ( install if you don't have it )
Enter fullscreen mode Exit fullscreen mode

Install yarn using npm (global)

npm install --global yarn
Enter fullscreen mode Exit fullscreen mode

Different steps you have to follow are given below to make the project:

1. Setup next js project:

I have created a folder as WingPilot inside which I want my project. Navigate inside and type below:

yarn create next-app
Enter fullscreen mode Exit fullscreen mode

Follow the step and check the default options given like below:

Nextjs Project setup

Once run the project using below:

yarn run dev 
Enter fullscreen mode Exit fullscreen mode

2. Setup Material-Tailwind UI from its docs for Next js or follow below step:

yarn add @material-tailwind/react
Enter fullscreen mode Exit fullscreen mode

then, change tailwind.config.ts to below:

import withMT from "@material-tailwind/react/utils/withMT";

module.exports = withMT({
  content: [
    "./pages/**/*.{js,ts,jsx,tsx,mdx}",
    "./components/**/*.{js,ts,jsx,tsx,mdx}",
    "./app/**/*.{js,ts,jsx,tsx,mdx}",
  ],
  theme: {
    extend: {
      backgroundImage: {
        "gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
        "gradient-conic":
          "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
      },
    },
  },
  plugins: [],
});


Enter fullscreen mode Exit fullscreen mode

3. Now to setup project simply lets understand the hierarcy of the project and then copy the code provided for each component:

app directory might have been created. Now we are going to change and make it like below:

app
├── Home
   └── page.tsx
├── SideBar.tsx
├── Table
   ├── Form.tsx
   └── page.tsx
├── api
   └── copilotkit
       └── route.ts
├── components
   ├── Footer.tsx
   └── Layout.tsx
├── favicon.ico
├── globals.css
├── layout.tsx
└── page.tsx
Enter fullscreen mode Exit fullscreen mode

A. Home/page.tsx

"use client";

import React from "react";
import Layout from "../components/Layout";

const Home = () => {
  return (
    <Layout>
      <div className="">
        <h2 className="text-2xl text-center my-16">WingPilot</h2>
        <p className="px-28 font-sans text-lg  font-normal leading-relaxed text-inherit">
          Welcome to WingPilot, where seamless interaction with your employee
          dataset is made possible through our innovative Copilot Kit library.
          Managing and understanding your employee data has never been easier 
          whether it <i></i>s discussing insights, adding new employees, or removing
          outdated information, our intuitive chat interface powered by Copilot
          Kit streamlines the entire process. With the ability to engage in
          natural language conversations, you can effortlessly navigate through
          your dataset, gaining valuable insights and making informed decisions.
          Experience the convenience of data management like never before with
          WingPilot.
        </p>
      </div>
    </Layout>
  );
};

export default Home;

Enter fullscreen mode Exit fullscreen mode

Image description

B. SideBar.tsx

import {
  Card,
  Typography,
  List,
  ListItem,
  ListItemPrefix,
} from "@material-tailwind/react";
import { PresentationChartBarIcon } from "@heroicons/react/24/solid";

import Link from "next/link";

let Options: string[] = ["Home", "Table", "About", "Contact"];

export function DefaultSidebar() {
  return (
    <Card className="h-[calc(80vh-2rem)] w-half max-w-[20rem] p-4 shadow-xl shadow-blue-gray-900/5">
      <div className="mb-2 p-4">
        <Typography variant="h5" color="blue-gray">
          WingPilot
        </Typography>
      </div>
      <List>
        {Options.map((option) => (
          <Link href={option} key={option}>
            <ListItem>
              <ListItemPrefix>
                <PresentationChartBarIcon className="h-5 w-5" />
              </ListItemPrefix>
              {option}
            </ListItem>
          </Link>
        ))}
      </List>
    </Card>
  );
}

Enter fullscreen mode Exit fullscreen mode

Image description

C. Table/Form.tsx

"use client";

import { CopilotTextarea } from "@copilotkit/react-textarea";
import { CopilotKit } from "@copilotkit/react-core";

import React, { useState, ChangeEvent } from "react";
import {
  Button,
  Dialog,
  Card,
  CardBody,
  Typography,
  Input,
  CardFooter,
} from "@material-tailwind/react";

interface FormData {
  id: string; // Added 'id' field
  name: string;
  job: string;
  date: string;
  qualities: string; // Added 'qualities' field
}

interface Props {
  addEntry: (formData: FormData) => void;
}

const Form: React.FC<Props> = ({ addEntry }) => {
  const [open, setOpen] = useState(false);
  const [formData, setFormData] = useState<FormData>({
    id: "", // Initialized 'id' field
    name: "",
    job: "",
    date: "",
    qualities: "", // Initialized 'qualities' field
  });

  const handleOpen = () => setOpen((cur) => !cur);

  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    const { name, value } = e.target;
    setFormData({ ...formData, [name]: value });
  };

  const handleSubmit = () => {
    addEntry(formData);
    setFormData({
      id: "", // Reset 'id' field
      name: "",
      job: "",
      date: "",
      qualities: "", // Reset 'qualities' field
    });
    handleOpen();
  };

  return (
    <>
      <CopilotKit url="/api/copilotkit">
        {/* Global state & copilot logic. Put this around the entire app */}
        <Button onClick={handleOpen}>Add Entry</Button>
        <Dialog
          size="xs"
          open={open}
          handler={handleOpen}
          className="bg-transparent shadow-none"
        >
          <Card className="mx-auto w-full max-w-[24rem]">
            <CardBody className="flex flex-col gap-4">
              <Typography variant="h4" color="blue-gray">
                Add your entry
              </Typography>
              <Typography
                className="mb-3 font-normal"
                variant="paragraph"
                color="gray"
              >
                fill the information below
              </Typography>
              <Typography className="-mb-2" variant="h6">
                Name
              </Typography>
              <Input
                label="Name"
                size="lg"
                name="name"
                value={formData.name}
                onChange={handleChange}
              />
              <Typography className="-mb-2" variant="h6">
                Job
              </Typography>
              <Input
                label="Job"
                size="lg"
                name="job"
                value={formData.job}
                onChange={handleChange}
              />
              <Typography className="-mb-2" variant="h6">
                Date Joined
              </Typography>
              <Input
                label="Date"
                size="lg"
                name="date"
                value={formData.date}
                onChange={handleChange}
              />
              <Typography className="-mb-2" variant="h6">
                Qualities
              </Typography>
              <CopilotTextarea
                className="peer w-[42vh] h-[20vh] bg-transparent text-blue-gray-700 font-sans font-normal outline outline-0 focus:outline-0 disabled:bg-blue-gray-50 disabled:border-0 disabled:cursor-not-allowed transition-all placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 border focus:border-2 border-t-transparent focus:border-t-transparent placeholder:opacity-0 focus:placeholder:opacity-100 text-sm px-3 py-3 rounded-md border-blue-gray-200 focus:border-gray-900"
                label="Qualities"
                placeholder="Briefly describe qualities of the employee..."
                value={formData.qualities}
                onValueChange={(value: string) =>
                  setFormData({ ...formData, qualities: value })
                }
                autosuggestionsConfig={
                {
                  textareaPurpose:
                    "Suggest something similar and best about the employee based on the information provided.",
                  chatApiConfigs: {
                    suggestionsApiConfig: {
                      forwardedParams: {
                        max_tokens: 20,
                        stop: [".", "?", "!"],
                      },
                    },
                  },
                }
         }
              />
            </CardBody>
            <CardFooter className="pt-0">
              <Button variant="gradient" onClick={handleSubmit} fullWidth>
                Add
              </Button>
            </CardFooter>
          </Card>
        </Dialog>
      </CopilotKit>
    </>
  );
};

export default Form;

Enter fullscreen mode Exit fullscreen mode

Image description

D. Table/page.tsx

'use client'; 

import React, { useState } from "react";
import { Card, Typography } from "@material-tailwind/react";
import Layout from "../components/Layout";
import Form from "./Form";
import {
  useCopilotAction,
  useCopilotReadable,
} from "@copilotkit/react-core";

interface TableRow {
  id: string;
  name: string;
  job: string;
  date: string;
  qualities: string; // Added 'qualities' field
}

const TABLE_HEAD: string[] = ["Name", "Job", "Date Joined", "Qualities", ""];

const Table: React.FC = () => {
  const [tableRows, setTableRows] = useState<TableRow[]>([
    {
      id: "1",
      name: "John Michael",
      job: "Manager",
      date: "23/04/18",
      qualities: "honesty, Disciplied, Punctual", // Example qualities
    },
    // Other initial data...
  ]);

  // Implementing the useCopilotReadable to describe the user's employee list
  useCopilotReadable({
    description: "The user's employee list.",
    value: tableRows,
  });

  const deleteEmployee = (id: string) => {
    setTableRows((prevRows) => prevRows.filter((row) => row.id !== id));
  };

  // Implementing the useCopilotAction for deleting an employee from the list
  useCopilotAction({
    name: "deleteEmployee",
    description: "Delete an employee",
    parameters: [
      {
        name: "id",
        type: "string",
        description: "The id of the employee to delete.",
      },
    ],
    handler: ({ id }: { id: string }) => {
      deleteEmployee(id);
    },
    render: "Deleting an employee...",
  });

  const addEntry = (entry: TableRow) => {
    setTableRows([...tableRows, entry]);
  };

  // Implementing the useCopilotAction for updating the employee list
  useCopilotAction({
    name: "updateEmployeeList",
    description: "Update the employee list",
    parameters: [
      {
        name: "items",
        type: "object[]",
        description: "The new and updated employee list items.",
        attributes: [
          {
            name: "id",
            type: "string",
            description: "The id of the employee.",
          },
          {
            name: "name",
            type: "string",
            description: "The name of the employee.",
          },
          {
            name: "job",
            type: "string",
            description: "The job title of the employee.",
          },
          {
            name: "date",
            type: "string",
            description: "The date joined of the employee.",
          },
          {
            name: "qualities",
            type: "string",
            description: "The qualities of the employee.",
          },
        ],
      },
    ],
    handler: ({ items }: { items: TableRow[] }) => {
      setTableRows(items);
    },
    render: "Updating the employee list...",
  });

  return (
    <Layout>
      <Card className="h-full w-full overflow-scroll">
        <table className="w-full min-w-max table-auto text-left">
          <thead>
            <tr>
              {TABLE_HEAD.map((head) => (
                <th
                  key={head}
                  className="border-b border-blue-gray-100 bg-blue-gray-50 p-4"
                >
                  <Typography
                    variant="small"
                    color="blue-gray"
                    className="font-normal leading-none opacity-70"
                  >
                    {head}
                  </Typography>
                </th>
              ))}
            </tr>
          </thead>
          <tbody>
            {tableRows.map(({ id, name, job, date, qualities }, index) => {
              const isLast = index === tableRows.length - 1;
              const classes = isLast
                ? "p-4"
                : "p-4 border-b border-blue-gray-50";

              return (
                <tr key={id}>
                  <td className={classes}>
                    <Typography
                      variant="small"
                      color="blue-gray"
                      className="font-normal"
                    >
                      {name}
                    </Typography>
                  </td>
                  <td className={`${classes} bg-blue-gray-50/50`}>
                    <Typography
                      variant="small"
                      color="blue-gray"
                      className="font-normal"
                    >
                      {job}
                    </Typography>
                  </td>
                  <td className={classes}>
                    <Typography
                      variant="small"
                      color="blue-gray"
                      className="font-normal"
                    >
                      {date}
                    </Typography>
                  </td>
                  <td className={`${classes} bg-blue-gray-50/50`}>
                    <Typography
                      variant="small"
                      color="blue-gray"
                      className="font-normal"
                    >
                      {qualities}
                    </Typography>
                  </td>
                  <td className={`${classes} bg-blue-gray-50/50`}>
                    <Typography
                      as="a"
                      href="#"
                      variant="small"
                      color="blue-gray"
                      className="font-medium"
                      onClick={() => deleteEmployee(id)}
                    >
                      Delete
                    </Typography>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>

        <div className="mt-10">
          <Form addEntry={addEntry} />
        </div>
      </Card>
    </Layout>
  );
}

export default Table;

Enter fullscreen mode Exit fullscreen mode

Image description

E. (api/copilotkit/route.ts) Setup copilot backend

import { CopilotRuntime, OpenAIAdapter } from "@copilotkit/backend";

export async function POST(req: Request): Promise<Response> {
  const copilotKit = new CopilotRuntime({});

  return copilotKit.response(req, new OpenAIAdapter({ model: 'gpt-3.5-turbo' }));
}

Enter fullscreen mode Exit fullscreen mode

F. make a component directory inside app and then make components/Footer.tsx

import { Typography } from "@material-tailwind/react";

const LINKS = [
  {
    title: "Product",
    items: ["Table", "Home", "Solutions", "Tutorials"],
  },
  {
    title: "Company",
    items: ["About", "Contact", "Press", "News"],
  },
  {
    title: "Resource",
    items: ["Blog", "Newsletter", "Events", "Help center"],
  },
];

const currentYear = new Date().getFullYear();

export function Footer() {
  return (
    <footer className="relative w-full">
      <div className="mx-auto w-full max-w-7xl px-8">
        <div className="grid grid-cols-1 justify-between gap-4 md:grid-cols-2">
          <Typography variant="h5" className="mb-6">
            WingPilot
          </Typography>
          <div className="grid grid-cols-3 justify-between gap-4">
            {LINKS.map(({ title, items }) => (
              <ul key={title}>
                <Typography
                  variant="small"
                  color="blue-gray"
                  className="mb-3 font-medium opacity-40"
                >
                  {title}
                </Typography>
                {items.map((link) => (
                  <li key={link}>
                    <Typography
                      as="a"
                      href="#"
                      color="gray"
                      className="py-1.5 font-normal transition-colors hover:text-blue-gray-900"
                    >
                      {link}
                    </Typography>
                  </li>
                ))}
              </ul>
            ))}
          </div>
        </div>
        <div className="mt-12 flex w-full flex-col items-center justify-center border-t border-blue-gray-50 py-4 md:flex-row md:justify-between">
          <Typography
            variant="small"
            className="mb-4 text-center font-normal text-blue-gray-900 md:mb-0"
          >
            &copy; {currentYear} <a href="#">WingPilot</a>. All
            Rights Reserved.
          </Typography>
          <div className="flex gap-4 text-blue-gray-900 sm:justify-center">
            <Typography as="a" href="#" className="opacity-80 transition-opacity hover:opacity-100">
              <svg className="h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
                <path
                  fill-rule="evenodd"
                  d="M22 12c0-5.523-4.477-10-10-10S2 6.477 2 12c0 4.991 3.657 9.128 8.438 9.878v-6.987h-2.54V12h2.54V9.797c0-2.506 1.492-3.89 3.777-3.89 1.094 0 2.238.195 2.238.195v2.46h-1.26c-1.243 0-1.63.771-1.63 1.562V12h2.773l-.443 2.89h-2.33v6.988C18.343 21.128 22 16.991 22 12z"
                  clip-rule="evenodd"
                />
              </svg>
            </Typography>
            <Typography as="a" href="#" className="opacity-80 transition-opacity hover:opacity-100">
              <svg className="h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
                <path
                  fill-rule="evenodd"
                  d="M12.315 2c2.43 0 2.784.013 3.808.06 1.064.049 1.791.218 2.427.465a4.902 4.902 0 011.772 1.153 4.902 4.902 0 011.153 1.772c.247.636.416 1.363.465 2.427.048 1.067.06 1.407.06 4.123v.08c0 2.643-.012 2.987-.06 4.043-.049 1.064-.218 1.791-.465 2.427a4.902 4.902 0 01-1.153 1.772 4.902 4.902 0 01-1.772 1.153c-.636.247-1.363.416-2.427.465-1.067.048-1.407.06-4.123.06h-.08c-2.643 0-2.987-.012-4.043-.06-1.064-.049-1.791-.218-2.427-.465a4.902 4.902 0 01-1.772-1.153 4.902 4.902 0 01-1.153-1.772c-.247-.636-.416-1.363-.465-2.427-.047-1.024-.06-1.379-.06-3.808v-.63c0-2.43.013-2.784.06-3.808.049-1.064.218-1.791.465-2.427a4.902 4.902 0 011.153-1.772A4.902 4.902 0 015.45 2.525c.636-.247 1.363-.416 2.427-.465C8.901 2.013 9.256 2 11.685 2h.63zm-.081 1.802h-.468c-2.456 0-2.784.011-3.807.058-.975.045-1.504.207-1.857.344-.467.182-.8.398-1.15.748-.35.35-.566.683-.748 1.15-.137.353-.3.882-.344 1.857-.047 1.023-.058 1.351-.058 3.807v.468c0 2.456.011 2.784.058 3.807.045.975.207 1.504.344 1.857.182.466.399.8.748 1.15.35.35.683.566 1.15.748.353.137.882.3 1.857.344 1.054.048 1.37.058 4.041.058h.08c2.597 0 2.917-.01 3.96-.058.976-.045 1.505-.207 1.858-.344.466-.182.8-.398 1.15-.748.35-.35.566-.683.748-1.15.137-.353.3-.882.344-1.857.048-1.055.058-1.37.058-4.041v-.08c0-2.597-.01-2.917-.058-3.96-.045-.976-.207-1.505-.344-1.858a3.097 3.097 0 00-.748-1.15 3.098 3.098 0 00-1.15-.748c-.353-.137-.882-.3-1.857-.344-1.023-.047-1.351-.058-3.807-.058zM12 6.865a5.135 5.135 0 110 10.27 5.135 5.135 0 010-10.27zm0 1.802a3.333 3.333 0 100 6.666 3.333 3.333 0 000-6.666zm5.338-3.205a1.2 1.2 0 110 2.4 1.2 1.2 0 010-2.4z"
                  clip-rule="evenodd"
                />
              </svg>
            </Typography>
            <Typography as="a" href="#" className="opacity-80 transition-opacity hover:opacity-100">
              <svg className="h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
                <path d="M8.29 20.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0022 5.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.072 4.072 0 012.8 9.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 012 18.407a11.616 11.616 0 006.29 1.84" />
              </svg>
            </Typography>
            <Typography as="a" href="#" className="opacity-80 transition-opacity hover:opacity-100">
              <svg className="h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
                <path
                  fill-rule="evenodd"
                  d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"
                  clip-rule="evenodd"
                />
              </svg>
            </Typography>
            <Typography as="a" href="#" className="opacity-80 transition-opacity hover:opacity-100">
              <svg className="h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
                <path
                  fill-rule="evenodd"
                  d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10c5.51 0 10-4.48 10-10S17.51 2 12 2zm6.605 4.61a8.502 8.502 0 011.93 5.314c-.281-.054-3.101-.629-5.943-.271-.065-.141-.12-.293-.184-.445a25.416 25.416 0 00-.564-1.236c3.145-1.28 4.577-3.124 4.761-3.362zM12 3.475c2.17 0 4.154.813 5.662 2.148-.152.216-1.443 1.941-4.48 3.08-1.399-2.57-2.95-4.675-3.189-5A8.687 8.687 0 0112 3.475zm-3.633.803a53.896 53.896 0 013.167 4.935c-3.992 1.063-7.517 1.04-7.896 1.04a8.581 8.581 0 014.729-5.975zM3.453 12.01v-.26c.37.01 4.512.065 8.775-1.215.25.477.477.965.694 1.453-.109.033-.228.065-.336.098-4.404 1.42-6.747 5.303-6.942 5.629a8.522 8.522 0 01-2.19-5.705zM12 20.547a8.482 8.482 0 01-5.239-1.8c.152-.315 1.888-3.656 6.703-5.337.022-.01.033-.01.054-.022a35.318 35.318 0 011.823 6.475 8.4 8.4 0 01-3.341.684zm4.761-1.465c-.086-.52-.542-3.015-1.659-6.084 2.679-.423 5.022.271 5.314.369a8.468 8.468 0 01-3.655 5.715z"
                  clip-rule="evenodd"
                />
              </svg>
            </Typography>
          </div>
        </div>
      </div>
    </footer>
  );
}
Enter fullscreen mode Exit fullscreen mode

Image description

G. components/Layout.tsx

import React, { PropsWithChildren } from "react";
import { DefaultSidebar } from "../SideBar";
import { Footer } from "./Footer";

const Layout = ({ children }: PropsWithChildren) => {
  return (
    <>
      <div className="flex gap-4 my-4">
        <DefaultSidebar />
        {children}
      </div>
      <div className="m-20">
        <Footer />
      </div>
    </>
  );
};
export default Layout;

Enter fullscreen mode Exit fullscreen mode

H. Update global.css to below:

@tailwind base;
@tailwind components;
@tailwind utilities;

Enter fullscreen mode Exit fullscreen mode

I. layout.tsx


import type { Metadata } from "next";
import { Inter } from "next/font/google";

import { CopilotKit } from "@copilotkit/react-core";
import { CopilotSidebar } from "@copilotkit/react-ui";
import "@copilotkit/react-ui/styles.css";
import { CopilotPopup } from "@copilotkit/react-ui";

import "./globals.css";



const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body className={inter.className}>
      <CopilotKit url="/api/copilotkit">
      <CopilotSidebar instructions={
            "Help the user manage a employee list. If the user provides a high level info then  "  
            "break it down into different fields and add them to the employeelist"
          }
          defaultOpen={true}
          labels={ {
            title: "You Assistant WingPilot",
            initial: "Hi you! 👋 How can I help you ?",
          } }
          clickOutsideToClose={false}>
        {children}
      </CopilotSidebar>
    </CopilotKit>

        </body>
    </html>
  );
}

Enter fullscreen mode Exit fullscreen mode

J. page.tsx

"use client";

import { DefaultSidebar } from "./SideBar";

export default function Home() {
  return (
    <div className="my-4">
      <DefaultSidebar />
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

K. Add your OpenAI API key in environment variable

Add your environment variables to .env.local inside this directory WingPilot/wingpilot/.env.local

OPENAI_API_KEY=your-api-key
Enter fullscreen mode Exit fullscreen mode

Finally run the project in local host and navigate to

yarn run dev
Enter fullscreen mode Exit fullscreen mode
http://localhost:3000/
Enter fullscreen mode Exit fullscreen mode

Demo Video

Github of Project :

Detail of the project can be seen through below link in Github. Clone the project and follow the steps given in README.md in github to run the project.

https://github.com/SauravKumarMahato/WingPilot
Enter fullscreen mode Exit fullscreen mode

Conclusion

By following these steps, you can integrate Copilot Kit into your Next.js project, providing an intuitive chat interface for managing employee data. With Copilot Kit's powerful capabilities, navigating and interacting with your dataset becomes effortless, empowering you to make informed decisions effectively.

Top comments (1)

Collapse
 
fernandezbaptiste profile image
Bap

Really good breakdown of the uses with CopilotKit. Thanks for sharing! 💪