All code

Repository

Pitchless

Reads what people are asking on Reddit, tells you which questions your product genuinely answers, and writes a reply for you to check before it goes anywhere.

Find the Reddit posts where your app is the answer.


Private repository. Everything below is written from the code; none of it is a link you can follow.

What it is

You connect an app. It monitors the subreddits where its users are, scores every new post for whether your product genuinely answers it, drafts a reply in a human register, and shows you the queue. You approve or discard.

Why it exists

Every indie developer has the same distribution problem and the same two bad options: post about your launch and be ignored, or lurk hoping to catch a relevant question. The second works and does not scale, because it means reading everything. This automates the reading and leaves the judgement.

As a business

The most obviously commercial thing I have built — a clear buyer, a clear alternative, and usage costs that map to pricing. The uncomfortable part is the point: a tool that drafts replies designed not to read as marketing is one product decision away from being a spam engine. What separates them is entirely in the scoring, and the architecture takes the honest side — a human approves every reply.

Stack

Client
React · Vite · shadcn/ui · Capacitor
Backend
Supabase · Twelve edge functions

The decision

The problem

The scoring model faces a badly imbalanced problem. The overwhelming majority of posts are not answerable by your product, and the two errors cost wildly different amounts: a missed opportunity costs nothing, and a false positive costs a reply that reads as spam, in public, attached to your product's name. The naive version of this tool is worthless precisely because it optimises for finding something.

What I did

Fit is judged per thread before any reply is drafted, and the score is surfaced to the human rather than used to post. Drafting is a separate function, so a low-scoring post never reaches it. Splitting fetch, analyse and save also means a post can be re-scored without being re-fetched.

What it costs

A model call per candidate post is the dominant cost, and it is spent mostly on posts that will be discarded — the economics are the inverse of the value. Any attempt to cut that by pre-filtering cheaply is exactly where the false positives would come back.

Where it ended

Built and parked. Complete enough to run — onboarding, auth, analytics, digests — with no evidence of a launch.

On screen

The Pitchless opportunity queue: two Reddit posts scored 88 and 60 against a threshold of 55, each with a drafted reply and Edit reply or Skip actions.
Fig. 1 - the queue: every post scored, the threshold visible and editable, and a drafted reply nobody has posted yet

A piece of the code

supabase/functions/fetch-opportunities/index.ts

const ageHours = getPostAgeHours(post.created_utc);if (ageHours > 24) continue; // Skip dead threads// Quick score to avoid expensive comment fetch on bad postsconst quickScore = calculateOpportunityScore({  post_age_hours: ageHours,  upvotes: post.score,  comment_count: post.num_comments,  op_replied: false,  post_title: post.title,  post_body: post.selftext,});if (quickScore.total < scoreThreshold - 20) continue;const { opReplied, topComments } = await fetchPostComments(  sub.subreddit_name,  post.id,);
The economics of this product are inverted: almost every post is not answerable by your product, so almost all of the spend goes on candidates that will be discarded. The answer is a cheap score first, computed from metadata that arrives free with the listing, and the expensive comment fetch only for posts that clear the bar with twenty points of slack. The slack is the interesting number: it is an admission that the cheap score is a worse estimator, priced rather than trusted.

Excerpt — trimmed for reading, not a full file.

Ask about this project