One distinction among engineering projects that I have begun to make is to ask if their outcome will be tools or frameworks.

Tools are independent, light-weight, loosely inter-related and versatile items. The UNIX command line utilities (cat, grep, awk, sed, find, etc.) are tools. Tools give you an enormous amount of freedom. You can compose them together in any order as many times as you wish to accomplish complex things. In carpentry saws and hammers are the tools, in cooking its pots and pans, in programming it's libraries like STL, Boost and Folly.

The other kind of thing we build often are frameworks. Frameworks bind and constrain. A framework allows you to do things, but it's equally important goal is to limit the things you can do, in the hope that they make you do the right things. Frameworks force you to follow patterns, and if you find yourself in a situation where that pattern doesn't work for you it can be quite painful to work around the framework's limitations.

An example of a framework would be one of the many web frameworks that are popular these days – Ruby on Rails, Django, or  front end development frameworks like React and Angular.js. If you start using one of these frameworks they really bind you to a certain way of doing things. If  you use Django, you'd better do MVC the way they like it. React will encourage you to do state management in a single way, and to do it any other way is extremely difficult. There is of course some configurability – Django will let you choose between several different databases and templating languages for example. But try to do anything unusual and it can be a struggle.

It isn't bad that frameworks restrict developer freedom – in fact, it is a wonderful thing. Restricting the things you can do means there are fewer things that can be done incorrectly. Building simple websites and managing how the rendering of data is separated from fetching of data is now understood well enough that the vast majority of patterns can be compiled into a framework like Django.

But the thing to always remember is this: when you are building something new, it is almost always better to build tools rather than frameworks. It is difficult to anticipate all the possible usage patterns in a problem space when you are even modestly unfamiliar with it, so it's unlikely that the  framework that you build will constrain you in the right ways. Often it will stop you from doing things you want, which will make you hack around the framework and defeat its purpose.

So start by building tools, rather than frameworks. Over time you will understand the usage patterns better, and eventually opportunities for wiring tools together into a framework will emerge. Frameworks are best grown organically.