Give AI (Code) a chance

On LinkedIn we’re seeing so many posts about vibe coding. Some people are very positive about it, others very negative. One thing that stands out to me is that a lot of the criticism comes from expecting vibe coding to solve the hardest, most obscure parts of programming. But why would we expect AI to already be able to tackle the trickiest computer science challenges?

Medicine began thousands of years ago, but we didn’t expect heart surgery right away. Engineering has been around for centuries, but skyscrapers came much later. Programming languages are only a few decades old, and it took time before we had web sockets and modern encryption. Even space flight started more than fifty years ago, yet we’re still not on Mars.

But what it can do is amazing. We can already spin up entire websites from scratch, generate BI dashboards that pull together complex data, or scaffold API backends in minutes. It helps with testing, boilerplate code, documentation, and even brainstorming design ideas. These are all the kinds of tasks that normally take up time and energy, and now we can shift more of that effort into creative problem-solving. The fact that AI can reliably handle this level of work today is not a limitation—it’s progress worth celebrating.

So maybe we need to give AI the same patience. Instead of demanding that it solve the hardest coding problems right now, let’s allow it the years it needs to grow. Just as doctors needed centuries before achieving successful heart transplants, AI will need time to mature before we can expect it to handle the deepest corners of our code.

We can “Just rewrite it” now

One of the most surprising benefits of AI-assisted coding is that it finally makes rewriting a project practical.

Back in 1970, Winston W. Royce *, in his paper Managing the Development of Large Software Systems, suggested that the only way to build a great application is to write it twice. As he put it, “arrange matters so that the version finally delivered to the customer for operational deployment is actually the second version.”

The first pass teaches you what really works and what doesn’t. The second pass is when you get it right. In the past, rewriting a full project was too expensive and time-consuming, so most teams just pushed forward with whatever they had. But with AI code generation, we can now revisit the same idea multiple times without months of extra effort, refining it each time until it’s something truly solid.

It’s like old wisdom finally caught up with the tools we have today.



* Winston W. Royce, Managing the Development of Large Software Systems is usually seen as the origin of the Waterfall method of Software Engineering

It’s about knowing what can be done

I’ve seen quite a few posts lately talking about how important context is when using AI to code. I couldn’t agree more. For me, vibe coding isn’t about asking the AI what to code, it’s about explaining what we want to achieve. It reminds me of something I heard years ago—programming is less about knowing how to do something and more about knowing what can be done.

As a senior developer, I’ve built up a strong understanding of the tools at my disposal—React, REST APIs, SQL, and many others. I also know what I want to achieve with the products I’m developing. When I bring that knowledge into the conversation with AI, I can guide it in the right direction and ensure the tools are being used correctly. That combination feels like a genuine superpower.

I wouldn’t claim that AI makes me ten times faster, but it has changed the way I work. I’m now able to deliver far more value in the same amount of time. That shift in output and focus is where the real impact or AI Coding/Vibe coding lies.

Start Simple!

When we talk about software architecture, it’s easy to get lost in diagrams full of boxes, arrows, and buzzwords. But for most startup projects, the foundation doesn’t need to be complicated.

At its simplest, you need three layers. The front end, where users interact with your product. The back end, which includes authentication and the business logic that powers the experience. And the database, where the information lives. That’s enough to get started and build something meaningful.

And here’s the exciting part: today we can vibe code across all of these layers. Tools like Bolt.new make it quick to spin up front ends. ChatGPT or GitHub Copilot can help shape the back end and authentication logic. They can even guide you through setting up and querying your database. Beyond those, there’s a growing world of AI tools that can fit in wherever you need them.

You don’t need queues, event buses, or complex logging right away. Keep it simple, focus on delivering value, and let these tools accelerate your progress. The sophistication can always come later—when your product, team, and users are ready for it.

Vibe Coding is about Best Practices

When we talk about being successful with AI-assisted coding, I think it’s easy to focus too much on the “magic” of the AI and forget the fundamentals. But success doesn’t come from just pressing generate. It comes from the same balance we’ve always needed in software: good ideas, the right technologies, and solid practices.

The first part is the idea itself. It’s tempting to throw every half-baked thought at an AI and hope it will shape it into a masterpiece. But that usually leads to messy, disconnected code. A better approach is to move step by step, layering features carefully so that modules fit together naturally. Just like in traditional coding, structure and pacing matter.
The second part is the technology. AI can write React code, for example, but it won’t decide for you whether state should sit inside a component, live in a shared context, or be managed through a dedicated state manager. Understanding those building blocks is what keeps a project performant, secure, and scalable. Without that knowledge, it’s very easy to end up with something fragile.

