AI Prompt setup on Nextjs.
Tags: ai, node, nextjs, javascript
Published: 2023-12-17 19:46:31

In this tutorial, we have setup our AI Prompt. Previously we did 3 parts. If you don’t know then see this link

1. Making API Using Node and Express. [Link](url)
2. Scaffolding redux-toolkit in NextJs. [Link](url)
3. API Setup in NextJs. [Link](URL)

Now we are doing 4th part. Let’s derive on-

**Step-1 : .env file Setup and necessary package install**

In your root project create .env.local file and do this

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b4hvmol2iitcax91a4te.png)

Here API key is a AI key which you get form your Ai Dashboard.  https://platform.openai.com/

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/scd4wyt40i5aamgt1a3f.png)

If you don’t have any AI API key then crate one and put in you .env.local file. And then install this package

```
  npm i openai@3.3.0
```

**Step-2 : movie Api Setup**

Previously we did a movie Api setup. [API Setup in NextJs](https://dev.to/kamruzzaman/api-setup-in-nextjs-3gen).
Go to reduxStore/features/movie folder and create this file
   1. movieApi.js
   2. movieSlice.js

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yq1f5xpteo5wv86sj1yf.png)

**movieApi.js**

```
import { apiSlice } from "../api/apiSlice";

export const moviesApi = apiSlice.injectEndpoints({
    endpoints: (builder) => ({
        topMovies: builder.query({
            query: () =>
                `/top-movies`,
        }),
        manualMovieStore: builder.mutation({
            query: (data) => ({
                url: "/movie-store",
                method: "POST",
                body: data,
            }),
        }),
        
        aiMovieStore: builder.mutation({
           
            query: (data) => ({
                
                url: "/ai-movie-store",
                method: "POST",
                body: data,
                
            }),
            async onQueryStarted(arg, { queryFulfilled, dispatch }) {
               console.log('redux', arg)
            },
        }),
        
    }),
});

export const { useTopMoviesQuery, useManualMovieStoreMutation, useAiMovieStoreMutation} = moviesApi;

```
Here we have Three end points. There are
   1. "/top-movies"
   2. "/movie-store"
   3. "/ai-movie-store"

**movieSlice.js**

```
import { createSlice } from "@reduxjs/toolkit";

const initialState = {
    topMovies: [],
    aiMovieData:{},
    sampleData:"sdfsf sdfsf"
    
};

const movieSlice = createSlice({
    name: "movie",
    initialState,
    reducers: {
        topMovies: (state, action) => {
            state.topMovies = action.payload;
            
        },
        aiMovieData:(state, action) =>{
            console.log('redux movie')
            state.aiMovieData = action.payload;
        }
       
    },
});

export const { topMovies, aiMovieData} = movieSlice.actions;
export default movieSlice.reducer;

```
Here we have Two actions. 
   1. topMovies
   2. aiMovieData
Now, movieApi.js file, we have aiMovieStore method for store Ai information in our Database. Here you saw aiMovieData action method. This action store AI information in redux store.

**Step-3: Ai Movie Page Setup and Others**
Go to ai-make-movie folder and see page.js file. Write this code-

```
import AiFormInput from "../component/ai-make-movie/AiFormInput";
import LeftSideBar from "../component/common/LeftSideBar";
import RightSideBar from "../component/common/RightSideBar";

const Page = () => {
    return (
        <div className="flex min-h-screen">
        <LeftSideBar />
        <div className=" flex-1 py-10  px-5 sm:px-10 ">
         <AiFormInput />
        </div>
        <RightSideBar />
        </div>
    );
};

export default Page;

```
Now go to component/ai-make-movie and you see AiFormInput.js file 

**AiFormInput.js**

```
'use client';
import { aiMovieData } from '@/app/reduxStore/features/movie/movieSlice';
import Image from 'next/image';
import { useRouter } from 'next/navigation';
import { Configuration, OpenAIApi } from 'openai';
import { useState } from "react";
import { useDispatch } from 'react-redux';
import Loading from '../../ai-make-movie/loading';

const AiFormInput = () => {
  const [aiIdea, setAiIdea] = useState();
  const dispatch = useDispatch();
  const router = useRouter();
  const [loading, setLoading] = useState(false);

  //Ai configuration
  const openAiApiKey = process.env.NEXT_PUBLIC_OPEN_AI_API_KEY;
  const configuration = new Configuration({
      apiKey: openAiApiKey
  })
  const openAi = new OpenAIApi(configuration);

  //Ai form submit handle
  const handleSubmit = async (e) => {
    e.preventDefault();
    setLoading(true);
    const aiSampleMovieData = await fetchSynopsis(aiIdea)
    dispatch(aiMovieData(aiSampleMovieData));
    //console.log('form submit', data)
      
   router.push("/movie-made")
    
  };

  async function fetchSynopsis(outline){
    const response = await openAi.createCompletion({
        model: 'text-davinci-003',
        prompt:`Generate an engaging, professional and marketable movie synopsis based on an outline. The synopsis should include actiors names in brackets after each character. Choose actors that would be ideal for this role.
        ###
        outline: A big-headed daredevil fighter pilot goes back to school only to be sent on a deadly mission.
        synopsis: The Top Gun Naval Fighter Weapons School is where the best of the best train to refine their elite flying skills, When hotshot fighter pilot Maverick (Tom Cruise) is sent o the school, his rackless attitude and cocky demeanor put him at odds with the other pilots, especially the cool and collected Iceman (Val kilmer). But Maverick ins't only competing to be the top fighter pilot, he's also fighting for the attention of his beautiful flight instructor, Charlotte Blackwood (kelly McGillis). Maverick gradually earns the respect of his intructors and peers - and also the love of Charlotte, but struggles to balance his personal and professional life. As the pilots prepare for a mission against a foreign enemy, Maverick must confront his own demons and overcome the tragedies rooted deep in his past to become the best fighter pilot and return from the mission triumphant.
        ###
        outline: ${outline}
        synopsis:
        `,
        max_tokens: 700
    })
    const synopsis = response.data.choices[0].text.trim();
    console.log('fetchSynopsis', synopsis)
    const aiMovieData = fetchTitle(synopsis);
    return aiMovieData;
    
}

async function fetchTitle(synopsis){
    const response = await openAi.createCompletion({
        model: 'text-davinci-003',
        prompt:`Generate a catchy movie title for this synopsis: ${synopsis}`,
        max_tokens: 25,
        temperature: 0.7
    })
    const title = response.data.choices[0].text.trim();
    console.log('fetchTitle-1', synopsis)
    console.log('fetchTitle-2', title)
    const aiMovieData = fetchImagePromt(title, synopsis)
    return aiMovieData;
}

async function fetchImagePromt(title, synopsis){
    const response = await openAi.createCompletion({
    model: 'text-davinci-003',
    prompt: `Give a short description of an image which could be used to advertise a movie based on a title and synopsis.The description should be rich in visual detail but contain no names.
    ###
    title: Love's Time Warp
    synopsis: When scientist and time traveller Wendy (Emma Watson) is sent back to the 1920s to assassinate a future dictator, she never expected to fall in love with them. As wendy infiltrates the dictator's inner circle, she soon finds herself torn between her mission and her growing feelings for the leader (Brie Larson). With the help of a mysterious stranger from the future (Josh Brolin), Wendy must decide whether to carry out her mission or follow her heart. But the choices she makes in the 1920s will have far-reaching consequences that reverberate throuugh the ages.
    image description: A silhouetted figure stands in the shadows of a 1920s speakeasy, her face turned away from the camera. In the background, two people are dancing in the dim light, one wearing a flapper-style dress and the other wearing a dapper suit. A semi-transparent image of war is super-imposed over the scene.
    ###
    title: zero Earth
    synopsis: When baodyguard kob (Daniel Radcliffe) is recruited by the United Nations to save Planet Earth from the sinister Simm (John Malkovich), an alien lord with a plan to take over the world, he reluctantly accepts the challenge, With the help of this loyal sidekick, a brave and resourceful hamster named Gizmo (Gaten Matarazzo), Kob embarks on a perilous mission to destroy Simm. Along the way, he discovers a newfound courage and strength as he battles Simms's merciless forces. With the fate of the world in his hands, kob must find a way to defeat the alien lord and save the planet.
    image description: A tired and bloodied bodyguard and hamster standing a top a tall skyscraper, looking out over a vibrant cityscape, with a rainbow in the sky above them.
    ###
    title: ${title}
    synopsis: ${synopsis}
    image description:
    `,
    temperature: 0.8,
    max_tokens: 100

    })
    console.log('fetchImagePromt-1', synopsis)
    console.log('fetchImagePromt-2', title)
    const aiMovieData = fetchImageUrl(response.data.choices[0].text.trim(), synopsis, title)
    return aiMovieData;
}

async function fetchImageUrl(imagePrompt,synopsis,title){
    const response = await openAi.createImage({
        prompt: `${imagePrompt}. There should be no text in this iamge.`,
        n: 1,
        size: '256x256',
        response_format: 'b64_json'
    })
    const b64JsonImage = response.data.data[0];
    console.log('fetchImageUrl-1', synopsis)
    console.log('fetchImageUrl-2', title)
     const aiMovieData ={
        b64JsonImage,
        synopsis,
        title
    }

    return aiMovieData;
}

  if(loading){
    return <Loading/>
  }
  
  return (
    <div>
      <form onSubmit={handleSubmit}>
      <div className="bg-gray-200 p-5 rounded-md dark:bg-black">
        <div className="text-center mb-8 relative">
          <h1 className="text-2xl font-bold text-gray-700 mb-3 dark:text-white">
            Hello, I am here to help Make Movie
          </h1>
          <p className="dark:text-white">
            Please, write your idea below input box
          </p>
        
          <Image
                src="/robot-1.webp"
                alt="Bird flying animation" 
                className="rounded-full w-48 h-48 absolute top-0 right-0"
                width={105} 
                height={105} 
                
            />
        </div>
        
        <br /><br /><br /><br />
        <div className="mb-6">
          <label
            htmlFor="message"
            className="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
          >
            Type your Idea
          </label>
          <textarea
            id="message"
            rows={4}
            className="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
            placeholder="Type Movie Idea..."
            onChange={(e)=>setAiIdea(e.target.value)}
            
          />
          
        </div>
        <div className="text-right">
          <button
            type="submit"
            className="bg-black text-white p-3 rounded-md dark:border"
          >
            Make Movie
          </button>
        </div>
      </div>
      </form>
    </div>
  );
};

export default AiFormInput;


```

