Always start with a code template
Tags: template, bunjs, npm, typescript
Published: 2024-01-28 07:32:42

# Templates make your life easier

Often, the hardest part of coding a new project is the beginning. That is until you learn how to use template! Then it turns out the beginning is just a piece of cake.

To accelerate the start of a new project, you can fill in all the default files that are always the same in every setup.

Of course, you could also just copy an existing copy, and go through the tedious work of remove project specific content, and also change all the package names to your new one.
The downside of doing that, aside from it being a pain in the bun, is that you'll surely end up with a bunch of junk that you forgot to cleanup.

In this post, I'll share my [Bun.js typescript template](https://github.com/jacklehamster/bun-template), which you are free to reuse, and explain what to look for if you want to create your own template.

# Creating a Github template

While you're welcome to use my template, you'd likely want to have your own, because every developer have their own development process. Personally, I like to have one bash command that builds and pushes everything to NPM, an example project using that library in the package itself, and I also like that each of my package have their own icon.

You can choose any repo to become a template. If for instance, you've been building a nice platform game, you can turn it into a template, so that your upcoming games can use it as a base.

For that, go to your Github repository's settings, and check "Template repository".

![Check Template repository in Github settings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w78h9kgd1q1r3tijzp9f.png)

That's it. Afterwards, you can create new repository using that template, and it will provide a starting point for those new repository.

![Make a new repository using a template](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jmytpt28pg35b0jivbmy.png)

## Difference with cloning

Note that creating a new repository out of a template is not the same as cloning it. As you make new changes to your repository, you're not expected to merge those back into the template. Likewise, if you update a template after having created a new repository out of it, that repository won't pick up the new template changes, unless you just copy over the code manually.

Creating a repository from a template is a bit like branching out, but you're not expected for the branch to merge back. Think of it as creating a blueprint for all your future projects, and that makes more sense.

# Now, let's talk about [bun-template](https://github.com/jacklehamster/bun-template)

