selamibaba

selamibaba

How would you model a fixed 78-item content domain without duplicating data?

I maintain a content website built around a fixed domain of 78 unique items.

This is the current overview page showing the complete data set:

Disclosure: I maintain the linked website. I am sharing it only to show the real content structure that I am trying to model.

The domain consists of:

  • 22 Major Arcana cards

  • 56 Minor Arcana cards

  • Four suits

  • Fourteen ranks within each suit

  • Upright and reversed interpretations

  • Stable URL slugs

  • Related meanings for love, career, feelings and yes-or-no questions

  • Individual editorial pages for each card

  • Interactive tools that also need access to the same card data

At the moment, some information exists in CMS entries, some in template code and some in JavaScript used by interactive tools.

I would like to move toward one reliable source of truth without sending the complete editorial content bundle to every browser.

A simplified TypeScript model might look like this:

type Suit = "wands" | "cups" | "swords" | "pentacles";

type Rank =
  | "ace"
  | "two"
  | "three"
  | "four"
  | "five"
  | "six"
  | "seven"
  | "eight"
  | "nine"
  | "ten"
  | "page"
  | "knight"
  | "queen"
  | "king";

type Orientation = "upright" | "reversed";

type MajorCard = {
  kind: "major";
  id: string;
  number: number;
  slug: string;
  title: string;
};

type MinorCard = {
  kind: "minor";
  id: string;
  suit: Suit;
  rank: Rank;
  slug: string;
  title: string;
};

type Card = MajorCard | MinorCard;

The longer editorial content could be stored separately:

type CardContent = {
  cardId: string;
  uprightMeaning: string;
  reversedMeaning: string;
  loveMeaning?: string;
  careerMeaning?: string;
  feelingsMeaning?: string;
  yesOrNo?: "yes" | "no" | "maybe";
  updatedAt: string;
};

I am considering four architectures.

Option 1: CMS as the source of truth

All metadata and editorial content remain in the CMS.

The frontend retrieves the entries through an API during the build or at request time.

Advantages:

  • Editors can work without touching the repository

  • Content publishing remains straightforward

  • No separate synchronization process

Concerns:

  • Invalid or incomplete records may be published

  • Relationships between cards may be difficult to validate

  • Build output depends on an external service

  • Interactive tools may require a second representation of the same data

Option 2: Versioned JSON or YAML

The complete card manifest is stored in the repository and validated during CI.

Long editorial content remains in the CMS.

Advantages:

  • Stable IDs, slugs and structural data are version controlled

  • The application can generate pages, routes and tests from the manifest

  • Breaking schema changes are visible in pull requests

Concerns:

  • Editors may need developer assistance when structural metadata changes

  • CMS entries and the repository manifest can drift apart

Option 3: TypeScript package

Create a small internal package containing card types, IDs, slugs and utility functions.

The website, calculators and editorial tools would all consume the same package.

Advantages:

  • Strong typing across applications

  • Reusable parsing and validation

  • Exhaustive handling of the fixed card set

Concerns:

  • Editorial content should probably not be bundled into the package

  • Updating one item may require publishing a new package version

Option 4: Database with generated types

Store everything in a relational database and generate TypeScript types from the schema.

Advantages:

  • One queryable source

  • Better support for editorial workflows and reporting

  • Easier localization and content versioning

Concerns:

  • More infrastructure than a relatively small fixed domain may require

  • Static page generation becomes dependent on database availability

My main questions are:

1. Where would you place the canonical identity data?

Would you consider the list of 78 IDs and slugs application code, CMS content or database data?

The cards themselves are fixed, but their descriptions change over time.

2. How would you validate completeness?

I want CI to verify that:

  • There are exactly 78 standard cards

  • Every ID and slug is unique

  • Every Minor Arcana suit contains all fourteen ranks

  • Every card has upright and reversed content

  • Every card has exactly one canonical page

  • Every related-card reference points to a valid card

Would you use JSON Schema, Zod, custom TypeScript assertions or database constraints?

3. How should stable identifiers differ from slugs?

Slugs may change for SEO or editorial reasons, but internal references should remain stable.

Would you use opaque IDs such as:

major-21
minor-wands-07

while treating the public slug as mutable presentation data?

