DEV Community

Cover image for 1 week with GitHub Copilot: Building an app using only Copilot
Matt Angelosanto for LogRocket

Posted on • Originally published at blog.logrocket.com

1 week with GitHub Copilot: Building an app using only Copilot

Written by Evgeny Klimenchenko ✏️

GitHub Copilot is the newest tool developed by GitHub to autocomplete code with the help of OpenAI.

Copilot generates smart code suggestions with context, such as docstrings, code comments, function names, or even file names. It then uses all this information to suggest code snippets that developers can easily accept by pressing the Tab key on a keyboard.

It understands Python, JavaScript, TypeScript, Ruby, and Go, as well as dozens of other languages because it’s “trained on billions of lines of public code,” per the Copilot website. And while it's currently still in its limited technical preview, those interested can sign up to join a waitlist to try it out.

In this article, we’ll explore Copilot’s main functionalities, how to build a simple application using only Copilot, and its pros and cons.

Copilot’s main features

Copilot’s main feature is its autocomplete function. When typing a function description, for example, Copilot completes the whole function before a user finishes. While this autocomplete is similar to other general autocomplete functionalities, Copilot goes a step beyond.

When continuing to write code and adding more comments, Copilot begins to understand the whole context of the code through its AI capabilities. With the context, it autocompletes comments mid-sentence.

For example, by adding a function, it generates a whole comment and a function; in this case, it figured out the last function should be a multiply function, as seen below.

Adding A First Function And Comment To See How Copilot Responds

Another cool feature of Copilot is the ability to see 10 full-page suggestions, instead of a single one-liner suggestion, and choosing which suits the code best.

To do that, press ^ + Return on a Mac keyboard or Ctrl + Enter on Windows to open a list of suggestions, as shown below.

Opening Copilot's Suggestions

Can you build an application with only GitHub Copilot?

With Copilot’s capabilities, I wanted to challenge myself to build a small application using only Copilot. For this challenge, I wanted to create a simple random quote application that also displays the sentiment of the quote.

To do this, I had a few rules to follow to see how much benefit I could receive from Copilot.

First, I could not search the internet if I encountered a problem, including using Stack Overflow or documentation. This let me see whether it was possible to solely rely on Copilot's suggestions to create working code.

The second rule was that I could not write any new code myself. I could, however, write comments, variables, names, and function names to trigger Copilot’s suggestions. Similarly, I could also make small edits to the suggested code.

And finally, I could trigger the list of Copilot suggestions and accept one, since this is a built-in feature.

Setting up the project

I chose Next.js and React to build this project since they are the tools I am most familiar with to help me better evaluate Copilot’s performance.

Since React makes it fairly painless for developers to build applications, and I wanted to see how Copilot would manage React components.

For Next.js, it provides a good starting point where I didn’t need to spend a lot of time setting everything up, and it has built-in back-end functions, making it useful to call different API endpoints without triggering CORS errors.

While Next.js might seem too powerful for this small project, there’s no need to install other dependencies beforehand and its integrated, easy-to-use API functions make it a good choice for this challenge.

Developing the API endpoints

Starting with developing API endpoints, I wanted a quote generator that returns a random quote on a GET request and a sentiment analysis endpoint. The sentiment analysis endpoint needed to receive a string as a query parameter and return a sentiment.

Since I didn't know what format the return value would be, I let Copilot write it and see what it could return.

/api/get_quote GET request endpoint

To create two endpoints using Next.js, I created two files in the api folder: get_quote.js and get_sentiment.js. Next.js could then create these endpoints based on the file names. All that was left is to define was the handler functions inside those files, and I let Copilot do that for me.

For the get_quote endpoint, I wrote a comment and chose a good suggestion:

// get random quote from random API
Enter fullscreen mode Exit fullscreen mode

Clicking the comment, Copilot responds with a list of different options to pick from.

Writing Command To Trigger Copilot To Get A Random Quote From An API

The suggestion I selected was the following:

const getQuote = async () => {
    const response = await fetch('https://quotes.rest/qod.json')
    const quote = await response.json()
    return quote.contents.quotes[0].quote
}
Enter fullscreen mode Exit fullscreen mode

This suggestion worked. Almost all of the other suggestions that I checked were either broken or required an API key that I didn’t have. This could be because Copilot was trained on open source GitHub code, and some endpoints might be outdated already, which can be frustrating.

