Jason L Cachia

Portfolio

contact

North Port, Florida

see also

Landing page.
A circle, with blind entries and manual reveal, its retros, members and invite links.
Weekly retros in three columns, with voting and comments. This week is not yet revealed. Demo data.
The same page in the app's dark and light themes. Demo data.

Relationship Retro

Retrospectives for couples or groups, with numerous options to support relationship communication.

  • Ruby on Rails 8
  • Hotwire
  • Turbo 8
  • Tailwind CSS
  • Solid Queue
  • PostgreSQL

In development, under Ferrum Tech Labs

A Rails app for couples and friend groups to run periodic went-well, didn't-go-well and action-item retrospectives over a period they choose. Visibility is configurable and can stay blind until reveal, so everyone submits before seeing each other's answers; or attributed to support collaboration during the retro period. Live updates across user sessions when desired.

What made it interesting

  • Real-time updates over Turbo Streams. Everyone viewing a retro sees an entry, comment or vote instantly, and the person who posted it gets a personalized version in their own tab.
  • Blind-until-reveal capability, so no one's answers anchor anyone else's.
  • Scheduled jobs on Solid Queue, such as the sweep that reveals retros when they come due.
Code excerpt: comments/create.turbo_stream.erb
<% if @retro_item.visible_to_all? %>
  <%# The broadcast already appended an
      un-personalized copy (current_user: nil,
      since after_commit runs with no request
      context) to every subscriber including
      the actor's own tab. Replace it in place
      with a personalized one so the actor sees
      their own Remove control without needing
      to reload. %>
  <%= turbo_stream.replace dom_id(@comment) do %>
    <%= render "comments/comment",
          comment: @comment,
          current_user: current_user %>
  <% end %>
<% else %>
  <%= turbo_stream.append(
        dom_id(@retro_item, :comments)
      ) do %>
    <%= render "comments/comment",
          comment: @comment,
          current_user: current_user %>
  <% end %>
<% end %>
SMS-first journaling: text an entry, get an AI response.
Emotion tags, mood over time and top emotions, generated per entry. Demo data, seeded with public-domain quotes.
Streaks, mood over time, and top emotions and themes across all entries, filterable by date range, emotion, theme and sentiment.
Weekly and monthly AI reflections built from the user's own entries, with breadcrumbs that connect each period to similar past entries.

brdcrmb

SMS-first journaling: text an entry, get an AI response.

  • Ruby on Rails 7
  • Hotwire
  • Turbo
  • Stimulus
  • Tailwind CSS
  • PostgreSQL
  • Twilio
  • Stripe
  • Render
  • AWS S3
  • OpenAI
  • Anthropic
  • Postmark

Head of Engineering, first employee (Jul 2024 to present)

A micro-journal and memory application I built from 0->1, owning architecture, infrastructure, integrations, engineering leadership and hands-on delivery. Users journal by text message and get AI-generated responses, then revisit their entries with emotion tags, trends and reflections. Encrypted and embedded user's personal entries to provide privacy and analysis by vector.

What made it interesting

  • Two-way Twilio SMS journaling, plus an AI SMS quiz that tests recall of past entries.
  • Database-level encryption with embeddings generated on save, and vector search over the encrypted entries.
  • Stripe subscription integration.
  • OpenAI and Anthropic powered emotion tagging, and periodic reflections with ties to previous entries.
The Crossroads Tavern: a tavern and a dining room staffed entirely by AI, with each role handing the guest off to the next.
Knowledge hand-off: the hostess records the guests' seating preference and occasion with tool calls, and the waiter picks up from there.
A party of 18 needs the manager's approval. The manager weighs the guests' situation and manners, and the tool turns that into odds (85% here) before deciding.
Escalating to the manager doesn't change the answer. The transfer is honored immediately and the manager stays in role too, and the yellow rows are hand-off checks run by the app, not the model. Earlier in the same chat, a scope check classified the guest's instruction-override attempt before the waiter replied and returned a fixed redirect.

Multi-agent handoff demo

AI agents that hand off what they know and stay in their roles, demoed as a restaurant.

  • Ruby on Rails 8
  • Hotwire
  • Turbo Streams
  • Tailwind CSS
  • Solid Queue
  • SQLite
  • RubyLLM
  • Claude Haiku
  • Ollama
  • qwen3:8b

Demo built for a non-technical founder

Built as a demo for a non-technical founder whose workflow depended on knowledge passing between agents. A restaurant staffed by AI personas (hostess, waiter, sommelier, chef, manager, busser) stands in as an example anyone can follow, and the point is making the handoff reliable: rules that matter are enforced in code, not requested in a prompt.

What made it interesting

  • Knowledge hand-off enforced in code. Staff record guest facts such as allergies through tool calls, and later tools read them back from the database, so a dish is withheld whether or not the model remembers.
  • A pre-turn scope check. A narrow structured yes/no classification runs before a persona replies, so an off-topic or instruction-override request can be turned away before the conversational model ever sees it.
  • Hand-offs treated as the end of an agent's turn. Every route goes through one Handoff model, background nudges use bounded retries, and a per-chat database turn lock keeps concurrent writers from corrupting a conversation.
Code excerpt: restaurant/decide_large_party_tool.rb
# The model supplies a weight, -2..2, for how the guest
# has made their case, and the code draws against the
# matching odds. So the model's read of the guest is
# where the non-determinism and the flavor live, and
# the outcome is still a real, guaranteed random draw
# it can neither skip nor overrule: only a heads here
# writes the approval SeatPartyTool checks for.
ODDS = { -2 => 0.15, -1 => 0.30, 0 => 0.50,
         1 => 0.70, 2 => 0.85 }.freeze

def execute(weight:, reason:)
  # ... guards: party size on record, approval
  # tier, weight in range ...

  odds = ODDS.fetch(weight)
  approved = SecureRandom.random_number < odds

  # ... record the weight and the model's reason ...
  if approved
    Restaurant::Fact.record!(
      chat: @chat,
      category: "party_approval",
      subject: "large party",
      value: size.to_s,
      severity: "preference"
    )
  end
  hand_back_to_hostess

  # ... "Heads -- approved" / "Tails -- declined" ...
end
The homepage hero at its full-tint frame. On the live page the bead sweeps in, holds, and fades on an 11-second loop. Work in progress.

Ferrum Tech Labs homepage

Rails upgrades, MVPs, custom websites and other services.

  • Astro
  • Cloudflare Workers
  • SVG and SMIL
  • CSS

Work in progress.

The marketing site for my Rails consulting practice, built as a light, mostly static Astro site for Cloudflare Workers. It is early and only the homepage exists, so this entry is a showcase of the design, led by a hero animation.

What made it interesting

  • This design intersects my interests as a hobby welder/fabricator and web developer.
  • A hero animation drawn as one inline SVG and driven by SMIL, with no animation library. A bead of thread sweeps across, gains its heat tint, holds, and fades on an 11-second loop.
  • Respects reduced motion. Visitors who prefer it get the same artwork frozen at its full-tint frame, and everyone else gets a Pause button.

Get in touch

Leave your email and a note, and I'll get back to you.