Here we are implement AI Prompt. Let’s do it-
If you hit this http://localhost:3000/ai-make-movie URL then you can see this page-


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u5p7s7ogws5620emz96y.png)

This page has one input field. User just type his idea and then click Make Movie button then AI generate our information. Let’s drive in our code. Here you see ** handleSubmit** method.

```
//Ai form submit handle
  const handleSubmit = async (e) => {
    e.preventDefault();
    setLoading(true);
    const aiSampleMovieData = await fetchSynopsis(aiIdea)
    dispatch(aiMovieData(aiSampleMovieData));
    //console.log('form submit', data)
      
   router.push("/movie-made")
    
  };

```
This method Tigger when we click Make Movie button. This method first call **fetchSynopsis** method and passed user input idea. 

```
async function fetchSynopsis(outline){
    const response = await openAi.createCompletion({
        model: 'text-davinci-003',
        prompt:`Generate an engaging, professional and marketable movie synopsis based on an outline. The synopsis should include actiors names in brackets after each character. Choose actors that would be ideal for this role.
        ###
        outline: A big-headed daredevil fighter pilot goes back to school only to be sent on a deadly mission.
        synopsis: The Top Gun Naval Fighter Weapons School is where the best of the best train to refine their elite flying skills, When hotshot fighter pilot Maverick (Tom Cruise) is sent o the school, his rackless attitude and cocky demeanor put him at odds with the other pilots, especially the cool and collected Iceman (Val kilmer). But Maverick ins't only competing to be the top fighter pilot, he's also fighting for the attention of his beautiful flight instructor, Charlotte Blackwood (kelly McGillis). Maverick gradually earns the respect of his intructors and peers - and also the love of Charlotte, but struggles to balance his personal and professional life. As the pilots prepare for a mission against a foreign enemy, Maverick must confront his own demons and overcome the tragedies rooted deep in his past to become the best fighter pilot and return from the mission triumphant.
        ###
        outline: ${outline}
        synopsis:
        `,
        max_tokens: 700
    })
    const synopsis = response.data.choices[0].text.trim();
    console.log('fetchSynopsis', synopsis)
    const aiMovieData = fetchTitle(synopsis);
    return aiMovieData;
    
}

```
This **fetchSynopsis** method has dummy result, so that AI know what I need actually. Then I passed outline which I passed as aiIdea Parameter. So this method give me some result. Then I sort this result and get my Synopsis or Description. Then I call another method **fetchTitle** for get a catchy Title. Here I passed my synopsis result as a Parameter. 