And then there are best practices. File sizes grow too large if you never pause to split them. APIs can quickly become unmaintainable if you don’t validate authentication properly. Test coverage, error handling, naming conventions — these are the details that separate “something that runs” from “something that lasts.”

There are other pieces too: version control discipline, clear documentation, and thinking about deployment early rather than as an afterthought. All of these add up. AI coding helps us move faster, but it doesn’t replace the craft, it amplifies it. And when we respect both the creativity of the idea and the discipline of the practice, that’s when we start to see real success.

Design Patterns in React

Introduction

I am a software engineer. I love coding, and I know how to code—I’m actually quite good at it. I know how to code and I use most design patterns automatically, but I honestly do not know what they are called (with a few exceptions).

Here are some common design patterns explained with React code:

Singleton Pattern

Ensures a class has only one instance.

Example in React: A global state management instance (e.g., Redux store, Context API provider).

const StoreSingleton = (function () {
  let instance;
  function createInstance() {
    return { user: null, theme: "dark" };
  }
  return {
    getInstance: function () {
      if (!instance) {
        instance = createInstance();
      }
      return instance;
    },
  };
})();

const store = StoreSingleton.getInstance();

Factory Pattern

Creates objects without specifying the class.

Example in React: Dynamic component rendering based on props.

const ButtonFactory = ({ type, label }) => {
  const components = {
    primary: (label) => <button className="btn btn-primary">{label}</button>,
    secondary: (label) => <button className="btn btn-secondary">{label}</button>,
  };
  return components[type] ? components[type](label) : <button>{label}</button>;
};

// Usage
<ButtonFactory type="primary" label="Click Me" />;

Observer Pattern

Notifies dependent objects when one changes.

Example in React: Event listeners, pub-sub mechanism, React Context API.

import { useState, useEffect } from "react";

const eventListeners = new Set();

const subscribe = (listener) => eventListeners.add(listener);
const unsubscribe = (listener) => eventListeners.delete(listener);
const notifyAll = (data) => eventListeners.forEach((listener) => listener(data));

const useNotification = () => {
  const [message, setMessage] = useState(null);
  useEffect(() => {
    const listener = (data) => setMessage(data);
    subscribe(listener);
    return () => unsubscribe(listener);
  }, []);
  return message;
};

// Usage
const NotificationDisplay = () => {
  const message = useNotification();
  return message ? <p>{message}</p> : null;
};

Decorator Pattern

Dynamically adds features without modifying core code.

Example in React: Higher-Order Components (HOCs) & Custom Hooks.

const withLogging = (WrappedComponent) => {
  return (props) => {
    console.log("Component Rendered:", WrappedComponent.name);
    return <WrappedComponent {...props} />;
  };
};

const Button = (props) => <button {...props}>{props.label}</button>;

const LoggedButton = withLogging(Button);

// Usage
<LoggedButton label="Click Me" />;

Adapter Pattern

Converts incompatible interfaces for seamless interaction.

Example in React: Converting an API response to match UI needs.

const legacyAPIResponse = { fname: "John", lname: "Doe" };

const adaptUser = (data) => ({
  firstName: data.fname,
  lastName: data.lname,
});

const UserProfile = ({ user }) => {
  const adaptedUser = adaptUser(user);
  return <p>{adaptedUser.firstName} {adaptedUser.lastName}</p>;
};

// Usage
<UserProfile user={legacyAPIResponse} />;

Strategy Pattern

Encapsulates algorithms for flexible swapping.

Example in React: Using different sorting algorithms in a table component.

const strategies = {
  ascending: (arr) => [...arr].sort(),
  descending: (arr) => [...arr].sort().reverse(),
};

const SortableList = ({ items, strategy }) => {
  const sortedItems = strategies[strategy](items);
  return <ul>{sortedItems.map((item) => <li key={item}>{item}</li>)}</ul>;
};

// Usage
<SortableList items={["Banana", "Apple", "Cherry"]} strategy="ascending" />;

Command Pattern

Wraps requests as objects to allow undo/redo.

Example in React: Undo/redo for a text editor.

import { useState } from "react";

const useCommand = () => {
  const [history, setHistory] = useState([]);
  const [index, setIndex] = useState(-1);

  const execute = (command) => {
    const newHistory = history.slice(0, index + 1);
    newHistory.push(command);
    setHistory(newHistory);
    setIndex(newHistory.length - 1);
    return command.execute();
  };

  const undo = () => {
    if (index >= 0) {
      const command = history[index];
      setIndex(index - 1);
      return command.undo();
    }
  };

  return { execute, undo };
};

Composite Pattern

Treats objects and compositions the same way.

Example in React: Recursive component rendering.

const Comment = ({ text, replies }) => (
  <div>
    <p>{text}</p>
    {replies && replies.map((reply, i) => <Comment key={i} {...reply} />)}
  </div>
);

