import { useState, type FormEvent } from 'react'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { api } from '../api/client'; import type { CreatedApiToken } from '../api/bindings/CreatedApiToken'; function Interests() { const qc = useQueryClient(); const interests = useQuery({ queryKey: ['interests'], queryFn: api.listInterests }); const [label, setLabel] = useState(''); const [weight, setWeight] = useState(0.5); const upsert = useMutation({ mutationFn: (body: { label: string; weight: number }) => api.upsertInterest(body), onSuccess: () => qc.invalidateQueries({ queryKey: ['interests'] }), }); const remove = useMutation({ mutationFn: (id: string) => api.deleteInterest(id), onSuccess: () => qc.invalidateQueries({ queryKey: ['interests'] }), }); const onAdd = (e: FormEvent) => { e.preventDefault(); if (!label.trim()) return; upsert.mutate({ label: label.trim(), weight }); setLabel(''); setWeight(0.5); }; return (

Interests

Positive weights pull matching stories up; negative weights bury them. These weights — and only these — decide your ranking.

setLabel(e.target.value)} placeholder="topic, e.g. rust" /> setWeight(Number(e.target.value))} /> {weight.toFixed(2)}
); } function Tokens() { const qc = useQueryClient(); const tokens = useQuery({ queryKey: ['tokens'], queryFn: api.listTokens }); const [name, setName] = useState(''); const [fresh, setFresh] = useState(null); const create = useMutation({ mutationFn: () => api.createToken({ name: name.trim() }), onSuccess: (t) => { setFresh(t); setName(''); qc.invalidateQueries({ queryKey: ['tokens'] }); }, }); const revoke = useMutation({ mutationFn: (id: string) => api.revokeToken(id), onSuccess: () => qc.invalidateQueries({ queryKey: ['tokens'] }), }); return (

API tokens

Agentic and algorithmic producers POST candidates to /v1/ingest/candidates with a bearer token. Each token is scoped to your feed.

{ e.preventDefault(); if (name.trim()) create.mutate(); }} > setName(e.target.value)} placeholder="token name" />
{fresh && (

Copy this now — it won’t be shown again:

{fresh.secret}
)}
); } export function Settings() { return (

Settings

); }