Skip to content

🪻 distributed transcription service

License

Notifications You must be signed in to change notification settings

taciturnaxolotl/thistle

Folders and files

NameName
Last commit message
Last commit date

Latest commit

33c55b1 · · Dec 17, 2025

History

140 Commits
Nov 23, 2025
Dec 1, 2025
Dec 1, 2025
Nov 23, 2025
Nov 22, 2025
Nov 23, 2025
Dec 17, 2025
Dec 17, 2025
Nov 20, 2025
Nov 20, 2025
Nov 20, 2025
Nov 24, 2025
Nov 20, 2025

Repository files navigation

Thistle

Important

This is crazy pre-alpha and is changing really rapidly. Stuff should stabilize eventually but probably not for a month or two.

.
├── public
├── src
│   ├── components
│   ├── pages
│   └── styles
└── whisper-server
    ├── main.py
    ├── requirements.txt
    └── README.md

9 directories, 3 fileses, 3 files

What's this?

Thistle is a transcription service I'm building for Cedarville's startup competition! I'm also using it as an opportunity to become more familar with web components and full stack applications.

How do I hack on it?

Development

I'm just running this locally for now but getting started is super straightforward.

bun install
bun devv

Your server will be running at http://localhost:3000 with hot module reloading. Just edit any .ts, .html, or .css file and watch it update in the browser.

Transcription Service

Thistle requires a separate Whisper transcription server for audio processing. Set it up in the whisper-server/ directory:

cd whisper-server
./run.shh

Or manually:

cd whisper-server
pip install -r requirements.txt
python main.pypy

The Whisper server will run on http://localhost:8000. Make sure it's running before using transcription features.

Environment Setup

Copy .env.example to .env and configure:

cp .env.example .env

# Edit .env to set WHISPER_SERVICE_URL=http://localhost:8000

The tech stack is pretty minimal on purpose. Lit components (~8-10KB gzipped) for things that need reactivity, vanilla JS for simple stuff, and CSS variables for theming. The goal is to keep the total JS bundle as small as possible.

How does it work?

The development flow is really nice in my opinion. The server imports HTML files as route handlers. Those HTML files import TypeScript components using " tabindex="0" role="button">

// src/components/counter.ts

import { LitElement, html, css } from "lit";

import { customElement, property } from "lit/decorators.js";

@
@customElement("counter-component")

export class CounterComponent extends LitElement {
  @@property({ type: Number }) count = 0;

    static styles = css`

    :host {

      display: block;

      padding: 1rem;

    }

  `;

    render() {
     return html`

      div>gt;${this.count}div>gt;

      button @click=${() =>gt; this.count++}>gt;+button>gt;

    `;
   }

}

Oh last two points. Please please please use standard commits for my sanity and report any issues to the tangled repo

© 2025-present Kieran Klukas