I’ve been working on rewriting Linkbucket for about three months now. A long time for such a simple project, but I had absolutely no idea on how to get started with Go web development. I was already used to the full-featured, friendly and ready-to-work environment that Laravel provides, with a well-defined architecture and model, and including everything you need, right out-of-the-box; but there’s no such thing as a full framework in the Go ecosystem: there are tons of micro-frameworks you can combine with other packages and components in order to create your fully personalized “framework” for your projects, that adapts to your needs. Creating your own framework from scratch gives you a lot of flexibility and freedom to decide how everything should work exactly; but it requires a lot more knowledge compared to using a full-featured framework, and puts in your hands a lot of important and sometimes risky decisions.
My initial idea was using Gin HTTP framework, with Gorm ORM, Extemplate template processor—which I discovered after reading this interesting article—, go-i18n for i18n and l10n and OAuth2 for API authentication. Designing the relational model was kinda tricky, as it had to support user-level tagging and OAuth2. Middleware and template data injection were not as simple as in Laravel. I was trying to replicate Laravel architecture! But I ended up getting really confused and gave up. After some weeks, I decided to try again from scratch, got confused again, and gave up for the next two months. I wrote some smaller projects with Go, including some simple web apps from other tutorials, a Telegram bot with Gin and Gorm for sensor alerts for an IoT project, and a simple “dockerized” Keybase bot. After a short unmotivational period, I stopped writing code. When I continued with programming, I got an inspiration boost and continued writing Linkbucket, this time following a simpler structure.
This new concept consisted on creating a headless RESTFul service using Echo, Gorm and go-jwt; and a separate React client that consumes the API. This time, designing a code structure for the service was way easier, after reading a lot and asking my friend @depado for guidance several times. It took me some time figuring out a standard error response body for validation and other errors. I wanted validation errors to be easy to parse from the client. Pagination was also important, and after trying to build my own small pagination engine, I ended up modifying gorm-paginator to return database errors and using my fork of the library.
Creating the client with React was really difficult for me, because I had never used it before, so I had to learn everything from scratch as I was building the client, and it resulted on a terrible spaghetti code that worked like shit, so I restructured everything using a Context and a service provider, which helped organizing the code a bit. I used React Bootstrap, react-js-pagination, react-tagsinput and axios. I added back-end pagination while I was working on the client. It is usable now, but it still works terribly, there’s a lot more to work.
I released this project as free software, under the GNU AGPLv3 license (the same as the original Linkbucket). There were still some details in order to make it production-ready—it’s still not entirely production-ready—, and there are some things I need to implement such as asynchronous bookmark import and export, e-mail password resets, Docker configuration and writing the API docs using api-documenter—the Python tool I wrote to generate formatted HTML API docs out of a JSON description file—. I’m also planning to make a cross-platform mobile app with Flutter—so I might as well learn how to use it—, write unit tests for both server and client, and enable CI and AWS integration. Yeah, a lot of work to do! It is a ridiculously simple project, but I’m really learning a lot by using new languages, tools and services.
I even created a simple and beautiful logo for Linkbucket using Adobe Illustrator. The typeface is not SF Pro, by the way; it is called Inter and it is free and open-source, and I love it! I discovered the font because the WordPress template I’m using for this blog actually uses Inter for display.
View on Behance
Source code moved to Sourcehut (still on GitHub, though).
Source code moved to Fossil (archived on GitHub and removed from Sourcehut)