feat: scaffold newsfeed — user-controlled news feed
A self-hosted feed where the user owns the ranking: per-source and signed per-interest weights, decayed by recency, via a transparent deterministic scorer. Content is sourced algorithmically (worker RSS/Atom polling) and agentically (per-user API tokens POSTing candidates to the ingest endpoint). Single-user today, multi-user by construction (every row keyed on user_id). Rust cargo workspace + Vite/React/SWC/TS SPA: - newsfeed-entities: DTOs (ts-rs bindings -> web/src/api/bindings) - newsfeed-core: ranking, auth primitives, ingest, data-access ports - newsfeed-data: SQLite adapters (sqlx, runtime queries) - newsfeed-api: axum REST/JSON daemon - newsfeed-worker: RSS polling + rescoring loop - web: responsive, mobile-first SPA (React Query, generated types) Deploy (Gitea Actions, build static musl + SPA, rsync as gitea_ci): api+worker -> slartibartfast, SPA -> oolon (nginx serves + proxies /v1). Deliberate deviations from house conventions (documented in CLAUDE.md/readme): - SQLite instead of Postgres; api+worker co-locate sharing one DB file. - Runtime sqlx queries instead of query! macros (SQLite dynamic typing; keeps CI database-free). Verified end-to-end: auth, token ingest, interest-weighted ranking, signals, pagination (curl + browser); cargo fmt/clippy -D/test and pnpm build/lint pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016fKZzDpvjiJ9eYbPGgJvUP
This commit is contained in:
18
web/src/api/bindings/CandidateSubmission.ts
Normal file
18
web/src/api/bindings/CandidateSubmission.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { Media } from "./Media";
|
||||
|
||||
/**
|
||||
* A candidate pushed to `POST /v1/ingest/candidates` by an agentic or algorithmic
|
||||
* source. The authenticated API token determines the owning user; `source` names the
|
||||
* producer for attribution and per-source weighting.
|
||||
*/
|
||||
export type CandidateSubmission = {
|
||||
/**
|
||||
* Stable de-dup key from the producer. Re-submitting the same key is a no-op.
|
||||
*/
|
||||
external_id: string, url: string | null, title: string, summary: string | null, author: string | null, tags: Array<string>, media: Array<Media>, published_at: string | null,
|
||||
/**
|
||||
* Optional name of the source that produced this candidate. If it matches an
|
||||
* existing agentic source for the user it is linked; otherwise ingested unlinked.
|
||||
*/
|
||||
source: string | null, };
|
||||
Reference in New Issue
Block a user