<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Abhishek Mishra</title>
    <description>The latest articles on Forem by Abhishek Mishra (@abhishek_mishra_39244395e).</description>
    <link>https://forem.com/abhishek_mishra_39244395e</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3603409%2F0e75d819-a2fe-435f-9932-4a715020b942.png</url>
      <title>Forem: Abhishek Mishra</title>
      <link>https://forem.com/abhishek_mishra_39244395e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/abhishek_mishra_39244395e"/>
    <language>en</language>
    <item>
      <title>Title: Building a Persistent Task Manager with JS and Bootstrap 🚀</title>
      <dc:creator>Abhishek Mishra</dc:creator>
      <pubDate>Tue, 23 Dec 2025 15:24:29 +0000</pubDate>
      <link>https://forem.com/abhishek_mishra_39244395e/title-building-a-persistent-task-manager-with-js-and-bootstrap-33he</link>
      <guid>https://forem.com/abhishek_mishra_39244395e/title-building-a-persistent-task-manager-with-js-and-bootstrap-33he</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Intro&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Have you ever wondered how to build a functional CRUD (Create, Read, Update, Delete) application without a complex framework like React or Angular? Today, we're diving deep into a Task Management app built using Vanilla JavaScript, Bootstrap 5, and Local Storage for data persistence.&lt;/p&gt;

&lt;p&gt;**&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Concept
&lt;/h2&gt;

&lt;p&gt;**&lt;br&gt;
The Tasky Project is designed to help users manage daily tasks by creating interactive cards. Each task includes a title, description, type, and an optional image URL.&lt;/p&gt;

&lt;p&gt;**&lt;/p&gt;
&lt;h2&gt;
  
  
  Key Features:
&lt;/h2&gt;

