Skip to main content

How We Pivoted from HRMS to GRC (and Somehow Got SOC 2 Certified Without Losing Our Minds)

{{pixgeist:cea3f375-8be8-4f7f-9786-1ac6fd8648cc}}

I need to share something that makes my impostor syndrome go absolutely wild: the complete clusterfuck that was our journey to SOC 2 certification.

Because here’s the thing about vulnerability in entrepreneurship—every time I think about sharing the messy parts, that voice kicks in: “Won’t admitting you struggled destroy your credibility?”

Fuck that voice. Let me tell you what actually happened.

The HRMS Fantasy (AKA: How I Wasted a Year)

February 2024. I started building Humadroid with this brilliant (read: completely wrong) assumption that I could solve HRMS better than everyone else. My logic seemed sound—I’d run Prograils, dealt with growing teams, juggled multiple expensive tools that barely talked to each other. I knew the pain points intimately.

I Got Paranoid About Security, So I Vibe-Coded a Rails Engine (Use at Your Own Risk)

{{pixgeist:65e5d26a-930b-437b-b538-a2ff22474eb7}}

TL;DR

Built Beskar - a Rails security engine with WAF, impossible travel detection, and auto-banning. Named after Mandalorian armor because layered protection. Mostly vibe-coded. Currently running in monitor-only mode on Humadroid because I’m not quite paranoid enough to trust my own paranoia gem. You probably shouldn’t use it yet. But here it is anyway.

I Rage-Quit WordPress and Built My Own Rails Site (Here's What Broke)

TL;DR

I migrated my startup’s website from WordPress to Rails because I was tired of fighting with hosting providers and plugin conflicts. Built custom scraping scripts, exported everything to Markdown, and automated SEO optimization with background jobs. Made several painful mistakes: forgot to remove old URLs from Search Console, used 301 redirects instead of 410 status codes, and nearly tanked my SEO with trailing slash inconsistencies. Now I have a faster site, cleaner code, automated content workflows, and I can extend it whenever I want. Worth it.

A Simple Solution for Combining Different Data Types in Rails

When building Humadroid’s dashboard, I needed to show both company announcements and employee shoutouts in a single feed. At first, I took what seemed like the easy route - using notifications as a bridge between these different types of content. Each announcement or shoutout would create a notification, and I’d just query those. Simple enough, right?

Well, not quite. I soon realized this approach had a major flaw: new users couldn’t see older announcements or shoutouts. They’d join the company and find an empty dashboard. Not exactly the welcoming experience I was aiming for!

Quick Tip: Reading Ruby Version from .tool-versions in Your Gemfile

While migrating from asdf to mise as my version manager, I needed to update how my Gemfiles read the Ruby version. It’s a small change, but I thought it might be useful to share.

With asdf, I was using .ruby-version:

ruby File.read(File.expand_path('.ruby-version', __dir__)).chomp

Now with mise using .tool-versions, which can contain versions for multiple languages, the line changed to:

ruby File.read(File.expand_path(".tool-versions"))[/^ruby[@ ](.+)$/, 1]

The regex matches a line starting with “ruby” (followed by either a space or @ symbol) and captures the version number.

A Simple Fix for Dynamicly Added External Widgets in Turbo-Enabled Sites

While working on Humadroid, I recently stumbled upon an interesting challenge with our chat widget. It’s a small discovery, but one that might save other developers some headaches.

The Problem

If you’re using Turbo (formerly Turbolinks) and external widgets like Chatwoot, you might notice they disappear or reload whenever you navigate between pages. This happens because these widgets usually attach themselves to the end of your DOM, and Turbo replaces all that content during page transitions.

This Week I've Learned - 2024-W49

PERSONAL

No post last weeks - had to take a break. Learning that rest is important, even when there’s lots to do.

TECH & CODING

WordPress Got Humadroid’s landing page rewritten in WordPress to let Bartek edit content without my help. Big thanks to Ilia and Florin from inntech who handled it. The frontend is super fast, but I was surprised how slow the admin side has become - making complex changes is really painful.

Nested forms with just Turbo Streams

Edit 11.12.2024: I’ve updated turbo stream responses to include field index.

Recently I was working on implementing dynamic nested forms using Turbo Streams, focusing on handling both new and persisted records without custom JavaScript. Well, mostly for fun, to try something new. And while there are multiple approaches to this problem, including Stimulus controllers or plain JavaScript, Turbo Streams offer a clean, server-driven solution that leverages Rails conventions.

The Core Concept: Form Manipulation vs Persistence

A key aspect of this implementation that might not be immediately obvious is that the IngredientsController doesn’t actually persist any data. Its sole responsibility is to manipulate the form structure through Turbo Stream responses.

This Week I've Learned - 2024-W44

CODING

  • Found a nice Ruby gem (actually it was recommended to me in this Xitter thread) - procore-oss/blueprinter which seems to be a very nice serializer (JSON Object Presenter) for Ruby. As I was implementing API for Humadroid recently with Time-To-Market in mind, I’ve actually settled on Grape & Grape Entity, but when we’ll be creating v2 of it in bigger team, we’ll most likely look for alternatives and blueprinter looks like a solid contender.