```
async function fetchTitle(synopsis){
    const response = await openAi.createCompletion({
        model: 'text-davinci-003',
        prompt:`Generate a catchy movie title for this synopsis: ${synopsis}`,
        max_tokens: 25,
        temperature: 0.7
    })
    const title = response.data.choices[0].text.trim();
    console.log('fetchTitle-1', synopsis)
    console.log('fetchTitle-2', title)
    const aiMovieData = fetchImagePromt(title, synopsis)
    return aiMovieData;
}

```
Now this method give me Movie Title require as my synopsis. Then again I call another method **fetchImagePromt** for image description. Here I passed Two parameter - title and synopsis

```
async function fetchImagePromt(title, synopsis){
    const response = await openAi.createCompletion({
    model: 'text-davinci-003',
    prompt: `Give a short description of an image which could be used to advertise a movie based on a title and synopsis.The description should be rich in visual detail but contain no names.
    ###
    title: Love's Time Warp
    synopsis: When scientist and time traveller Wendy (Emma Watson) is sent back to the 1920s to assassinate a future dictator, she never expected to fall in love with them. As wendy infiltrates the dictator's inner circle, she soon finds herself torn between her mission and her growing feelings for the leader (Brie Larson). With the help of a mysterious stranger from the future (Josh Brolin), Wendy must decide whether to carry out her mission or follow her heart. But the choices she makes in the 1920s will have far-reaching consequences that reverberate throuugh the ages.
    image description: A silhouetted figure stands in the shadows of a 1920s speakeasy, her face turned away from the camera. In the background, two people are dancing in the dim light, one wearing a flapper-style dress and the other wearing a dapper suit. A semi-transparent image of war is super-imposed over the scene.
    ###
    title: zero Earth
    synopsis: When baodyguard kob (Daniel Radcliffe) is recruited by the United Nations to save Planet Earth from the sinister Simm (John Malkovich), an alien lord with a plan to take over the world, he reluctantly accepts the challenge, With the help of this loyal sidekick, a brave and resourceful hamster named Gizmo (Gaten Matarazzo), Kob embarks on a perilous mission to destroy Simm. Along the way, he discovers a newfound courage and strength as he battles Simms's merciless forces. With the fate of the world in his hands, kob must find a way to defeat the alien lord and save the planet.
    image description: A tired and bloodied bodyguard and hamster standing a top a tall skyscraper, looking out over a vibrant cityscape, with a rainbow in the sky above them.
    ###
    title: ${title}
    synopsis: ${synopsis}
    image description:
    `,
    temperature: 0.8,
    max_tokens: 100

    })
    console.log('fetchImagePromt-1', synopsis)
    console.log('fetchImagePromt-2', title)
    const aiMovieData = fetchImageUrl(response.data.choices[0].text.trim(), synopsis, title)
    return aiMovieData;
}

```
Here inside this method, first I setup dummy result then I setup my parameter. This method give me image description as require title and synopsis. Now I get Three result
   1. synopsis or Description
   2. title or Movie Title
   3. imagePrompt or Image Description.
Now we call, another method **fetchImageUrl** for image create. 

```
async function fetchImageUrl(imagePrompt,synopsis,title){
    const response = await openAi.createImage({
        prompt: `${imagePrompt}. There should be no text in this iamge.`,
        n: 1,
        size: '256x256',
        response_format: 'b64_json'
    })
    const b64JsonImage = response.data.data[0];
    console.log('fetchImageUrl-1', synopsis)
    console.log('fetchImageUrl-2', title)
     const aiMovieData ={
        b64JsonImage,
        synopsis,
        title
    }

    return aiMovieData;
}

```
This method give me Base64 image and size 256 x 256. We can increase size. Now we get three information from AI and return this information like as  object to **handleSubmit** method 

```
//Ai form submit handle
  const handleSubmit = async (e) => {
    e.preventDefault();
    setLoading(true);
    const aiSampleMovieData = await fetchSynopsis(aiIdea)
    dispatch(aiMovieData(aiSampleMovieData));
    //console.log('form submit', data)
      
   router.push("/movie-made")
    
  };

```
Here this method got all information from AI and then dispatch this information to **aiMovieData** action, which we were create **movieSlice.js**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cmxt3hgg6gszghqwfrff.png)

So, **aiMovieDate** method store AI information. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mglqlsh72bba7g4gx1xc.png)

Now we show this information in our redux extension plugin.

**Step-4: Ai Result Show and Others** 

Go to /movie-made folder, open **page.js** and do this

```
import AiFormResult from "../component/ai-make-movie/AiFormResult";
import LeftSideBar from "../component/common/LeftSideBar";
import RightSideBar from "../component/common/RightSideBar";

const Page = () => {
    return (
        <div className="flex min-h-screen">
        <LeftSideBar />
        <div className=" flex-1 py-10  px-5 sm:px-10 ">
          <AiFormResult />
        </div>
        <RightSideBar />
        </div>
    );
};

export default Page;

```
Now go to /component/ai-make-movie folder and open **AiFormResult.js** and write this-

```
'use client';
import { useAllCategoriesQuery } from "@/app/reduxStore/features/category/categoryApi";
import { useAiMovieStoreMutation } from "@/app/reduxStore/features/movie/moviesApi";
import Image from 'next/image';
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import { useSelector } from "react-redux";

const AiFormResult = () => {
  const [movieData, setMovieData] = useState({
    title: '',
    category_id: '',
    description: '',
    image: null, 
  });
  const aiMovieData = useSelector((state)=>state.movies.aiMovieData);
  const { data, isLoading, isError } = useAllCategoriesQuery();
  const router = useRouter()
  const [aiMovieStore, { isSuccess }] = useAiMovieStoreMutation();

  //b64_json convert image src
  const getImageSource = () => {
    const imageData = aiMovieData?.b64JsonImage?.b64_json || '';
    return `data:image/png;base64,${imageData}`;
  };

  
  //for category when category change.
  const handleChange = (e) => {
    const { name, value } = e.target;
    setMovieData({ ...movieData, [name]: value });
  };

  //set ai data into movieData
  useEffect(()=>{
    setMovieData({
      title: aiMovieData?.title,
      description: aiMovieData?.synopsis,
      image: aiMovieData?.b64JsonImage?.b64_json,
      });
  },[aiMovieData?.b64JsonImage?.b64_json, aiMovieData?.synopsis, aiMovieData?.title])

  const handleSubmit = async (e) => {
    e.preventDefault();
    if(movieData.category_id == ''){
      alert('please Select Category')
      return;
    }
    
      console.log('Response from server:-2', movieData);
    
    try {
      const formData = new FormData();
      formData.append('title', movieData.title);
      formData.append('category_id', movieData.category_id);
      formData.append('description', movieData.description);
      formData.append('image', movieData.image);
      console.log('form submit', movieData)
      const response = await aiMovieStore(formData);
      // Handle the success response
      console.log('Response from server:', [...formData]);
      // Assuming you want to reset the form after successful submission
      setMovieData({
        title: '',
        category_id: '',
        description: '',
        image: null,
      });
      router.push("/");
    } catch (error) {
      // Handle the error
      console.error('Error saving the movie:', error);
    }
  };

  
  return (
    <div className="bg-gray-200 p-5 rounded-md dark:bg-black my-10">
      <div className="text-center mb-8">
        <h1 className="text-2xl font-bold text-gray-700 mb-3 dark:text-white">
          This is your Search Result
        </h1>
      </div>
      <form onSubmit={handleSubmit}>
      <div className="mx-10 px-10 py-16 bg-gray-400 dark:bg-black dark:border">
      <div className="mb-6 flex items-center justify-center">
          
          <Image
                src={getImageSource()}
                alt="result-image"
                className="rounded-md border border-2 border-x-1 w-[350px]"
                name="image"
                onChange={handleChange}
                width={105} 
                height={105} 
                layout="responsive"
            />
        </div>

        
        <div className="mb-6">
          <label
            htmlFor="large-input"
            className="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
          >
            Movie Title
          </label>
          <input
            type="text"
            id="large-input"
            className="block w-full p-4 text-gray-900 border border-gray-300 rounded-lg bg-gray-50 sm:text-md focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
            placeholder="Type your Movie Title..."
            value={aiMovieData?.title}
            name="title"
            onChange={handleChange}
            
          />
        </div>
        <div className="mb-6">
            <label
              htmlFor="base-input"
              className="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
            >
              Movie Category
            </label>
            <select
              id="category"
              className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
              name="category_id"
              onChange={handleChange}
            >
              <option value="">Choose category</option>
              {data && data.data?.map((category) => (
                <option key={category._id} value={category._id}>
                  {category.name}
                </option>
              ))}
            </select>
          </div>
        <div className="mb-6">
          <label
            htmlFor="message"
            className="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
          >
            Movie Short Description
          </label>
          <textarea
            id="message"
            rows={8}
            className="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
            placeholder="Type Movie short description..."
            value={aiMovieData?.synopsis}
            name="description"
            onChange={handleChange}
          />
        </div>
        <div className="text-right">
          <button className="bg-black text-white p-3 rounded-md dark:border">
            Save your Movie
          </button>
        </div>
      </div>
      </form>

    </div>
  );
};

export default AiFormResult;

```
now hit http://localhost:3000/movie-made URL then you can see this page

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7vfoo5aqz4h44q420i02.png)

Here This page, Show AI information. If you click **Save your Movie** button then it Tigger **aiMovieStore**
Method which we were define in moviesApi.js file. This method save Ai information data in our MongoDB.

```
import { apiSlice } from "../api/apiSlice";

export const moviesApi = apiSlice.injectEndpoints({
    endpoints: (builder) => ({
        topMovies: builder.query({
            query: () =>
                `/top-movies`,
        }),
        manualMovieStore: builder.mutation({
            query: (data) => ({
                url: "/movie-store",
                method: "POST",
                body: data,
            }),
        }),
        
        aiMovieStore: builder.mutation({
           
            query: (data) => ({
                
                url: "/ai-movie-store",
                method: "POST",
                body: data,
                
            }),
            async onQueryStarted(arg, { queryFulfilled, dispatch }) {
               console.log('redux', arg)
            },
        }),
        
    }),
});

export const { useTopMoviesQuery, useManualMovieStoreMutation, useAiMovieStoreMutation} = moviesApi;

```
Now we Finished our AI Prompt. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xvdcypguw4nfmnjx1h6y.png)
**Form page**



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9lpw5rm2081veh495ffs.png)
**Loading page**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qzq0labohw950qwfy39l.png)
**Ai Information show**



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g10x07iustvulxkg7t4i.png)
**Home page**

Next we deploy this App. Here is this Tutorial-

Deploy A NextJs App and Node API on a Linux Server. [Link](https://dev.to/kamruzzaman/deploy-a-nextjs-app-and-node-api-on-a-linux-server-3ge8)

full Project github
Node
https://github.com/kamruzzamanripon/node-movie-api
NextJs
https://github.com/kamruzzamanripon/next-movie-ui-with-node-api
NextJs UI
https://github.com/kamruzzamanripon/next-movie-ui

That's all. Happy Learning :) .
[if it is helpful, giving a star to the repository 😇]