&lt;p&gt;**&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Persistent Storage: Tasks stay even after a page refresh thanks to localStorage.&lt;/li&gt;
&lt;li&gt;Live Search: Filter through your tasks in real-time.&lt;/li&gt;
&lt;li&gt;In-Place Editing: Modify task details directly on the card.&lt;/li&gt;
&lt;li&gt;Fully Responsive: A clean UI that works on mobile and desktop using Bootstrap.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;1. The Power of&lt;/strong&gt; &lt;code&gt;localStorage&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;One of the most important aspects of this project is ensuring that user data isn't lost. We use a central state object and synchronize it with the browser's storage.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;JavaScript&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Function to sync our local state with browser storage
const updateLocalStorage = () =&amp;gt; {
  localStorage.setItem(
    "task",
    JSON.stringify({
      tasks: state.taskList,
    })
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the application loads, it triggers &lt;code&gt;loadInitialData()&lt;/code&gt; to fetch this stored string, convert it back into JSON, and render the cards on the screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Dynamic UI Rendering&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of hardcoding HTML, we use Template Literals to generate task cards dynamically based on the data. This allows for a much more scalable application.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;JavaScript&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const htmlTaskContent = ({ id, title, description, type, url }) =&amp;gt; `
  &amp;lt;div class="col-md-6 col-lg-4 mt-3" id=${id}&amp;gt;
    &amp;lt;div class='card shadow-sm task__card'&amp;gt;
      &amp;lt;div class='card-header d-flex justify-content-end'&amp;gt;
          &amp;lt;button type='button' class='btn btn-outline-primary' onclick="editTask.apply(this, arguments)"&amp;gt;
              &amp;lt;i class='fas fa-pencil-alt'&amp;gt;&amp;lt;/i&amp;gt;
          &amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div class='card-body'&amp;gt;
          &amp;lt;img src=${url || 'default-image.png'} class='card-img-top' /&amp;gt;
          &amp;lt;h4 class='card-title'&amp;gt;${title}&amp;lt;/h4&amp;gt;
          &amp;lt;p class='text-muted'&amp;gt;${description}&amp;lt;/p&amp;gt;
          &amp;lt;span class='badge bg-primary'&amp;gt;${type}&amp;lt;/span&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
`;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Implementing Search Functionality&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The search feature uses the &lt;code&gt;.filter()&lt;/code&gt; method to match the user's input against the task titles in our state. Every time you type, the UI clears and re-renders only the matching tasks.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;JavaScript&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const searchTask = (e) =&amp;gt; {
  const resultData = state.taskList.filter(({ title }) =&amp;gt;
    title.toLowerCase().includes(e.target.value.toLowerCase())
  );

  resultData.map((cardData) =&amp;gt;
      taskContents.insertAdjacentHTML("beforeend", htmlTaskContent(cardData))
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Handling Edits with contenteditable&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A cool trick used in this project is the &lt;code&gt;contenteditable&lt;/code&gt; attribute. Instead of opening a new form, we make the existing card text editable, allowing for a seamless user experience.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;JavaScript&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Making fields editable
taskTitle.setAttribute("contenteditable", "true");
taskDescription.setAttribute("contenteditable", "true");
taskType.setAttribute("contenteditable", "true");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Building this project highlights how powerful Vanilla JavaScript can be when combined with utility-first CSS frameworks like Bootstrap. It teaches fundamental concepts like DOM manipulation, event handling, and state management.&lt;/p&gt;

&lt;p&gt;Check out the full source code here: &lt;a href="https://github.com/abhishekmishra173/Tasky-Project" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Title: Building a "Smart" Markdown Note-Taker with Next.js 15 and OpenAI</title>
      <dc:creator>Abhishek Mishra</dc:creator>
      <pubDate>Tue, 23 Dec 2025 14:45:20 +0000</pubDate>
      <link>https://forem.com/abhishek_mishra_39244395e/title-building-a-smart-markdown-note-taker-with-nextjs-15-and-openai-8d2</link>
      <guid>https://forem.com/abhishek_mishra_39244395e/title-building-a-smart-markdown-note-taker-with-nextjs-15-and-openai-8d2</guid>
      <description>&lt;p&gt;&lt;strong&gt;Intro&lt;/strong&gt;&lt;br&gt;
In 2025, a standard CRUD app isn't enough to impress. Users expect applications to think. Today, we’re going to build a Smart Note-Taking App that doesn't just store Markdown but uses AI to automatically generate tags and summaries for your notes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Stack:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frontend/Backend: Next.js 15 (App Router)&lt;/li&gt;
&lt;li&gt;Styling: Tailwind CSS&lt;/li&gt;
&lt;li&gt;Database: Prisma + PostgreSQL (via Supabase)&lt;/li&gt;
&lt;li&gt;AI: OpenAI API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;**&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Setting Up the Project
&lt;/h2&gt;

&lt;p&gt;**&lt;br&gt;
First, initialize your project with the latest Next.js features:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;bash&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;``
npx create-next-app@latest smart-notes --typescript --tailwind --eslint
cd smart-notes
npm install @prisma/client lucide-react openai
npx prisma init
``

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;**&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The Database Schema
&lt;/h2&gt;

&lt;p&gt;**&lt;br&gt;
We need a simple but effective model. In prisma/schema.prisma:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PostgreSQL&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`

model Note {
  id        String   @id @default(cuid())
  title     String
  content   String   @db.Text
  tags      String[]
  summary   String?  @db.Text
  createdAt DateTime @default(now())
}
`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;**&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The "Smart" Logic (Server Action)
&lt;/h2&gt;

&lt;p&gt;**&lt;br&gt;
Instead of a separate API route, we’ll use a Next.js Server Action. This keeps our logic bundled and secure on the server.&lt;/p&gt;

&lt;p&gt;Create a file at &lt;code&gt;app/actions/notes.ts&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;typescript&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"use server";
import { PrismaClient } from "@prisma/client";
import OpenAI from "openai";

const prisma = new PrismaClient();
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

export async function createSmartNote(formData: FormData) {
  const title = formData.get("title") as string;
  const content = formData.get("content") as string;

  // AI Magic: Generate Summary and Tags
  const aiResponse = await openai.chat.completions.create({
    model: "gpt-4o-mini",
    messages: [
      { role: "system", content: "Analyze the following note. Return a JSON object with a 'summary' (1 sentence) and 'tags' (array of strings)." },
      { role: "user", content: content }
    ],
    response_format: { type: "json_object" }
  });

  const { summary, tags } = JSON.parse(aiResponse.choices[0].message.content || "{}");

  const note = await prisma.note.create({
    data: { title, content, summary, tags },
  });

  return note;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;**&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The UI: Clean and Functional
&lt;/h2&gt;

&lt;p&gt;**&lt;br&gt;
In your &lt;code&gt;app/page.tsx&lt;/code&gt;, create a simple form to handle the input. We'll use useFormStatus to show a loading state while the AI is "thinking."&lt;/p&gt;

&lt;p&gt;&lt;em&gt;typescript&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createSmartNote } from "./actions/notes";

export default function Home() {
  return (
    &amp;lt;main className="max-w-4xl mx-auto p-8"&amp;gt;
      &amp;lt;h1 className="text-3xl font-bold mb-6"&amp;gt;Smart Markdown Notes 📝&amp;lt;/h1&amp;gt;

      &amp;lt;form action={createSmartNote} className="flex flex-col gap-4 bg-gray-50 p-6 rounded-lg shadow"&amp;gt;
        &amp;lt;input name="title" placeholder="Note Title" className="p-2 border rounded" required /&amp;gt;
        &amp;lt;textarea name="content" placeholder="Write your markdown here..." rows={6} className="p-2 border rounded" required /&amp;gt;
        &amp;lt;button type="submit" className="bg-blue-600 text-white py-2 rounded hover:bg-blue-700 transition"&amp;gt;
          Save Smart Note
        &amp;lt;/button&amp;gt;
      &amp;lt;/form&amp;gt;

      {/* Logic to fetch and map notes would go here */}
    &amp;lt;/main&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;**&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Why this matters in 2025
&lt;/h2&gt;

&lt;p&gt;**&lt;br&gt;
&lt;strong&gt;Server Actions:&lt;/strong&gt; We eliminated the need for complex useEffect and fetch calls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI Integration:&lt;/strong&gt; We moved from "Full Stack" to "AI-Native" by integrating intelligence directly into the data flow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Type Safety:&lt;/strong&gt; Using TypeScript ensures that our AI response matches our database schema.&lt;/p&gt;

&lt;p&gt;**&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;**&lt;br&gt;
Building full-stack apps today is about orchestrating services. By combining the power of Next.js with AI, you can create tools that provide actual utility beyond just data storage.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>nextjs</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
