Skip to main content

Command Palette

Search for a command to run...

Building Stillroom: My First AI App Using Node, Express, and Groq

Published
Building Stillroom: My First AI App Using Node, Express, and Groq
T

Full Stack Software Engineer | Developer Advocate | Community Manager | Contant Creator | Technical Writer | Tech Blogger | Open Source Contributor

My favourite thing about ChatGPT and Microsoft’s Copilot? They’ve helped me become a better developer.

I’ve seen that some developers don’t rely much on AI or don’t even use it at all, and I admire them. Although I do admit, sometimes relying too much on AI can water down your thought process, your ability to independently resolve or troubleshoot problems and perhaps even forget the fundamentals of programming.

I am part of a team where I am always exposed to and reading senior developers’ code. There is one intermediate, and I am the only junior in the team. A lot of times, when I use ChatGPT or Copilot, it is to help me understand the code I am reading. AI, to me, is my teacher. I love the fact that I can go to ChatGPT and ask the same query again and again until I get it right because I know it won’t ever get tired of explaining the same logic repeatedly.

Being multilingual also poses its own unique challenge, so I want the explanations to be in the simplest English possible.

This is not to say that my seniors aren’t welcoming, nor to say I am not getting all the support I need.

I just want to understand the “What does this piece of code actually do?”, not just the “why”. To break down code into small, clear, digestible pieces.

That’s how Stillroom was born

Paste code → get a clear explanation in balanced and simple English.

This is the story of how I built it, the challenges I faced, and what I learnt along the way.

Exploring AI/LLMs

I’ve always been curious about artificial intelligence and how everything regarding it works behind the scenes. My curiosity has piqued since the popularity of ChatGPT and because many, if not most, products and companies are integrating AI into their workflows. The knowledge I have regarding AI and LLMs is pretty much surface-level, but enough to follow along in a conversation. I would like to deepen my learning and gain more exposure in my career.

What is Artificial Intelligence

Artificial intelligence is essentially the attempt to teach machines how to think, or at least simulate thinking in a way that feels natural to us. Teaching them how to recognise pattern recognition, predictions, decision-making, and understanding context.

It’s a system trained on massive amounts of data, so it can notice patterns we don’t even realise we’re giving it. AI is mathematics + data + probability + human intention working together quietly in the background.

What are Large Language Models

LLMs (like ChatGPT) are just one specific type of AI, focused on language. They’re trained to understand text, predict the next token, question or conversation, and generate responses that feel meaningful.

The best way to think of them is as statistical models that learnt language by being exposed to absurd amounts of text. That could be billions of sentences, paragraphs, conversations, code, books, and articles. They learn structure, rhythm, tone, patterns


An LLM doesn’t “know” things the way humans do. It predicts the most likely continuation based on everything it’s seen. But because human language itself is patterned, the output often feels intelligent, thoughtful, or strangely human.

How AI and LLMs work together

AI is the broad field
 the brain.
LLMs are a subset of AI focused on language

AI gives the system:

  • reasoning

  • maths

  • internal tools

  • decision-making

  • the ability to follow instructions

LLMs give it:

  • communication

  • explanation

  • context understanding

  • the ability to sound natural

  • the ability to adapt to your tone

Together, they create something that feels like a conversation: part machine precision, part human-like expression.

Stillroom

Software development has taught me that there’s always something to learn. Even if it’s something you’re familiar with, there is and always still room to learn and grow.

Stillroom is an AI app I designed to help me do exactly that. It helps me break down code I know and code I don’t and see how the same logic can be explained in multiple ways. I’m not just learning what the code does; I’m learning how to communicate the concept behind it.

Server-side with Node, Express and Groq

Before this project, I’d never built anything with Node and Express. I am currently focused on being a C# .NET backend developer. I like to be fluid, to learn and try tools outside my known stack. Node and Express are the most popular environments for small web APIs, have massive community support, and work perfectly with Vercel and serverless functions.

Groq AI is a lightning-fast API for running Llama models cheaply and quickly. Why did I choose it? Free-tier friendly and flexible, and its OpenAI-style API is simple to work with, and the documentation is great. It is perfect for code explanation, not too slow, not too heavy.

1. The Express App Setup

This part of the backend creates the actual server that receives requests from the frontend. It initialises an Express application, allows it to read JSON data, and mounts the /api/analyze route.

const app = express();
app.use(express.json());
app.use("/api/analyze", analyzeRouter);

const PORT = process.env.PORT || 4000;
app.listen(PORT, () => {
  console.log(`Stillroom server listening on port ${PORT}`);
});

2. The /api/analyze Route

This is the heart of Groq. It takes the user's provided code, adds validation to check if the input is not empty, and then forwards it to Groq’s Llama model with a carefully written system prompt that shapes the tone of the explanation.

   const { entry, language } = req.body;
    if (!entry || !entry.toString().trim()) {
      return res
        .status(400)
        .json({ error: "Code snippet (entry) is required." });
    }

    const messages = [
      { role: "system", content: SYSTEM_PROMPT },
      {
        role: "user",
        content: `Explain this ${
          language ? language + " code" : "code"
        }:\n\n${entry}\n\nPlease give: (1) a one-sentence summary, (2) a concise step-by-step breakdown, (3) suggestions/improvements if any. Use markdown code blocks for examples.`,
      },
    ];

3. Extracting the LLM Response

LLMs sometimes return message content in different shapes depending on the provider or version. This takes the first choice from the model, gets the AI’s written explanation, and sends it back to the frontend in a clean format. This block safely extracts the explanation:

const reflection = aiRes.data?.choices?.[0]?.message?.content;
res.json({ reflection });

Client-side with Next.js, TailwindCSS, Motion and Lottiefiles

On the frontend, this small block of code is responsible for handling what happens when the user clicks “Explain”. It starts by clearing old errors, validating that the user actually pasted something, and showing a loading state so the UI feels responsive. If the input is empty, it gracefully notifies the user and stops there.

    // within submit() {}
    SetError("");
    if (!entry.trim()) {
      setError("Paste a code snippet to get an explanation.");
      return;
    }
    setLoading(true);
    setReflection("");
    try {
      const res = await axios.post(`${backendUrl}/analyze`, {
        entry,
        language,
      });
      const text: string = res.data.reflection;
      setReflection(text);

Once the snippet is confirmed to be real code, the function sends it to the backend using a Axios POST request. The backendURL points to the deployed Express server, and the payload includes both the code and the detected, if selected, language. When the server returns a response, the Reflection.tsx component pulls out the reflection text, which is the model’s explanation, and updates the UI with it.

const [reflection, setReflection] = useState<string>(
    "Your explanation will appear here"
);  

// inside the component's return
{reflection && <Reflection text={reflection} />}

I chose a few lightweight tools that made the interface feel smooth without overwhelming the project. Tailwind CSS handled all the styling. For subtle interactions, Framer Motion (now Motion) added gentle transitions and small movements that make Stillroom feel calm and alive, especially when elements fade in or shift on load. And for the loading state, I used an animation from LottieFiles, which provided a lightweight, looping loader that fits the aesthetic of the app.

Deployment Process on Vercel

The love I have for Vercel is beyond words. I love Vercel. Deployment was very straightforward and just clicks of buttons.

For the client, I had already created a project on my dashboard. Selected my repo and which folder to deploy, and Vercel did the rest, and just like that, Stillroom’s deployment was a success.

For the server, I deployed it using Vercel CLI. Installed the package, logged in to my account and ran the vercel command, set the name of my project, and just like that, the deployment was a success.

Closing

Stillroom started as a curiosity, a small idea to help me understand code more clearly, and it ended up becoming my first AI project. Along the way, I learnt more about JS backend development, AI and LLMs. And each challenge pushed me a little further.

Building this reminded me that you don’t need a grand idea to start; you just need something personal and useful. Stillroom is exactly that for me. And if you’ve been thinking about building an AI application, this is your sign to build something of your own.

Full Stack 🚀

Part 2 of 4

This section will be focusing more on the functionality side of things with minimal CSS in mind. I will be discussing learnings from various frontend (NextJS, Angular...) and backend (.NET. Node/Express...) frameworks

Up next

Trust the CLI: My Essential Git Commands

Because sometimes, the command line is the most reliable teammate.