Actors and Roles
Overview
The people and systems involved in Jester, and what each one is responsible for.
People
Content manager
The operator responsible for creating and managing content, working through the admin UI (jester-user-web).
| Action | Details |
|---|---|
| Race information | Register, update and delete race result JSON; register AI prediction data |
| Articles | Request AI generation, review and edit the body, publish |
| Failed generations | Inspect the failure reason and regenerate with extra instructions |
| Past blogs | Import past blogs (uploading scraped JSON) and update their categories |
| Blogs | Request AI rewrites / original writing, review and edit, delete, publish |
| Thumbnails | Request thumbnail generation for a blog |
| Related information | Generate related-blog links for a blog |
| Master data | Create, update and delete categories and NG words |
Content reader
The end user who reads published content.
| Action | Details |
|---|---|
| Race result page | The race result with the "10-second summary" article embedded |
| Blog articles | Published blog articles |
Systems (automated)
App Lambda (odds_poc_app)
Accepts REST API requests from content managers, performs CRUD and kicks off asynchronous work.
| Role | Details |
|---|---|
| API handling | Accepts requests and returns responses for every endpoint |
| Database access | Reads and writes DocumentDB |
| Media storage | Uploads media to S3 and issues presigned URLs |
| Job dispatch | Enqueues article generation, blog generation, rewrite and thumbnail jobs on SQS |
| Embeddings | Generates the embedding vector when a past blog is registered |
| Related information | Computes blog similarity and inserts the related-information section (synchronously) |
article_generation Lambda
Writes the 10-second race result summary with AI.
| Role | Details |
|---|---|
| Race analysis | An AI agent analyses the race result, race video and course image (horse racing only) together |
| Writing | Writes one headline and three sentences, grounded in confirmed facts and the analysis |
| Factual guards | Substitutes values, checks against the official data and screens NG words; unresolved issues fail the generation |
| Result dispatch | Sends the generated article data to article_builder over SQS |
| Failure recording | On a final-attempt failure, keeps the article as "failed" with the reason |
article_builder Lambda
Builds the article HTML from the generated data and stores it in DocumentDB.
| Role | Details |
|---|---|
| Receiving | Receives article_generation's output over SQS |
| HTML build | Renders the article data through a React component into the summary box HTML |
| Persistence | Stores the article as a draft in DocumentDB (it never publishes) |
blog_generation Lambda
Writes blogs from race data.
| Role | Details |
|---|---|
| Race recap | Writes a post-race retrospective from the race result, video and course image |
| Race prediction | Writes a pre-race prediction from the entry list and AI prediction marks |
| Factual guards | Substitutes values, checks against the official data and screens NG words, as for articles |
| Embeddings | Embeds the generated body so it can be found by related-information search |
| Result dispatch | Sends the blog body to blog_builder over SQS |
blog_rewriter Lambda
Rewrites past blogs without changing their content.
| Role | Details |
|---|---|
| Race analysis | When the blog is race-linked, analyses the race result, video and course image |
| Rewriting | Rewrites while preserving the content and the author's voice, structured into article blocks |
| Summary | Generates the "10-second summary" from the rewritten body |
| NG word screening | Screens the output (words already present in the source are excluded) |
| Result dispatch | Sends the rewritten body to blog_builder over SQS |
blog_builder Lambda
Pours the blog body into an article template, builds the HTML and stores it in DocumentDB.
| Role | Details |
|---|---|
| Template selection | Chooses the template (prediction / race result / generic) from the category |
| HTML build | Renders the article area with oddspark's real components and SCSS |
| Carry-over | Preserves the existing thumbnail and related information across rebuilds |
| Persistence | Stores the blog as a draft in DocumentDB |
thumbnail_generation Lambda
Creates a thumbnail image from the race video.
| Role | Details |
|---|---|
| Moment selection | An AI agent analyses the race video, race result and course image and picks the best second |
| Frame extraction | Extracts that frame with ffmpeg |
| Persistence | Stores the image in S3 and registers the media record in DocumentDB |
| Embedding | Inserts the thumbnail into the blog body just below the "10-second summary" |
Related repositories
jester-user-web
The admin UI used by content managers (a React SPA). It also provides previews of race result pages and blog articles.
oddspark-static-pages
The repository holding oddspark's design assets (components and SCSS). blog_builder and jester-user-web render with the real components synced from it.