Have you ever wonder how to make your repository more readable and lower the entry-level for new joiners in your team? How to decrease the time needed for onboarding new people and limit questions asked by external people who want to use your solutions or contribute to them? Or how to make it easier just for yourself to recreate the developing ecosystem after reimaging/changing your laptop? Recently, I analyzed many repositories (private and open source) and discovered that some of them are much more friendly to new joiners than others. What makes them so special? Several small things you can implement in your project with really low time and effort costs. Below, you can find 6 — in my opinion — the most useful tips to improve your code repository just today.
Probably that point is obvious for many of you. But at the same time it’s so important I can’t miss that point in my article. Readme is a file in the root of your git project where you should describe the most essential info about it. What kind of information should be placed there? Definitely, the main purpose of the repository — why it was created, what is the purpose of it, who is responsible for that project. Personally, I am also a huge fan of adding a section with specific info on how to install, develop, and deploy code in the repo. Yeah, I know that majority of times in the beginning it will be sth like:
git clone <repository-address> npm install npm run start
but remember that our projects are not always so simple! When your repository is growing and you start using subrepositories, monorepos, micro-frontends, complex dependencies, dockers, or advanced logic to deploy, the first run of the app may become a nightmare for a new joiner — especially if that’s a person with a different technical background than yours. Adding specific info in the readme about that processes (especially formed as a chain of commands to call in a terminal) not only lowers an entry-level to contribute to your repository but also decreases the time needed for onboarding a new person or answering questions from other teams in your company. And it should take less than 5 minutes (in the most basic way you can just copy-paste commands you use each time to start a project from terminal to readme file). Completely, worth it — don’t you think? If you need some inspiration, check e.g. github-changelog-generator — really nice example of a good readme file!
Example of scripts section in package.json
Package.json is the next, super-essential file in almost every JS/typescript based project. It’s a file where you can define the version, name, and dependencies for the project. Thanks to that you can just call
npm install or
yarn to install all dependencies required for your project (in the correct versions!). As a frontend developer, you probably use that all the time. But there is also a section which is, unfortunately, less popular — and I’m writing here about scripts. It’s nothing more but a key-value list where you can define your own names for some commands. When you are using e.g. Angular, some of them will be generated during the init of the project — like
test. Although, I strongly encourage you to add your custom ones. If you have a special command to start unit tests, add it to scripts. If you are using some tools to check code styling, add it in that section. If you are using docker, add a script to run it locally there as well. To be honest, almost every command you use in the terminal should be placed here. Benefits are at least two: all useful commands are documented, so a new person in the team can easily check what actions are possible and you receive short, easy to remember, and type alias to call in the terminal.
Example of swagger file from the official page — swagger.io
Defining and documenting API can be a challenging task. Fortunately, we have something called a swagger — a set of open-source tools built around the OpenAPI Specification that can help you design, build, document, and consume REST APIs. Thanks to them, you can create a webpage with all endpoints defined with their query params, body params, schemas of the expected response, etc. What’s more, you can also test calls directly from that page. You don’t have to dig into source code to understand APIs. And using or changing your service is much easier, don’t you think? Let’s say some words about how to implement them in our project lifecycles. There are two main approaches to defining swagger: as a contract before development or autogenerating that based on created service code. Both of them have their own cons and pros. Defining swagger file as an API contract before touching a code allows us to parallel work between different teams dependent on that service and create typescript types based on that (useful when your backend is written in Node and you want to share types between repositories). But also requires more effort— all endpoints have to be defined manually and some later changes in service may be missed (developers have to remember about changes in two places). On the other hand, you can use annotations to generating swagger files automatically, based on source code — using libraries available for almost all languages. Thanks to that you don’t have to worry about updating documentation, but all consumers have to wait for a working version of API to start their work and some comments. Nevertheless, no matter which option is better in your case, using swagger definitely can take your API documentation to a completely new level.
Note: Very often your swagger contract will be defined in a separate repository. If so, remember to add a swagger link to the Readme file in the main project. Be nice to others, don’t make them search for that (or worse, miss knowledge it exists)!
Probably, the most surprising point here. But well-written tests may be a much better source of knowledge about the repository than traditional documentation. Docs can lie — code never! When I have a problem with understanding some part of a system, I’m always taking a look at a unit or functional tests for that. It simple way to check which use cases were predicted by the code author and how it should work. And good tests increase also the quality of your project. Double win!
A little thing, but makes me happy! A .nvmrc file allows you to define and document the node version used in the project. It’s only one line, but whoever was struggling with a broken installation and had no clue what’s wrong, will appreciate it. Especially, because errors printed in the terminal are not suggesting the wrong node version at all! Using .nvmrc it’s enough to call
nvm use before
npm install and the correct node version will be used. So small, so nice!
Please, don’t waste your and others’ time on manually checking indents or formatting rules. And write them down instead of saying “We always do it that way” during code review. I know that “spaces vs tabs” is a holy war in programming but you have to decide that battle in your team. Add tools like eslint or prettier and set of rules to your repository. Automate that checks. Test your formatting on pre-commit or creating merge requests. Define rules in a transparent way — not only in your head. And let a computer do that simple checks — it is the best at that!
Of course, the list presented above is not exhausted and there are many more ways to improve your codebase to make it more new-joiners friendly. But all tips presented by me are easy to implements and — in my personal opinion — have a huge impact on people who want to start work with your repository. I hope, you will find that article useful! Happy coding!