Inspiration
A few years back, me and my cousin came up with a business idea for designing and printing custom t-shirts. I started working on a tool that would allow a user to design their own t-shirts. The idea was basically to allow users design their own tees and the design would be printed on to a plain tee and delivered to the user.
Choosing the stack
Well, from the requirements, we could need to provide some kind of user interface to the user on which they would be able to design their tees. So, naturally we opted for a web-based solution as it would be more accessible. There were two options for rendering the designs, ie: using html5 canvas or using webGL. I had previously worked on a project that used webgl, but I took the easy approach with canvas as there is this great library called fabricjs
which initially seemed like it could fit all our requirements perfectly. So, I went with fabricjs.
Now, since the design was just a single step of the whole workflow, I decided to use a modern frontend framework for my stack. Back then, I was working on React with another project so naturally I opted for Nextjs as I loved working with React and Nextjs.
Challenges
Fabricjs covers a lot of things. To create a user interface able to manage all these aspects was a major challenge for this project. Although we currently have not covered everything that fabricjs has to offer, we have managed to create a framework that allows us to control most of the properties a fabric object has to offer. From fonts, colors, shadows to height width and scaling factors, many other things provided by fabricjs as an API for modifying a fabric object now has corresponding UI mutator elements which modify the fabric object directly from the user interface.
For this, we opted to create two types of mutators, an ObjectMutator
and other PropertyMutator
. The ObjectMutator
is just a collection of property mutators that can mutate the properties of a given fabric object. For instance, a fabric.Rect
object has different properties than a fabric.Circle
. To address this, we created two Object mutators namely CircleMutator
and PolygonMutator
.
Each mutator has its set of PropertyMutator
such as StringMutator
, NumberMutator
, ColorMutator
etc that correspond to the type of the value that the object property holds. This results in NumberMutator
being able to mutate properties such as height, width, scaling, border, strokeWidth etc and ColorMutator
being able to mutate properties such as strokeColor, fillColor, shadowColor and so on.
The other thing that was somewhat challenging is to be able to embed custom fonts into SVG images that could be exported from the app.
We used google fonts api to load custom fonts into the app, but since an SVG image could be opened regardless of it being in the app or not, we needed to find a solution to integrate fonts into SVG. Interestingly enough, SVGs are just XML documents that can have the <style>
tag. So, we are considering developing a solution that would allow us to embed the font face being used in the SVG image directly into the image itself. As of now, custom fonts on the SVG images do not work unless the font is already installed on the host machine.
Experimentation
While I was learning about monorepos, I tried to integrate the nextjs application into a monorepo with express as backend for our application. This was my firstt time using a monorepo using Nx and I didn't feel any advantage of using a monorepo as just a few components were shared across frontend and backend and the overhead and complexity of using a monorepo were far greater than the amount of duplication our apps shared. Hence, I again ejected the monorepo and now the applications are in separate repositories.
Further development
I have published just the Editor part of the application as open source in github. There are still a lot of things to be done, bugs to be fixed and we also have some integration tasks on the pipeline.