Voxicle Build Log 15

⏮️ Previous Build Log Objectives Mark feedback public/private Start on settings page 🛠️ What I Worked On Mark feedback as private/public Logged in users can mark feedback as private so it won’t be shown on the public dashboard. Gitlab Dependency Proxy I started using the Gitlab dependency proxy so that we can pull in image from Docker hub using Gitlab to avoid hiting rate limits. But also means we can use image cache which should makes jobs a quicker when pulling say postgres. ...

How to Use the GitLab Proxy in CI

Personal Projects For the moment, the GitLab proxy will not work if the project is in your personal namespace i.e. gitlab.com/hmajid2301. So to make it work with my project Voxicle I had to move to its own group. GitLab Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/323773 Background The GitLab dependency proxy, allows us to cache Docker images that we pull from Docker Hub. This allows us to reduce bandwidth and speed up builds, i.e. quicker to pull Postgres for our tests in CI. ...

Voxicle Build Log 14

⏮️ Previous Build Log Objectives Public page for feedback private and public feedbacks allow anonymous voting 🛠️ What I Worked On Public Feedback Dashboard We started of with this: And finish with this Users can now do the almost everything they can when logged in but when anonymous. We attach a deviceID cookie to them to be able to spot if its the same user. This only works for the same device and until they clear their cookies but should be good enough for most of the users I think for now. ...

Voxicle Build Log 13

I will stop making these weekly I think and produce them when there is actual stuff to share, as not make them stale and boring. Some times they may end up weekly, depending on how much progress I am making. ⏮️ Previous Build Log Objectives ✅ Better error modals (fixed) ✅ Start working on public page ✅ Multi tenant sub domains i.e. org1.voxicle.app 🛠️ What I Worked On Error Modal Bug I have some middleware that will show an error modal when we return an error back to the client. I may change this to be a toast for certain actions vs a full on modal but we can do that in the middleware. ...

Part 8: Neovim as Part of Your Development Workflow

After another 5 months (again) I’m finally back blogging about my development setup, opps! What is Neovim? Neovim is a text editor, that you can run in your terminal. Much like vim and vi or nano. So we would run this inside our terminal emulator and Zellij. It differs from vim because you can configure it using lua vs vimscript . Some of the other unique features it had, you can now do in vim (I believe). Such as tree sitter support and LSPs. ...

Voxicle Build Log Week 12

⏮️ Last Weeks Objectives Implement Authorization using RLS in Postgres Better error modals (fixed) 🛠️ What I Worked On 🔒 Row Level Security (Authorization) Row Level Security for Feedback and Upvotes. With row level security we can add policies and use config variables. Such that we set the organization ID and users can only get feedback that is part of their organization. This means we can simplify our SQL queries with fewer joins and fewer where clauses. Making them easier to read. Essentially it lets us do a simple form of authorization inside the web app. ...

How I Setup Tailwindcss LSP With Neovim & Nix (With DaisyUI)

Recently, I have been building an app (https://voxicle.app #ShamelessPlug), with tailwind and DaisyUI. I have been having issues getting the tailwind LSP to work nicely in Neovim, and only recently managed to make it work. So in this article, I will go over how I set up, assuming you are using Nix as a package manager. Why Nix? In my project, it is a go web app, so all the dependencies in the project are managed as go modules by my go.mod file. Then everything else the developer needs is set up as a dev shell. Things like the standalone tailwind CLI, I am using a nix flake which already has DaisyUI built in so it can also generate those types i.e. btn in the final styles.css (or whatever you called it). The flake is here: https://github.com/aabccd021/tailwindcss-daisyui-nix ...

Voxicle Week 11

Cricket is back this week, so I didn’t have as much time as I would over the weekend as I was out playing both weekends. But I made progress every day even a little on Voxicle. I need to work out, what the minimum features I want before I start to market and share with others to try it and provide feedback. Last Week Fixed my Tailwind LSP for a better DevEx Improved my Gitlab CI file when building the dev Docker image Improved the UI Allow users to change the sort filters i.e. latest or oldest Next Week Implement Authorization using RLS in Postgres Better error modals (fixed)

Why I Built a Web App With HTMX, Go & Postgres

Introduction Recently, I have started to build apps using the web stack: frontend htmx tailwindcss daisyui alpine backend go templ postgres devex gitlab ci nix devshells I have now built two apps using this stack, one of them being banterbus.games a browser-based party game (currently broken). Using web sockets, so it isn’t the most normal web application. As there are a few quirks of web sockets. Banter Bus Code: https://gitlab.com/hmajid2301/banterbus I am currently building a more normal CRUD app, called Voxicle (https://voxicle.app), a SaaS platform for collecting and acting on user feedback. The first time, I am trying to build something which I will charge others for (hence the code also not being open-source yet). Some more context here: https://haseebmajid.dev/posts/2025-03-03-go-feedback-my-new-side-project/ ...

TIL - How to Set Dynamic URL With HTMX and AlpineJS

TLDR; Add this attribute to your x-bind:hx-delete x-effect="currentItemId;htmx.process($el)" as an example (adjust for your example). Background In my app, I show the user 25 feedbacks per page, and they can delete them which opens a modal to confirm the action. If the user presses the delete button in the modal I want to send a HTTP DELETE request to an endpoint like /feedback/{id}, but the ID is dynamic, as we are using one modal for all the feedbacks vs having one modal per one feedback. ...

TIL - Fix Telescope Ignoring Env Files

Recently I noticed when I searched using Telescope in Neovim, that I could see env.local.template but not .env.local. Where my keybinding looked like this: vim.keymap.set("n", "<leader>ff", function() builtin.find_files({ hidden = true, follow = true }) end, { desc = "Find all files" }) This was because I was ignoring the .env* paths in my gitignore, I could tell telescope to not follow the gitignore. But I would get a lot more junk when searching in Telescope. I just wanted to see certain patterns but still mostly respect the gitignore file. You can do the following: ...

Voxicle Week 9 & Week 10

Last 2 week Again got really busy with some personal stuff, and stuff at work so didn’t really have much motivation to work on this project. But I have been forcing myself to code, so at least make some progeres. I did the following: Worked out we can use row level security in Postgres for better authorization Added lots more tests Edit Feedback Dynamic URL using Alpine Figure out duplication bug Filter on search More filter options Next Week Next week I want to; ...

Voxicle Week 7 & Week 8

Last 2 week Some stuff kept me busy so I couldn’t really work on my project work. I did the following: Added tests E2E with new skeleton How to debug E2E tests with delve (i.e. the server running separately) Fixed a bunch of TODOs in the code base Delete feedback However I got a busy with other random pieces of work that come up that kept me busy. Hopefully this week will be more productive. ...

TIL - How to Get Dropbar and Auto Session to Work

Original Article You can find more context on the problem here In my post last month I thought I had fixed this issue but turns out I did not. The actual fix to stop getting this error: 5108: Error executing lua [string "v:lua"]:1: attempt to call global 'dropbar' (a nil value) stack traceback: [string "v:lua"]:1: in main chunk bat /home/haseeb/.local/share/nixCats-nvim/sessions/%2Fhome%2Fhaseeb%2Fprojects%2Fvoxicle.vim | rg dropbar setlocal winbar=%{%v:lua.dropbar()%} setlocal winbar=%{%v:lua.dropbar()%} setlocal winbar=%{%v:lua.dropbar()%} We want the winbar to nil. The fix that worked for me was this: ...

Voxicle Week 6

This week I did the following: Finish core feedback page Add new feedback upvote display as list or grid Stretch try to implement basic RBAC (more of a PoC) However I got a busy with other random pieces of work that come up that kept me busy. Hopefully this week will be more productive. Next Week Next week I want to; Finish core feedback page search display as list or grid email updates when a feature has been completed more filter options Stretch public/private views Carry on working on the core feature set and make it so we can share with other people. ...

Voxicle Week 5

This week On my list of tasks I had the following: Fix auth refresh token flow not fully working Add span information to the auth middleware Simplify templ with pop drilling Update project name And managed to do all of them, even starting to work the core feedback part of the application i.e. allowing users to actually add feedback to the project. I rebranded the app from Go Feedback to Voxicle (which means voice and cycle). ...

TIL: How to Fix Issue With Dropbar and Auto Session

Actual Fix This fix didn’t actually work the actual fix can be found here I recently moved to dropbar from barbecue as it has been archived and kept getting a weird error for buffer open when I would reopen Neovim. I use the auto-session plugin, which loads back the previous state of NixVim when I last exited in that folder, i.e. open buffers. E5108: Error executing lua [string "v:lua"]:1: attempt to call global 'dropbar' (a nil value) stack traceback: [string "v:lua"]:1: in main chunk I noticed though I would only get this error the second time I would open Neovim, which then made think maybe it was an issue with auto-session. So I looked at the serialised file it generates so it knows what to load when we open Neovim again. Which I found at: ...

Go Feedback Week 4

This week I decided to use wristband to the tenant and then organization on my side of the app. I am not fully happy with it. During sign up the user creates a tenant but that might be confusing to the customer vs telling them its an organization. But it does mean a new user is created and tenant on both wristband side and in the service database. Then I moved onto working on the subscription logic with paddle. Updated the pricing page to pull in data from the backend when populating the page. Also integrating the overlay checkout, which is the simplest way to integrate paddle with my app. I cannot style it as much as the inline one, but it involves writing less JS. So I will use that for now. I am finishing off the subscription webhook logic, to create the data on our side. ...

Go Feedback Week 3

Week 3 I finished off the auth flow this week, decided to move over to using the wristband UI instead of using my own components. It ended up being a lot of code which was nice to actually delete and I think the wristband setup is pretty nice and slick. I had to adjust slightly how I will create users in my own DB but it wasn’t a big deal. ...

Go Feedback My New Side Project

Background Last year, I worked on two main side projects: OptiNix: CLI tool to easily find nix options. Banter Bus: My third attempt at building a browser based multi-player game. Whilst Banter Bus is not fully done, I got it to an almost working state and at some point will go back and fix a bunch of the bugs and add some new features. However, I finally decided I wanted to try my hand at building something that I could try to make some money from. Whilst also learning more about business, product design etc. How can I launch an actual product vs building something? Purely for fun. ...

How to Fix Firefox Rendering Emoji Font (NixOS)

I was some issues with the ways some fonts were rendering in Nix/NixOS machines. It seemed to specifically effect a few apps, mainly Firefox and only certain webpages. Sometimes numbers would render like below: Debugging Steps This occurred off and on over the course of a few weeks. My font setup was primarily done using stylix and a bit of NixOS option config. I noticed this only seemed to happen when the CSS on the page include a font-family like so “monospace” i.e. the monospace font in quotes. But without quotes, the font would render fine. ...

TIL: How to Fix PipeWire/WirePlumber Issues on NixOS

TIL: How to Fix PipeWire/WirePlumber Issues on NixOS For the last month or so, the audio on my Desktop was broken in the sense I had to run these three commands to make it work pipewire & wireplumber & pipewire-pulse Now, normally I hibernate my computer, so I didn’t really have to do this more than once or twice. However, it was very annoying either way to remember to know how to do it. ...

My Year in Review 2024

I did one of these last year, and thought why not do another quick year in review. Catch people up with what I’ve been up to. This year was not nearly as transformative as my previous year in terms of changes I made to my workflow. I am still using Nix and NixOS, I am still using Neovim. I moved onto from tmux to zellij mainly because I just like the floating terminal it provides. But other than that, it’s basically the same as the end of last year. ...

Part 7: Zellij as Part of Your Development Workflow

After another 5 months I’m finally back blogging about my development setup. Which since my last post, has been a lot more stable. As much closer to a workflow I am mostly happy with. In this post, we will go over how I integrate Zellij. What is a terminal multiplexer? Zellij is a terminal multiplexer think like tmux or screen. It another one of those projects written in rust. Which seems pretty popular for creating similar tools to existing ones but usually faster. ...

Speaking Tips I Have Learnt From Conferences

Since 2022 I have tried to speak at least one conference/meetup a year. The main reason for this was it forces to really learn the area I want to present about a lot deeper. If you can explain something new to someone clearly then it really shows you understand it very well. Recently, I was lucky enough to speak at GoLabs 2024 in Florence, which was a load of fun and a week later at the London Gophers November Meet. ...