The No-Code Challenge: Building a CMS with Copilot and Node.js

In January, copilot “chat commands” became generally available. Now we have access to “/explain”, “/fix”, “/terminal”, and “/test” commands besides the general chat with Copilot. Is it possible to develop a project using copilot, without writing a single line of code? This is the question that I was toying with for the last 4-5 weeks. So I went on and gave it a try.

Here’s the shortest answer: No! But that does not do the justice to the whole story. It is possible to write ALMOST ZERO lines of code.

The Experiment

This is the project I defined for myself: I want to create a Blog using Nodejs, Typescript, expressjs, postgresql, Objectionjs, mochajs and chai. I wanted to make it a bit more complicated and out of the ordinary open source project codebase structure to see how Copilot behaves. As a result, I decided to use Robert C. Martin’s Clean Architecture.

The end goal was writing 0 lines of code. As someone might consider commands as code also, I tried to even create the project folder using Copilot, sacrificing some time to figure out if it’s possible at all. To my surprise it’s possible to setup the whole project completely using prompts! Prompt: Create a folder named “copilot-no-code-experiment”. As a result it returned an “mkdir” command.

If you have given Copilot a try, you probably already know that with each code block, we get 4 options:

  • Copy
  • Insert at Cursor
  • Insert into Terminal
  • Insert into New File

Copilot does not automatically execute the command in terminal like some agents do. However, “Insert into Terminal + Enter” is still no-code. The advantage is that we can make sure we actually want to execute the command.

In the following gallery you can find screenshots of some of the prompts that I used to set up the project, add the dependencies, create files and folders, add configuration, and finally, implement some code.












Final Results

Overall it produces exceptional results and it is possible to write almost no-code, if you want to. I say “if you want to” because, copilot is better off as what its name suggests, “a copilot”. In many cases, it is much faster to write code rather than waiting for Copilot to come up with the solution, reviewing it, and then applying it, or, applying the code, reviewing, and then modifying it.

That being said, some issues that I faced are as follows:

  • As context got bigger, and spread over more files, copilot could not consider the whole picture. Rather, it would concentrate on the current prompt.
  • I found out that it’s very important to think about things in a step by step manner. For instance, “declaring an interface in advance” instead of “asking for the code that also includes the interface” improves the results
  • “Inline copilot chat” opens with a new context and does not consider the current context from the Chat interface. So, it is always better to select the code first, and ask about the selected code instead.
  • “/explain” explains and offers a solution! Obviously, that’s what the name suggests. The problem is that I couldn’t use the solution directly. Either I should’ve written another prompt for Copilot to come up with a code solution or fixed the code myself. The latter was much faster in most cases.
  • Generating more complicated code takes more accurate and longer prompts to generate correct results. It makes much more sense to start writing the code, add comments and use inline code completion to get to the final solution.
  • There’s a button that generates commit message based on the staged changes, but the message is trivial and not self-explanatory.
  • Some typescript errors.

By experience, copilot does way better when dealing with clean code compared to working in stale codebase. With this experiment, I see about 83% increase in performance – let’s say something in the range of 70% to 85%. With this amount of performance improvement, I do not see the reason why we shouldn’t switch from “If it ain’t broke, don’t fix it” to behaving with code as it is “replaceable, one-time-use parts”. Obviously, I do not mean it in a reckless, big-bang change kind of way. What I mean is, with these improvements, it makes more sense to follow Martin Fowler’s refactoring advices to refactor code, and throw away parts rather than maintaining them by tweaks here and there. Happy coding!

Leave a Reply

Your email address will not be published. Required fields are marked *