DEV Community

Cover image for 🎉 Let's Build an AI Twitter Post Project Using Gemini API, Next.js, and TailwindCSS 🚀
Jagroop Singh
Jagroop Singh

Posted on

57 9 8 8 10

🎉 Let's Build an AI Twitter Post Project Using Gemini API, Next.js, and TailwindCSS 🚀

2025 is here, and what better way to kick off the year than by building an awesome Twitter Post project? 🎯 In this blog, I’ll show you how to integrate the Gemini API with Next.js and style it using TailwindCSS to create a simple but effective post system. Plus, we'll use the Gemini API Key to fetch posts and display them.

Let's firstly preview how our final mini project looks like :

Now,Let’s dive in! 🔥


Prerequisites 📋

Before we get started, make sure you have:

  • Node.js installed
  • A Gemini API key (set up at Gemini for key)
  • Familiarity with Next.js/React.js and TailwindCSS (if you need a refresher or want to learn Nextjs/Reactjs, check out this course :

1. Create a Next.js Project 🖥️

Start by creating a new Next.js project:

npx create-next-app twitter-post
cd twitter-post
Enter fullscreen mode Exit fullscreen mode

2. Install Gemini API Package 📦

Now, let’s install the Gemini npm package:

npm i @google/generative-ai
Enter fullscreen mode Exit fullscreen mode

Create a .env.local file in the root directory and add your Gemini API key:

GEMINI_API_KEY=your_api_key_here
Enter fullscreen mode Exit fullscreen mode

3. Fetch Twitter Posts with Gemini API 🔥

Create app/api/submit/route.tspath in project,In route.ts we will fetch the Twitter-like posts using the Gemini API and display them.

import { GoogleGenerativeAI } from '@google/generative-ai';
import { NextResponse } from 'next/server';

const API_KEY = process.env.GEMINI_AI_API_KEY || "";

export async function POST(req: Request) {
  const { description } = await req.json();

  if (!description) {
    return NextResponse.json(
      { error: 'Description is required.' },
      { status: 400 }
    );
  }

  try {
    const genAI = new GoogleGenerativeAI(API_KEY);
    const model = await genAI.getGenerativeModel({ model: 'gemini-1.5-flash' });
    const prompt = `Generate twitter tweet on the basis of this description: ${description}`;
    const result = await model.generateContent([prompt]);

    if (result && result.response) {
      const generatedText = await result.response.text();
      return NextResponse.json({ tweet: generatedText });
    } else {
      throw new Error('No response received from model.');
    }
  } catch (error) {
    console.error('Error generating tweet:', error);
    return NextResponse.json({ error: 'Failed to generate tweet' }, { status: 500 });
  }
}

Enter fullscreen mode Exit fullscreen mode

Above code's functionality description is:

  • Generates Tweet: Takes a description, uses Google's AI to create a tweet based on it.
  • Error Handling: Returns errors if no description is provided or if AI fails.
  • AI Model Used: Uses gemini-1.5-flash for content generation.

4. Main front-end logic of handling : generate tweet, copy tweet. regenerate tweet is :

This is simple server side html, tailwindcss component :

import { RiTwitterXLine } from "react-icons/ri";
import InteractiveForm from "./components/InteractiveForm";

export default function Home() {
  return (
    <div className="flex flex-col justify-center items-center min-h-screen bg-[#1a1a1a] w-full">
      <RiTwitterXLine size={50} color="white" />
      <div className="flex flex-col justify-center items-center mt-7 w-full max-w-4xl py-3">
        <p className="text-white text-4xl font-extrabold">Idea to tweet in seconds.</p>
        <p className="text-white text-2xl">Tweet Craft is your superhuman tweet-writing expert.</p>
        <InteractiveForm />
      </div>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

and the main part that handle all the tweet generation, copy,regenrate is client side component which is :

'use client';

import { useState } from 'react';
import { BsArrowRightCircle } from "react-icons/bs";

export default function InteractiveForm() {
  const [tweet, setTweet] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);

  const handleSubmit = async (e: any) => {
    e.preventDefault();
    const description = e.target.description.value;
    setLoading(true);

    const response = await fetch('/api/submit', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ description }),
    });

    const result = await response.json();
    setLoading(false);

    if (result.tweet) {
      setTweet(result.tweet);
    } else {
      console.error('Error:', result.error);
    }
  };

  const handleCopy = () => {
    if (tweet) {
      navigator.clipboard.writeText(tweet);
      alert('Tweet copied to clipboard!');
    }
  };

  const handleRegenerate = async () => {
    if (tweet) {
      setLoading(true);
      const description = tweet;
      const response = await fetch('/api/submit', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ description }),
      });

      const result = await response.json();
      setLoading(false);

      if (result.tweet) {
        setTweet(result.tweet);
      }
    }
  };

  return (
    <div className="w-full relative">
      <form onSubmit={handleSubmit} className="w-full">
        <div className="relative">
          <textarea
            id="description"
            name="description"
            rows={10}
            placeholder="Write your thoughts here..."
            className="
              block 
              w-full
              px-4 
              py-3 
              mt-4
              bg-[#1a1a1a]
              text-lg
              border 
              border-gray-300 
              text-white
              rounded-md 
              focus:outline-none 
              focus:ring-2 
              focus:ring-gray-300 
              focus:border-transparent
            "
          />
          <button
            type="submit"
            className="
              absolute 
              bottom-2 
              right-2 
              p-2 
              rounded-full 
              text-white 
              bg-transparent 
              hover:bg-gray-700
            "
            disabled={loading}
          >
            <BsArrowRightCircle size={30} />
          </button>
        </div>
      </form>

      {tweet && (
        <div className="mt-6 text-white">
          <p className="text-lg">{tweet}</p>
          <div className="flex gap-4 mt-4">
            <button
              onClick={handleCopy}
              className="px-4 py-2 bg-blue-500 rounded-full text-white hover:bg-blue-400"
            >
              Copy
            </button>
            <button
              onClick={handleRegenerate}
              className="px-4 py-2 bg-green-500 rounded-full text-white hover:bg-green-400"
            >
              Regenerate
            </button>
          </div>
        </div>
      )}

      {loading && (
        <div className="absolute top-0 left-0 w-full h-full flex items-center justify-center bg-opacity-50">
          <span className="text-white">Generating tweet...</span>
        </div>
      )}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

You can easily change colors, spacing, and other design elements using Tailwind classes.

5. Run the Project 🚀

Now, it’s time to run your project:

npm run dev
Enter fullscreen mode Exit fullscreen mode

Open http://localhost:3000 in your browser, and you’ll see your Twitter-like post feed in action! 🎉


Contribute to the Repository 💻

I would love to see what you can build with this project! Feel free to fork this repository, create issues, or even submit pull requests. Let's make this project even more powerful together!

Like embedding twitter api's,adding functionality of suggestion buttons etc.

Check out the GitHub repository here🚀 :

GitHub logo Jagroop2001 / tweet-craft

Tweet Craft is an AI-powered application built with Next.js that generates tweets based on user descriptions. By using Gemini's API, the app enables users to easily craft tweets based on their input, making it perfect for those looking for quick and creative social media content.

Tweet Craft

Tweet Craft is an AI-powered application built with Next.js that generates tweets based on user descriptions. By using Gemini's API, the app enables users to easily craft tweets based on their input, making it perfect for those looking for quick and creative social media content Video Link : https://vimeo.com/1043260556?share=copy

Features

  • AI Tweet Generation: Users provide a description, and the app generates a tweet based on the input.
  • Gemini API Integration: The app utilizes Gemini's API to process natural language descriptions and create tweets.

Installation

Prerequisites

  • Node.js (>= 18.0)
  • npm or yarn (package manager)

Steps to Get Started

  1. Clone the repository:

    git clone https://github.com/Jagroop2001/tweet-craft
    cd tweet-craft
    Enter fullscreen mode Exit fullscreen mode
  2. Install the dependencies:

    npm install
    # OR
    yarn install
    Enter fullscreen mode Exit fullscreen mode
  3. Set up your Gemini API key:

    • Create a .env.local file in the root of the project.
    • Add your Gemini API key to the file:
    GEMINI_AI_API_KEY="YOUR GEMINI API KEY"
    Enter fullscreen mode Exit fullscreen mode
  4. Run…


Happy coding, and I hope you have an amazing 2025! 🎉 Let’s build more cool stuff together!

🚀 Stay connected and follow my journey! 🌟

👉 Follow me on Twitter 🐦

👉 Check out my GitHub 💻

Do your career a big favor. Join DEV. (The website you're on right now)

It takes one minute, it's free, and is worth it for your career.

Get started

Community matters

Top comments (19)

Collapse
 
yashksaini profile image
Yash Kumar Saini

I really love how light it is, I am going to use it and recreate the frontend at most

Collapse
 
jagroop2001 profile image
Jagroop Singh

That's awesome @yashksaini ! I'm sure your recreation will turn out great—good luck with the frontend!

Collapse
 
paxnw profile image
caga

Wow, @jagroop2001 this is an amazing project! 🚀 Combining Gemini API, Next.js, and TailwindCSS is such a powerful stack—can't wait to clone this project. Keep up the great work! &
Happy New year !!

Collapse
 
jagroop2001 profile image
Jagroop Singh

Thanks @paxnw , Happy New year to you too.

Collapse
 
ali822cwh profile image
Ali822-cwh

I love this project ❤️

Collapse
 
jagroop2001 profile image
Jagroop Singh

Thanks @ali822cwh ❤️

Collapse
 
mahak_kaurchhabra_39a895 profile image
Mahak Kaur

Good work @jagroop2001 ! would definitely wanna try this out myself.

Collapse
 
jagroop2001 profile image
Jagroop Singh
Collapse
 
works profile image
Web

this is really an amazing and very useful project! 🚀.

Collapse
 
jagroop2001 profile image
Jagroop Singh

thanks @works

Collapse
 
hraifi profile image
sewiko

this is very useful project

Collapse
 
jagroop2001 profile image
Jagroop Singh

Thanks @hraifi

Collapse
 
lithoeme profile image
lithoeme

what does it do exactly?

Collapse
 
jagroop2001 profile image
Jagroop Singh

This web app generates tweets based on the description provided by the user. It's a handy tool for creating engaging and concise tweets effortlessly.

The project is open-source, and contributors are actively improving it. You can check it out and contribute on GitHub: github.com/Jagroop2001/tweet-craft

Collapse
 
lithoeme profile image
lithoeme

omg ive been looking for exactly this i think. imma check it out!

Thread Thread
 
jagroop2001 profile image
Jagroop Singh

🎉

Collapse
 
jagroop2001 profile image
Jagroop Singh
Collapse
 
shan323 profile image
Zee

Hi @jagroop2001 !!
This project is really inspiring especially for me as I am very new to coding and I read this blog and undertand the functionality and will surely clone this and extend this further.

I am very noob so it may possible that I need your help.
Would you mentor me in this project so that we can extend this further ?

Collapse
 
jagroop2001 profile image
Jagroop Singh

Hi @shan323 !!
Welcome to dev.to !!

Yes I will completely mentor you whenever you need my help.
You can reach me on linkedin,twitter,email etc. everything is added on my profile and all the best.

11 Tips That Make You a Better Typescript Programmer

typescript

1 Think in {Set}

Type is an everyday concept to programmers, but it’s surprisingly difficult to define it succinctly. I find it helpful to use Set as a conceptual model instead.

#2 Understand declared type and narrowed type

One extremely powerful typescript feature is automatic type narrowing based on control flow. This means a variable has two types associated with it at any specific point of code location: a declaration type and a narrowed type.

#3 Use discriminated union instead of optional fields

...

Read the whole post now!

👋 Kindness is contagious

Dive into an ocean of knowledge with this thought-provoking post, revered deeply within the supportive DEV Community. Developers of all levels are welcome to join and enhance our collective intelligence.

Saying a simple "thank you" can brighten someone's day. Share your gratitude in the comments below!

On DEV, sharing ideas eases our path and fortifies our community connections. Found this helpful? Sending a quick thanks to the author can be profoundly valued.

Okay