Skip to content

srid/triffect

Repository files navigation

Triffect

Triangular affect journaling. Tap a point inside a triangle to log where you are on the good / bad / naivete spectrum and track patterns over time.

The three vertices map to actualfreedom.com.au's categorization of feelings:

  • Sensuous (green, top) — felicitous and innocuous feelings (delightful, harmonious)
  • 'Bad' (red, bottom-left) — hostile and invidious passions (hateful, fearful)
  • 'Good' (pink, bottom-right) — affectionate and desirable passions (loving, trusting)

Your tap position is stored as barycentric coordinates — three values ∈ [0,1] that sum to 1, representing proximity to each vertex.

Tap the triangle to log a mood instantly (with haptic feedback on mobile). Today's entries appear as colored dots on the triangle, and past week averages show as faded dots behind them.

Views

Three switchable views for today's entries (persisted in localStorage):

  • Timeline — horizontal 24h bar with dots at their logged time
  • Dots — chronological dot row, pure mood sequence
  • Arcs — stacked semicircle with average mood mini-triangle in the center

Tap any calendar day to view its entries in the same views.

Calendar

A 4-week heatmap with mini mood-triangles per day and a consecutive-day streak counter.

GitHub Pages

A static build is deployed to GitHub Pages on every push to master. All data lives in your browser's IndexedDB via Triplit — nothing leaves the device. No server, no account, no sync.

Export / Import

Tap Export data at the bottom of the page to download all entries as a JSON file (triffect-YYYY-MM-DD.json). Tap Import data to restore entries from a previously exported file. Import is idempotent — duplicate entries (matched by ID) are skipped.

The export format is a versioned envelope:

{
  "version": 1,
  "exportedAt": "2026-03-30T10:15:00.000Z",
  "entries": [
    {
      "id": "01JQXYZ1234567890ABCDEF",
      "good": 0.33,
      "bad": 0.33,
      "naivete": 0.34,
      "created_at": "2026-03-30T09:00:00.000Z"
    }
  ]
}

Schema

Each entry stores a point in the triangle:

Field Type Description
id string (auto) Unique identifier
good number [0,1] Barycentric weight toward Good vertex
bad number [0,1] Barycentric weight toward Bad vertex
naivete number [0,1] Barycentric weight toward Naivete vertex
created_at date Timestamp of the entry

The three barycentric coordinates always sum to 1. A tap near the Naivete vertex produces high naivete, low good and bad.

Stack

Layer Choice
UI SolidJS + TailwindCSS v4
Data Triplit — local-first with IndexedDB, auto-sync to self-hosted server
Build Vite + vite-plugin-pwa
Tests Cucumber + Playwright
Dev env Nix flake (zero-input, npins)
CI just ci — distributed across systems via SSH, posts GitHub commit statuses

Setup

nix develop    # or: direnv allow
just install
just dev       # starts Vite + Triplit dev server

Self-hosting

A home-manager module is provided for NixOS deployment behind Tailscale or equivalent. No auth — single-user by design.

services.triffect = {
  enable = true;
  package = triffect.packages.x86_64-linux.default;
  port = 8080;
};

Tests

just test       # build + e2e (Cucumber/Playwright)
just test-dev   # e2e against running dev server

CI

just ci         # runs nix build + home-manager + e2e on all configured systems
just ci protect # sets up GitHub branch protection from CI checks

References

About

Triangular affect journaling

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors