Build AmICited

KINDAreplaces $57.73/mosaves $692.76/yrback to the verdict

0%0 of 17 items done

Saved on this device only. Tick prerequisites first, then work the phases in order · do not start one until the checks above it pass.

A local answer-engine visibility tracker whose hard problems are staying honest about being a proxy rather than a measurement, keeping a run's cost bounded and predictable, and not reading a trend into noise from fifty non-deterministic answers.

estimated effort weekendthe files for this build are in the project pack

RuntimeNode 22 with TypeScript, a CLI plus a server-rendered dashboardStorageSQLite via better-sqlite3, runs written once and never updatedProvidersOne module per provider behind one ask function, search or grounding enabledCostA ledger row per call and a hard ceiling checked before each requestMatchingWord-boundary alias matching, never substring

Before step 1

Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.

  1. installfree

    Why Runs the CLI, the scheduler and the dashboard.

    Get it nodejs.org, or nvm install 22. open ↗

    Verify node --version prints v22 or higher

  2. API keypay per use, and the search component is billed per search on several providers

    Why Each provider is a separate account with its own grounded-search billing, and enabling four of them means four bills.

    Get it Create an account with each provider and generate an API key with the smallest scope offered.

    Verify A single one-prompt run completes against each enabled provider

  3. have readyfree

    Why The cost ceiling is only meaningful if the numbers behind it are today's, and every one of these providers has changed pricing.

    Get it Open each provider's pricing page, record the token rates and the grounded-search rate with the date.

    Verify Every enabled provider has a price and a checked date in the configuration

  4. have readya few pounds a month

    Why The value here is an archive that compounds daily, and a laptop that sleeps produces a chart with holes in it.

    Get it A small VPS, a home server or anything that can run a nightly job.

    Verify A scheduled run completes overnight without you present

  5. decidefree

    Why The questions are the instrument, and changing them mid-way makes every earlier figure incomparable, so they deserve an hour before the first run.

    Get it Write the questions a buyer would actually type, and list the competitors by every name and spelling they use.

    Verify Both files exist, the prompt count is under the cap, and every alias is listed

Data model

Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.

- brands(id, name, aliases_json, domain, is_competitor) · your brand and the competitors, same table
- prompts(id, text, intent, active, added_at) · the buyer questions, capped and versioned by addition
- runs(id, started_at, finished_at, provider_set_json, prompt_count, status, cost_estimate, cost_actual)
- answers(run_id, prompt_id, provider, model_id, raw_text, finish_reason, latency_ms, error_text, tokens_in, tokens_out, searches, asked_at) · written once, never updated
- citations(answer_id, ordinal, raw_url, host, canonical_path, is_owned) · normalised, tracking parameters stripped
- mentions(answer_id, brand_id, count, first_offset) · offset as a crude prominence proxy, labelled as crude
- cost_ledger(run_id, provider, kind, units, unit_note, estimated_at) · kind is tokens or searches, because they are billed separately
- Nothing in this schema has an update path. Corrections are new rows, so the history stays true to what was returned on the day.

Environment variables

These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.

VariableNeededExampleWhere the value comes from
DATABASE_PATHrequired./data/visibility.dbRuns, answers, citations and the cost ledger. This is the archive.
BRAND_FILErequired./brand.jsonYour brand, its aliases, its domain and the competitor list.
PROMPTS_FILErequired./prompts.jsonThe buyer questions. Changing them is recorded against the run.
MAX_PROMPTSrequired50A cap, because cost scales with prompts times providers.
PROVIDER_CONCURRENCYrequired3Per provider. Higher is not faster once you are rate limited.
MONTHLY_COST_CEILING_USDrequired40Reaching it pauses scheduled runs and says so, rather than skipping.
MIN_RUNS_FOR_TRENDrequired14Below this the charts show points and a note instead of a trend line.
ANTHROPIC_API_KEYsecretoptionalsk-ant-...redactedOne provider's key. Every provider key is optional and the run skips providers with no key, visibly.

The build, in order

  1. Inputs, and a run that cannot be overwritten

    Brand, competitors and questions are files you edit, and each run appends an immutable set of answers.

    1. A trigger or a constraint, not a code review habit.

      Files src/db/schema.sqltests/immutable-answers.test.ts

    2. So a shift in the numbers can be traced to a shift in the questions.

      Files src/runs.ts

    3. Partial data that says it is partial is useful; partial data that lies is not.

      Files src/runs.ts

    done when · tick each as it passes
    watch out
    • Treating a re-run as a refresh and updating yesterday's row for the same prompt and provider destroys the archive that makes this tool worth anything after week three, and you will not notice until you want a chart. Insert only, and let the dashboard aggregate across runs.
  2. Asking, with a bill you predicted

    Every provider is called with grounding on, concurrency bounded, and the cost estimated before the run starts.

    1. Because prices change and a number in the code is a number nobody rechecks.

      Files src/config/pricing.tsdocs/pricing-sources.md

    2. The estimate is the only thing between a cron job and a surprise.

      Files src/cost.ts

    3. A missing provider that looks like zero visibility is a wrong conclusion.

      Files src/providers/index.ts

    done when · tick each as it passes
    watch out
    • A nightly cron with a retry on every failure quietly multiplies the run, and since grounded search is billed per search on top of tokens, a week of unnoticed retries costs several times what the first run's estimate said. Estimate before the run, record a ledger row per call, and refuse to start a run whose estimate exceeds the ceiling.
  3. Finding yourself without finding the wrong word

    Brand and competitor mentions and cited sources are extracted in a way you would defend.

    1. The difference between a chart and a flattering error.

      Files src/match.tstests/near-miss.test.ts

    2. Same page, same row, whatever the campaign parameters say.

      Files src/citations.tstests/url-normalise.test.ts

    3. In the interface, not only in a comment.

      Files src/views/answer.tsx

    done when · tick each as it passes
    watch out
    • Substring matching a short brand name finds it inside ordinary words and inside competitor names, so a brand called Arc scores a mention every time an answer says March or Arcadia, and the resulting chart is confidently wrong in your favour. Match on word boundaries with an explicit alias list, and keep a fixture test of words that must not match.
  4. A dashboard that refuses to draw a trend from noise

    The report shows share of voice, the gap list and how much of it is signal.

    1. The honest version of a sparse chart.

      Files src/views/trend.tsx

    2. It is the only view here that tells you what to do next.

      Files src/views/gaps.tsx

    3. They look the same on a chart and mean opposite things.

      Files src/views/provider.tsx

    done when · tick each as it passes
    watch out
    • Plotting a visibility percentage from a single day's fifty prompts produces a line that moves every day for reasons that are entirely model non-determinism, and somebody makes a content decision from it. Show the run count beside every figure, suppress the trend below the minimum, and state the sample size on every chart.
what this build does not replace
after v1, if you want it

Need the files? The project pack on the verdict page hands your agent the whole brief · more seo & marketing.