Conclusion

I use most of these design patterns daily—but I don’t know what they are called. I know I don’t like a services pattern (oh sorry, the Facade pattern) as I like keeping all my fetching code together in my Context. Though, to be honest, I am starting to wonder why.

Why Are We Still Using CVs in 2025? AI Can Do Better

In a world where AI can write essays, generate code, and even hold conversations, why am I still manually sending my CV to apply for jobs? The traditional recruitment process—where a job is posted, recruiters screen candidates, and job seekers send applications—feels outdated and inefficient.

Let’s be honest: companies already struggle with an overwhelming number of applications, and job seekers waste hours tweaking resumes and searching for roles that match their skills. But what if AI could eliminate this manual back-and-forth entirely?

The AI-Powered Hiring Solution

Imagine a platform where companies upload a job description, and AI automatically extracts key requirements—skills, experience, and qualifications. On the other side, candidates upload their CVs, and AI instantly matches them to relevant job postings. Instead of job seekers manually searching through thousands of ads, AI alerts recruiters when a highly matched candidate appears.

Why This is Better for Everyone

For Job Seekers: No more hours spent on job boards. You simply upload your details, and AI ensures your profile gets seen by the right employers.

For Recruiters: Instead of filtering through endless applications, AI presents only the most relevant candidates, speeding up hiring decisions.

For Companies: A streamlined, data-driven hiring process that reduces hiring costs and ensures better role-fit candidates.

Is This a New SaaS Opportunity?

The more I think about it, the more it feels like AI is ready to disrupt the hiring process entirely. Instead of companies and candidates spending countless hours searching for each other, why not let AI handle the matchmaking?

This could be built as a SaaS platform that integrates with job boards and applicant tracking systems, making hiring faster, smarter, and more efficient.

The question is—who’s already working on this? And if no one has done it right, maybe it’s time to build it.

My frustrations with my AI Buddies

Using AI code generation tools can feel like having a supercharged assistant—they can quickly draft code snippets, suggest solutions, and even build entire components. But as helpful as they are, I’ve found some frustrating limitations that often slow me down rather than speed me up.

One of the biggest issues I run into is that AI tools can’t remember my personal coding style. Every developer has their own way of structuring code, naming variables, and organizing logic. I might prefer concise functions or certain design patterns, but AI generators typically offer generic solutions that don’t align with how I like to write code. This means I often spend extra time rewriting or tweaking the output to match my style, which defeats the purpose of using these tools for efficiency.

Another pain point is that AI tools don’t remember which frameworks or CSS libraries I’m using. If I’ve chosen React with Tailwind CSS for a project, the AI might still suggest solutions using plain CSS or even other frameworks entirely. It’s frustrating to constantly correct the suggestions, reminding the tool that I’ve already made specific technology choices. This disconnect slows down development and forces me to double-check everything for compatibility.

I also like using the Context API in React, particularly putting fetch calls directly in the Provider for better encapsulation and centralized data management. However, AI often suggests creating standalone service files instead, which doesn’t align with my approach. This mismatch forces me to rewrite the AI-generated code to fit my preferred architecture.

Then there’s the issue of file organization. I like to use a feature-based folder structure, keeping related components, hooks, and utilities together. But AI tools have no sense of where files should go. They’ll suggest creating a new file but won’t place it in the right folder or follow my project’s organization pattern. This leads to a messy file structure that I have to clean up manually, making the process more cumbersome.

Overall, while AI code generation has a lot of potential, it lacks the memory and context needed to be truly helpful. Without the ability to learn and adapt to my style, tools, and project structure, it often creates more work than it saves. Until these tools can bridge that gap, they’ll remain more of a novelty than a reliable development partner.

My AI Buddies

Generative AI has completely changed how I approach software development. From writing snippets of code to automating repetitive tasks, these AI tools have become my go-to partners in the coding process. Today, I want to share how three of my favorite AI agents—GitHub CoPilot, Cline, and Bolt—have enhanced my workflow.

My Experience with GitHub CoPilot in VS Code

GitHub CoPilot, developed by GitHub and OpenAI, has been a game-changer for me. Integrated seamlessly into Visual Studio Code, it feels like having a helpful coding buddy suggesting lines of code and even entire functions as I type. Whether I’m working with PHP or React, CoPilot provides intelligent, context-aware recommendations that save me time and help me break through coding blocks. It’s especially handy for automating boilerplate code and exploring new frameworks or libraries without needing to constantly check documentation.

How Cline in VS Code Simplifies My Workflow

Cline is another AI-powered tool that has made coding more intuitive for me. While CoPilot helps by suggesting code, Cline enhances my development workflow by offering smarter interactions directly within VS Code. I can ask Cline to do something in a code file using English, and it can run complex terminal commands, navigate my file system, and automate build processes. This has been a huge help in bridging the gap between coding and command-line tasks, allowing me to stay focused on building instead of getting stuck on syntax-heavy commands.

Why I Love Using Bolt.new and Bolt.diy

Bolt has been a fantastic addition to my toolkit, with its two products: Bolt.new and Bolt.diy. Bolt is all about rapid prototyping. I can have an idea for a web app and turn it into a working prototype in minutes. It generates functional codebases, user interfaces, and basic logic structures, Bolt.diy van even import an existing codebase and I can tell it to add features or make modifications. It strikes the perfect balance between automation and creative control for me.

Bringing It All Together

Each of these AI tools brings something unique to my workflow:

  • CoPilot boosts my productivity by suggesting relevant code in real-time.
  • Cline streamlines command-line tasks, making my development process smoother.
  • Bolt helps me accelerate prototyping and custom development with smart automation.

By integrating these tools into my daily work, I’ve been able to cut down on development time, dive into new technologies more easily, and focus on solving complex problems instead of getting stuck in routine tasks. Whether you’re a seasoned developer or just starting out, these generative AI agents could become your new favorite coding companions.

I truly believe the future of coding is more collaborative, with AI working alongside us to unlock greater creativity and efficiency. It’s an exciting time to be part of the software development world!

Have you tried any of these tools yet? I’d love to hear how they’re working for you!

Impact Of Ai On Software Engineering

How Generative AI is Changing Software Engineering

Generative AI is making big waves in software engineering, changing how we create, manage, and improve code. From tools that handle entire codebases to smarter ways of working, AI is becoming a key player in the field. Let’s dive into three big ways it’s transforming things: AI-managed codebases, AI-driven best practices, and the boost in productivity once developers get the hang of it.

AI-Managed Codebases: Letting AI Handle the Heavy Lifting

I can hardly contain my excitement about the rise of AI-managed codebases! The idea of tools like Bolt.new taking care of entire systems feels like stepping into a future we’ve only dreamed about. These platforms are doing things we once thought impossible, like:

  • Building apps from scratch based on what users need.
  • Keeping code optimized for speed, security, and scalability.
  • Updating old code and fixing issues without needing a person to step in.

This is so much more than just a technical improvement; it’s a complete shift in how we think about development. Imagine having an AI partner that keeps your code clean, identifies and fixes bugs before they cause trouble, and always ensures everything is up-to-date. It’s freeing us from the tedium of maintenance and giving us more time to focus on creative and meaningful challenges. The possibilities here are limitless, and I can’t wait to see how far we can push this technology!

AI Best Practices: Developers Still Call the Shots

As incredible as AI is, it’s important to remember that developers are still the ones in charge. AI tools might be smart, but they need our guidance to make sure they’re doing the right thing. These tools are fantastic at spotting patterns and coming up with solutions, but we’re the ones who ensure:

  • The code matches the project’s goals and user needs.
  • Ethical issues like fairness, privacy, and security are addressed.
  • The solutions work in real-world scenarios.

It’s like having an exceptionally talented assistant who can handle the heavy lifting, but we’re still the directors of the project. Developers bring creativity, vision, and judgment to the table, and that’s something AI can’t replicate. This partnership allows us to achieve more than ever before while staying true to what’s important.

A Productivity Boost: Unlocking New Potential

The speed and efficiency generative AI brings to the table are nothing short of thrilling. For developers who learn how to use these tools, the productivity gains are incredible. AI can:

  • Cut down the time spent fixing bugs and testing.
  • Make onboarding new team members a breeze with automatically generated documentation.
  • Help developers try out new ideas quickly by handling repetitive setup tasks.

I’m amazed every time I see how much faster projects move when AI is involved. Tasks that used to take days can now be done in hours, giving teams the freedom to focus on what really matters: innovation and problem-solving. This is the kind of transformation that changes not just projects but entire industries.

But to fully embrace this potential, developers need to:

  • Learn how to give clear instructions to AI.
  • Carefully review AI-generated code to make sure it fits the project’s needs.
  • Keep up with the latest advancements in AI tools and techniques.

The Future of Software Engineering

Generative AI isn’t just another tool; it’s opening the door to a whole new way of thinking about software engineering. It’s letting us dream bigger, move faster, and achieve more than we ever thought possible. But even with all this power, the human element remains essential. Developers are still the ones steering the ship, setting the goals, and making sure we stay on course.

The future of software engineering is incredibly exciting. We’re moving toward a world where developers spend less time on routine tasks and more time shaping strategies, solving problems, and creating bold new ideas. Generative AI isn’t here to replace us; it’s here to amplify what we can do. I’m so excited to see how this technology will evolve and to be part of this journey into a new era of innovation.