I created the [bun-template](https://github.com/jacklehamster/bun-template) repository as a blueprint for creating TypeScript libraries that I will reuse for my games. For that I had a few specific goals in mind that defined how the template would be setup:

### It had to be Bun.

Since [Bun.js](https://bun.sh/) came out, I've been following it's development closely, and eventually decided that I would go ["All in on Bun"](https://dev.to/jacklehamster/im-going-all-in-on-bunjs-3ljk).

I was mainly impressed by the fact that Bun worked. It had far less problems than NPM when it came down to configure TypeScript and React, given that Bun supports them out of the box. Now it's a bit weird to say "I'm impress because it works". Imagine that you just bought a car from the dealership, and your first word of praise is: "Wow, I'm so impressed that it didn't break down as soon as I started the engine!". But with Node.js, I think we've reached a new low standard...

Anyway I digress. The other advantages that Bun.js gives is the speed of execution. I didn't initially care that Bun.js built so fast, because my JavaScript games run in the browser so they are not affected, but I realize now that fast building really does improve the development process drastically.

Because Bun.js finishes within a few milliseconds, I found that it costs nearly nothing to add "bun i" (equivalent to npm i) and running unit tests for every build. As a results, I've just made it part of my build process, which ensures that I didn't forget to build dependencies or I didn't cause a regression after any change I save. On top of that, I have a bunch of random scripts which really don't need to run on every build. But that said, given that they run so fast, I decided to run on every build anyway.

At the end, instead of several building steps, I just have one build.sh bash script that completes immediately.

### Update package name in package.json

When creating a new repository out of a template, the package.json still has name of the template repository ("bun-template"), and that has to be updated to the name of the new repository.

Since I'm super lazy, I created a script for that. It really needs to be run only once, but since it finishes so fast, I just let it run every build. This ensures I don't forget to execute it after creating a new repository out of my template.

You can find the script here:
[update-package.ts](https://github.com/jacklehamster/bun-template/blob/main/scripts/update-package.ts)

It updates:
- package name to match repository
- author name and email
- package description (using github's)
- repo url
- homepage url

### A demo for each library

One thing that annoys me a lot, is getting a library and not being able to see what it does until I write a bunch of code to use it, and/or configure a bunch of dependencies to make sure it doesn't break. So one of my requirement for each library is that they include a demo package, which will use the library itself to do something basic with it.

For that, I prepare a package in the "example" folder of each repository, which has its own package.json. That package.json uses the library itself, referencing it locally. That way, any new change made is reflected immediately, and can be tested locally within the example.

[package.json in example folder](https://github.com/jacklehamster/bun-template/blob/main/example/package.json):
```json
{
  "name": "example",
  ...
  "dependencies": {
    ...
    "bun-template": "file:.."
  }
}
```

### Generate a nice favicon

In each of my repository, I have a new [icon](https://github.com/jacklehamster/bun-template/blob/main/icon.png) that's more or less related to what the library does. I do use that icon in the README, but the main reason for having that icon is because it gets displayed in [SourceTree](https://www.sourcetreeapp.com/). With those icons, I can find at a glance the repository I need, in the list of repos.

![Repos with icons](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1q0xq3huywr6bvurhro1.png)

It also rather looks nice!

Since there's an "example" demo running in the browser for each library, it would be nice to have the favicon of each demo to match the repository icon.

Well, we do have that, thanks to this "build-icon" command that's part of the example's package.json.

```
"build-icon": "png-to-ico ../icon.png > favicon.ico"
```

I know many might think it's insignificant, but somehow this makes me happy, and making yourself happy is one way to improve your development experience.

### Publish to npm.js

One of my critical requirement for the bun-template is that it publishes all changes directly into [npm.js](https://www.npmjs.com/package/bun-template), so that I can import into other projects as dependencies.

To achieve that, I had to fix several issues, but finally I found the right series of steps so that it can be published to npm.js, and successfully imported by other typescript projects. Those involve:
- [Auto-commit](https://github.com/jacklehamster/bun-template/blob/main/commit-all.sh): The auto-commit script simply commits all pending changes under a generic message. Now, it's not very good engineering practice to have non-descriptive commit message. That said, this is only used when I forget to manually commit my changes with a nice message, or when I'm lazy. So yeah it happens very often. I figured, how often do I look back at my commit messages? Very rarely. So saving the time avoiding to do a manual commit is worth it. Perhaps in the future, I'll try to use an AI to read the changes made and attempt to understand them and produce a more descriptive message.

- [Make repo ssh](https://github.com/jacklehamster/bun-template/blob/main/make-repo-ssh.sh): To publish to npm.js, I use a tool called ["np"](https://www.npmjs.com/package/np). Despite the nice short name, the fact that it only has 2 letters make it difficult to search on the Internet, so I really had to dig to solve all its problems. One issue I found when using "np is that the repo has to be an "ssh" repo, not "https". Otherwise, it just gets stuck at the "publishing tags" phase. So using the script above, you just turn it into an "ssh" repo and be done with it!

- [Execute np](https://github.com/jacklehamster/bun-template/blob/main/np.sh): Finally, we execute "np" to publish to "npm.js".

I do have to press "Enter" a few times after executing the "np" command to confirm a few things. It could have been automatic by just executing `echo y | np patch`. That said, the prompt is not a big deal, and it's a chance to choose whether to increment the version as a patch (1.0.1), a minor (1.1.0) or major version (2.0.0).

# The value of template

Having a template isn't just a benefit for starting new projects. One of the goal for my game projects is to have them all split into small reusable components, which are part of their own repository, for the overachieving goal to have more modularized projects.

One barrier to that is the annoyance of creating a new repo filled with code every time. Having template takes away that barrier, so it contributes directly to better code architecture.

# References

You can find the Bun.js typescript template here:
[bun-template](https://github.com/jacklehamster/bun-template).

To use it, click [Use this template].