4. Build-time or runtime content retrieval?

Most pages are public editorial pages and change infrequently.

Would you generate them statically and rebuild when content changes, or use server-side rendering with caching and revalidation?

5. How would you avoid shipping all content to the client?

Interactive tools need card IDs, titles, images and short summaries, but they do not need every full-length article.

Would you maintain separate public and editorial projections of the same data, or generate a lightweight client manifest automatically?

6. Localization

A translated card should retain the same internal ID but have a different title, slug and article content.

Would you model localized content as:

type LocalizedCardContent = {
  cardId: string;
  locale: string;
  slug: string;
  title: string;
  content: CardContent;
};

Or keep routes and translations in a separate localization layer?

7. Generated types or handwritten unions?

Because the domain is fixed, an exhaustive union provides useful compiler guarantees.

However, manually writing and maintaining 78 constructors or literal values feels repetitive.

Would you generate TypeScript types from the validated manifest, or treat the manifest itself as the runtime source and derive the types using as const?

8. CMS synchronization

If structural data lives in the repository but editorial content lives in the CMS, how would you prevent drift?

I am considering a CI job that fetches the CMS records and validates them against the versioned card manifest before deployment.

Is that a reasonable boundary, or is splitting ownership between two systems likely to cause more problems than it solves?

My current preference is:

  1. Versioned manifest for stable IDs, structure and relationships

  2. CMS for long editorial content

  3. Schema validation during CI

  4. Generated lightweight JSON for interactive tools

  5. Static generation with targeted revalidation after publishing

I would appreciate feedback from anyone who has built a content-heavy site around a small but strictly defined domain.

Where Next?

Popular Frontend topics Top

New
pillaiindu
Some days ago I came across a video teaching the internals of git. It had some nice diagrams and animations. The diagrams looked like han...
New
dyowee
Why or when should one choose Tailwind over Bootstrap? :slight_smile:
New
AlessandroDsgroup
Hi to everyone, we are experiencing a 401 error related to the connection of the websocket (in reference to our web app); we are unable ...
New
pavanforza
I have a requirement to extract data from firebase which is used to build serverless applications. Can we connect Firebase no-sql databa...
New
harwind
First have a look at the code: function mainfunc(func, par3, par2){ window[func](par3, par2); } function calledfunc(par3, par2){ ...
/js
New
JessicaW33
Hello All, How would you implement a navigation system in React Native? Could not find a way so I ask the community can someone help me ...
New
Fl4m3Ph03n1x
Background I have a custom component in my LiveView, which is basically a group of checkboxes. I want to add a new attribute to my custo...
New
PickyBiker
I have done small amounts of programming for IOS and for Android, but now I need to create something that works with both. What are the ...
New
grboi
I am learning full-stack and wanted to know which tech would be best, which would scale better. This is because when sitting for intervie...
New

Other popular topics Top

Devtalk
Hello Devtalk World! Please let us know a little about who you are and where you’re from :nerd_face:
New
AstonJ
If it’s a mechanical keyboard, which switches do you have? Would you recommend it? Why? What will your next keyboard be? Pics always w...
New
AstonJ
Or looking forward to? :nerd_face:
503 15149 280
New
Exadra37
I am thinking in building or buy a desktop computer for programing, both professionally and on my free time, and my choice of OS is Linux...
New
dimitarvp
Small essay with thoughts on macOS vs. Linux: I know @Exadra37 is just waiting around the corner to scream at me “I TOLD YOU SO!!!” but I...
New
AstonJ
If you get Can't find emacs in your PATH when trying to install Doom Emacs on your Mac you… just… need to install Emacs first! :lol: bre...
New
PragmaticBookshelf
Build efficient applications that exploit the unique benefits of a pure functional language, learning from an engineer who uses Haskell t...
New
Fl4m3Ph03n1x
Background Lately I am in a quest to find a good quality TTS ai generation tool to run locally in order to create audio for some videos I...
New
mindriot
Ok, well here are some thoughts and opinions on some of the ergonomic keyboards I have, I guess like mini review of each that I use enoug...
New
CommunityNews
Open-source implementation of the classic GTA engine now running directly in your browser. Experience the reVC technology demo on DOS.Zon...
New