Also, this endpoint returns the quote of the day, which means for every call, I receive the same quote for the current day, which was not what I was expecting. Instead, for every endpoint call, I wanted to receive a different random quote.

For the second part of this endpoint, I needed to create a handler for the endpoint that calls the function Copilot already generated. The handler is the function that Next.js calls when the client requests the endpoint.

To do this, I declared the function with its name to see whether Copilot would suggest the correct implementation or not.

Declaring A Function And Its Name To See If Copilot Adds Correct Implementation

And Copilot surprised me again. Everything seemed correct.

First, it called the getQuote function and returned the quote received from the web service. Then, it saved the quote to the constant and returned JSON to the client with the retrieved quote. The only thing I had to add was .status(200) to send the 200 status code to the client.

/api/get_sentiment GET request endpoint

For the get_sentiment function, I chose Copilot’s suggestion and didn’t have to change anything.

I input the following:

// determine if the text is positive or negative
Enter fullscreen mode Exit fullscreen mode

Then, Copilot suggested the following code, which I used:

async function getSentiment(text) {
    const response = await fetch(`http://text-processing.com/api/sentiment/`, {
        method: "POST",
        body: `text=${text}`,
        headers: {
            "Content-Type": "application/x-www-form-urlencoded",
        },
    })
    const json = await response.json()
    return json.label
}
Enter fullscreen mode Exit fullscreen mode

However, for the endpoint part, I had to add .status(200), similar to the get_quote endpoint. Here is what I provided to Copilot:

export default async function handler(req
Enter fullscreen mode Exit fullscreen mode

And then, Copilot suggested the following, which I selected:

export default async function handler(req, res) {
    const sentiment = await getSentiment(req.query.text)
    res.json({ sentiment })
}
Enter fullscreen mode Exit fullscreen mode

Copilot managed to provide us with a working solution again, suggesting the right handler and calculating what the get_sentiment handle function needed to return. This suggestion looks similar to the one we had previously.

Let's see how Copilot handled React component generation next.

React components

For the frontend, I needed a couple of specified React components and a React controller component with a button. The two specified components needed to display text: one for quote text and another for sentiment text.

Let's see how Copilot handled creating these React components.

QuoteTextBox

I began with the QuoteTextBox component that would showcase a simple quote; I added the following comment to see what Copilot would suggest:

// React component to show a quote inside a div

const
Enter fullscreen mode Exit fullscreen mode

Copilot suggested a simple function component, which I did not have to change at all.

const QuoteTextBox = (props) => {
  const { quote } = props
  return (
    <div className="quote-text-box">
      <p>{quote}</p>
    </div>
  )
}

export default QuoteTextBox
Enter fullscreen mode Exit fullscreen mode

Copilot Suggests A Simple Function Component

SentimentTextBox

To build the sentiment text box, I added the following comment:

// React component to show sentiment text inside a div

const
Enter fullscreen mode Exit fullscreen mode

For this text box, it was a bit trickier to find the right suggestions, and I had to scroll through most of them until I found one that would work with my code:

const SentimentTextBox = (props) => {
  // Get sentiment text from props
  const sentimentText = props.sentimentText

  // Return component
  return (
    <div className="sentiment-text-box">
      {sentimentText}
    </div>
  )
}

// Export component
export default SentimentTextBox
Enter fullscreen mode Exit fullscreen mode

It’s important to clearly understand what to expect from Copilot because it is only a tool, and developers can’t just rely on the first suggestion it gives.

SentimentTextBox Suggestion From Copilot

I still needed to come back to this component to map what the API returns to readable text. For example, if the web service returns neg, I needed to map it to Negative.

Controller component with button

I also needed a controller component to manage all the logic. The first two React components I created just received data and rendered it on-screen, but the controller component needed to manage the API calls.

I started by inputting the following:

// React component that uses QuiteTextBox and SentimentTextBox and APIs to show quotes and sentiment with a button to generate new quotes.

const
Enter fullscreen mode Exit fullscreen mode

Then, Copilot brought this suggestion:

const QuoteGenerator = ({quote, sentiment, onClick}) => {
  return (
    <div>
      <QuoteTextBox quote={quote} sentiment={sentiment} />
      <button onClick={onClick}>Generate New Quote</button>
      <SentimentTextBox sentiment={sentiment} />
    </div>
  )
}

export default QuoteGenerator
Enter fullscreen mode Exit fullscreen mode

The controller component suggested by Copilot appeared to be pretty basic; it lacked the API calls and didn’t use correct props for SentimentTextBox. However, Copilot did provide the correct structure, it just needed some tweaks to finish it.

Then, I just needed to add functions to the controller component. Instead of passing quote, sentiment, and onClick, I asked Copilot to generate them. I also needed some Hooks to store the sentiment and quote data received from calling the APIs.

For Hooks, Copilot figured out right away what I needed. To trigger the suggestion for the first Hook, I began typing a comment and Copilot suggested the correct Hook.

However, for the second Hook, I didn’t even need to type a comment. I accepted the first Hook suggestion, moved to the next line, and Copilot suggested the second Hook immediately.

Copilot Suggests Two Hooks

While the endpoints were correct, I still needed to make some changes to make them work. I had to ask very specifically what I wanted, otherwise, Copilot started suggesting different web services.

I wanted it to just call endpoints that were already created. Furthermore, I need to specifically call the getSentiment endpoint when I received a quote and map the sentiment to human-readable text.

Call And Map getSentiment Hook

And this is my final version after some minor changes from my side:

const QuoteGenerator = () => {
    // Hook to store text in state
    const [quoteText, setQuoteText] = React.useState('')
    const [sentimentText, setSentimentText] = React.useState('')

    // Function to get quotes from API /api/get-quote
    const getQuote = () => {
        fetch('/api/get-quote')
            .then(response => response.json())
            .then(json => {
                setQuoteText(json.quote)
                getSentiment(json.quote)
            })
    }

    // Function to get sentiment from API /api/get-sentiment\
    const getSentiment = (text) => {
        fetch('/api/get-sentiment?text=' + text)
            .then(response => response.json())
            .then(json => {
                setSentimentText(json.sentiment)
            })
    }

    // Function to be called when user clicks on button to generate new quote
    const onClick = () => {
        getQuote()
    }

    const mapSentimentToText = {
        'neg': 'Negative',
        'pos': 'Positive',
        'neutral': 'Neutral'
    }

    return (
        <div>
            <QuoteTextBox quote={quoteText} />
            <SentimentTextBox sentimentText={mapSentimentToText[sentimentText]} />
            <button onClick={onClick}>Generate New Quote</button>
        </div>
    )
}

export default QuoteGenerator
Enter fullscreen mode Exit fullscreen mode

The final application

After experimenting with my simple quote-generating app, I found that Copilot gives enough help to create a simple application.

Final Quote Generator App

I didn't have high expectations and initially thought I would need to change a lot of code to make the application work.

However, Copilot surprised me. In some places, it gave me nonsense suggestions, but in other places, the suggestions were so good that I can't believe Copilot made them.

Copilot pros and cons

To recap my experience with Copilot, I’ve compiled the pros and cons of working with it so you can decide whether Copilot is something you can use daily or not.

Copilot pros

The main advantage of using Copilot is that it provides autocomplete on steroids. As an autocomplete tool, I believe it is currently the best on the market; there is nothing even close to as useful as Copilot.

Copilot also shows developers multiple ways to solve different problems that may not be so obvious. When in need of a code snippet, the 10 suggestions functionality is great and can often be used in place of Stack Overflow for efficiency.

In all, Copilot is fun to use. For all the tech geeks, it is something new to play around with and it makes daily work a bit more interesting.

Copilot cons

While its functionality provides greater efficiency, users must remember it’s a tool, not a human developer replacement. Because Copilot is not a panacea, users cannot solely rely on it for all their code. Most of its suggestions require changes to fit specific needs.

And finally, I noticed Copilot was suggesting to use React classes for small components with little logic instead of functional components with Hooks. Because it was trained on openly available code on GitHub, Copilot might provide some depreciated suggestions for coding.

Conclusion

GitHub Copilot is not something that can just listen to a project idea and code everything for you. It is also not taking over developer jobs, either. But it is something that can make coding easier.

GitHub Copilot is good with small tasks; when you start asking it something more complex, you often get nonsense. Nevertheless, it is a very good tool for both beginner and experienced developers alike.


Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

Alt TextLogRocket Dashboard Free Trial Banner

LogRocket is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — start monitoring for free.

Top comments (0)