You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A "you are here" for the project after a long pause — honest state of the codebase, what the previous Rails app gives us, how the scattered vision/planning issues reconcile, and a concrete MVP build order to get from "dictionary" → "layered encyclopedia" and start landing the features in #66 / #67.
This is the orientation doc. It does not replace the planning issues — it points at them. See the Issue Map at the bottom.
1. Where we are (current Phoenix codebase)
One commit (7c6dd33, "Initial commit: Devil's Dictionary Phoenix/Elixir rebuild"). It's a clean, well-structured dictionary — not yet an encyclopedia. Phoenix 1.8 + LiveView 1.1 + Postgres + Tailwind v4.
✅ What actually works
Schemas + changesets, all migrated & tested-by-construction:
Three working LiveViews:HomeLive (search), TopicLive (/define/:slug — the 3-tier definition page), BrowseLive (/browse, /browse/:letter A–Z).
DictionaryComponents — tier-specific definition cards (gilded aristocracy / clean middle / social plebs). This is the "layout is the argument" idea, already rendered.
Infra wired: Oban in the supervision tree, Cachex dep, Req, Floki, pg extensions migration, Oban jobs table.
DictionaryAPI context is an empty stub — just a moduledoc saying "API clients added in Phase 4." This is the single biggest gap vs. what we want next (import from sources).
Auth is cosmetic — Accounts is written around Clerk (webhook sync, get_user_by_clerk_id), but there's no clerk_elixir dep, no webhook controller, no auth plug, no login UI. Nothing is actually gated.
Oban has zero workers — configured but idle.
No admin/seeding UI — content only via seeds.exs or IEx.
Relationships exist in data but have no real UI (TopicLive "See Also" is a thin placeholder).
Only 4 test files (Phoenix defaults + error views) — no context/LiveView tests.
2. The asset we already paid for: the old Rails app
The closed PRs (#12–#62, all Bump …-rails, solid_queue, brakeman, aws-sdk-s3, nokogiri, engtagger) confirm the prior version was a mature Rails app, and #44 documents it in detail. Don't reinvent — port.
The Rails ingestion logic (parsing, rate handling, dedup) is reference material we can translate into Elixir DictionaryAPI.Clients.* + Oban workers. Action: locate the Rails repo and link it here so we can port client-by-client. (Not in this working tree; ~/Code/projects-2026/argus is a different Elixir app, not the old dictionary.)
3. Reconciling the vision (so we stop re-planning)
Multiple issues describe the same thing with different vocabulary. They agree; here's the merge:
The dictionary→encyclopedia move is exactly: keep the tiered definitions (dictionary), then layer on evidence from the culture (#67), quotes with provenance (#65), and relationships (#66 see-also) — the "in popular culture" + cross-reference fabric that makes it encyclopedic. The schema already anticipates this (tiers, external IDs, relationships).
Recommendation: keep the :aristocracy/:middle/:plebs enum in code (it's the brand voice), treat Canonical/Curated/Public as the conceptual names in docs. Don't rename the enum for MVP.
4. Recommended MVP build order
Goal of MVP: a real corpus, imported from real sources across the three tiers, on a polished definition page, with the first slice of the evidence layer. Auth, votes, bots, and media-heavy sources are deferred.
Phase 0 — Harden the foundation (small, do first)
Seed the full Ambrose Bierce corpus (~1,000 public-domain defs) so the dictionary feels real, not a demo. 👑
Add context + LiveView tests for the existing Dictionary paths (search, tier ordering, /define/:slug).
Decide auth posture for MVP (see Open Decisions) — likely defer Clerk, ship read-only + an IEx/admin seed path.
Phase 1 — The import pipeline (the "base layer to import different sources" the project hinges on) 🎯
Build DictionaryAPI for real, vertically, on the free/no-auth sources so there are no key blockers:
A mix dd.import <word> task (or tiny admin LiveView) that, given a headword, fans out to all clients and populates all three tiers. This is the "magic moment."
Port one 👑 source next (Samuel Johnson) to prove the aristocracy tier isn't only static Bierce.
Tier vs. Layer naming in UI copy — keep aristocracy/middle/plebs visible, or surface Canonical/Curated/Public? Recommend: keep the class names, they're the brand.
AI-generated 👑 definitions ("Oscar Wilde on crypto") — in MVP corpus or deferred? Recommend: defer; seed real public-domain first.
This issue: state-of-the-world + MVP build order tying the above to the code that exists.
Suggested housekeeping: this issue + #61 + #66/#67 are the only ones needed day-to-day. #44/#47/#48 are now reference; consider labeling them planning/reference to reduce noise.
Purpose
A "you are here" for the project after a long pause — honest state of the codebase, what the previous Rails app gives us, how the scattered vision/planning issues reconcile, and a concrete MVP build order to get from "dictionary" → "layered encyclopedia" and start landing the features in #66 / #67.
This is the orientation doc. It does not replace the planning issues — it points at them. See the Issue Map at the bottom.
1. Where we are (current Phoenix codebase)
One commit (
7c6dd33, "Initial commit: Devil's Dictionary Phoenix/Elixir rebuild"). It's a clean, well-structured dictionary — not yet an encyclopedia. Phoenix 1.8 + LiveView 1.1 + Postgres + Tailwind v4.✅ What actually works
Topic(title, slug, type, pronunciation, part_of_speech,display_typeredirect/disambiguation, self-refredirect_to)Definition(content, source_name/url/year,tier ∈ [:aristocracy,:middle,:plebs], position, author FK)Person(bio, birth/death dates → auto-aristocracy if dead, external IDs: google_knowledge_id, tmdb_id, open_library_id, wikidata_id)TopicRelationship(word_form/synonym/related/see_also/antonym/broader/narrower/disambiguates, weight, bidirectional)Accounts.User(Clerk-shaped)Dictionarycontext — full CRUD,get_topic_with_definitions/1(tier-ordered preload),search_topics/2(ilike), relationships, word-forms.HomeLive(search),TopicLive(/define/:slug— the 3-tier definition page),BrowseLive(/browse,/browse/:letterA–Z).DictionaryComponents— tier-specific definition cards (gilded aristocracy / clean middle / social plebs). This is the "layout is the argument" idea, already rendered.🟡 Stubbed / shaped but not functional
DictionaryAPIcontext is an empty stub — just a moduledoc saying "API clients added in Phase 4." This is the single biggest gap vs. what we want next (import from sources).Accountsis written around Clerk (webhook sync,get_user_by_clerk_id), but there's noclerk_elixirdep, no webhook controller, no auth plug, no login UI. Nothing is actually gated.seeds.exsor IEx.❌ Not present at all
2. The asset we already paid for: the old Rails app
The closed PRs (#12–#62, all
Bump …-rails,solid_queue,brakeman,aws-sdk-s3,nokogiri,engtagger) confirm the prior version was a mature Rails app, and #44 documents it in detail. Don't reinvent — port.~23 models (STI: Topic→Person/Place/Concept/…; Expression→Quote/Lyric/Poem; Media→Movie/TvShow/Photo/Art/Gif) + Vote, Bot, BotInfluence, join tables.
14 working API integrations with known auth/effort:
The Rails ingestion logic (parsing, rate handling, dedup) is reference material we can translate into Elixir
DictionaryAPI.Clients.*+ Oban workers. Action: locate the Rails repo and link it here so we can port client-by-client. (Not in this working tree;~/Code/projects-2026/argusis a different Elixir app, not the old dictionary.)3. Reconciling the vision (so we stop re-planning)
Multiple issues describe the same thing with different vocabulary. They agree; here's the merge:
:aristocracy👑:middle📚:plebs📱The dictionary→encyclopedia move is exactly: keep the tiered definitions (dictionary), then layer on evidence from the culture (#67), quotes with provenance (#65), and relationships (#66 see-also) — the "in popular culture" + cross-reference fabric that makes it encyclopedic. The schema already anticipates this (tiers, external IDs, relationships).
Recommendation: keep the
:aristocracy/:middle/:plebsenum in code (it's the brand voice), treat Canonical/Curated/Public as the conceptual names in docs. Don't rename the enum for MVP.4. Recommended MVP build order
Goal of MVP: a real corpus, imported from real sources across the three tiers, on a polished definition page, with the first slice of the evidence layer. Auth, votes, bots, and media-heavy sources are deferred.
Phase 0 — Harden the foundation (small, do first)
Dictionarypaths (search, tier ordering,/define/:slug).Phase 1 — The import pipeline (the "base layer to import different sources" the project hinges on) 🎯
Build
DictionaryAPIfor real, vertically, on the free/no-auth sources so there are no key blockers:DictionaryAPI.Clients.FreeDictionary(dictionaryapi.dev) → 📚 Middle definitions + pronunciation/part-of-speech.DictionaryAPI.Clients.UrbanDictionary→ 📱 Plebs definitions (this is where situationship/performative live).DictionaryAPI.Clients.Wikiquote→ quotes/curated → 📚 Middle (feeds Quote layer with provenance scoring #65 later).Definition(dedup on topic+source) → bumpdefinition_count.mix dd.import <word>task (or tiny admin LiveView) that, given a headword, fans out to all clients and populates all three tiers. This is the "magic moment."Phase 2 — Evidence wall MVP (#67) 🔥
Evidenceschema:topic_id,type ∈ [:tiktok,:youtube,:song_lyric,:instagram,:tweet],url,title,thumbnail_url,submitter,metric_kind,metric_count,position.TopicLive, "stays put while the definitions argue."Phase 3 — Encyclopedic fabric
TopicRelationshipdata — real cross-linking.Deferred (post-MVP)
Clerk auth + user accounts · voting/agree-counts (needs auth) · Curator Bots (#17) · key-gated media sources (TMDB/Unsplash/Giphy/Genius) · disambiguation/redirect pages.
5. Open decisions (need a call before/within Phase 1)
6. Issue map (how the open issues relate)