Skip to content

📍 State of the project + MVP build order (dictionary → layered encyclopedia) #68

Description

@holden

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

  • Schemas + changesets, all migrated & tested-by-construction:
    • Topic (title, slug, type, pronunciation, part_of_speech, display_type redirect/disambiguation, self-ref redirect_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)
  • Dictionary context — full CRUD, get_topic_with_definitions/1 (tier-ordered preload), search_topics/2 (ilike), relationships, word-forms.
  • 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.
  • Seed data (demo-scale): 3 people, 5 topics, 17 definitions, 3 relationships.

🟡 Stubbed / shaped but not functional

  • 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 cosmeticAccounts 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.

❌ 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:

    Tier fit Free / no-auth (do first) Needs key
    👑 Aristocracy Samuel Johnson, (Bierce = static corpus)
    📚 Middle WikiQuotes, PoetryDB, OpenLibrary TMDB, Unsplash, Artsy, KnowledgeGraph, BrainyQuotes (Zyte), Genius (Bearer+Zyte)
    📱 Plebs ConceptNet, Datamuse Urban Dictionary (RapidAPI), Giphy

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:

Code term (shipping) #64 "encyclopedia" framing #46/#48 "class" framing Nature Who controls
:aristocracy 👑 Canonical Aristocracy of the Dead Truth Editorial / curated import
:middle 📚 Curated Middle Class Interpretation Editorial + institutional import
:plebs 📱 Public The Plebs Noise / culture User-submitted + social import

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:

  • 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).
  • Pattern to standardize once: Req client → Cachex cache → Oban worker → upsert Definition (dedup on topic+source) → bump definition_count.
  • 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.

Phase 2 — Evidence wall MVP (#67) 🔥

Phase 3 — Encyclopedic fabric

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)

  • Auth for MVP: defer Clerk and ship read-only + admin-seed (faster), or wire Clerk now (unblocks votes/submissions earlier)? Recommend: defer.
  • Find & link the old Rails repo so API clients can be ported rather than rewritten. Where does it live?
  • Evidence votes at launch? The Evidence Wall — masonry feed of mixed culture (tweets, lyrics, reels, TikToks, YouTube) with type filters #67 cards show counts — for MVP, show native source metrics (likes/views) only and defer our own agree-voting until auth exists? Recommend: yes, native-only first.
  • 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.

6. Issue map (how the open issues relate)

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions