Frontend System Design/The RADIO Framework
Lesson 6 of 17 · Episode 6

RADIO — Core Entities

Identifying the core entities your UI is built around.

RADIOEntitiesData modeling
Watch on YouTube ↗

The architecture diagram kept saying “data” — this component sends data, that one reads data. The D step finally asks: what is that data? We describe the system from the data's point of view — its core entities and where each one lives.

The map

Where we are in RADIO

The architecture told us pieces exchange data. Now we model it. Tap D:

D · Core Entities
Identify the core entities the UI is built around, what each one owns, and how they relate.
The D in RADIO

What core entities are

A data entity is a block of data you can name with a single word — a Post, a Comment, a User. The D step identifies the core entities in your system, the fields each one holds, and which component or module owns them. That's what lets you say precisely “the store holds the posts; the header reads the author.”

Where data comes from

Two kinds of data

Almost every system mixes two sources of data, and telling them apart decides where each piece should live:

Server-originated
lives in the database
Your profile (name, avatar)
Feed posts & comments
Anything fetched from an API
Persists across devices & sessions.
Client-originated
starts life in the UI
Draft text in an input
isLoading / isError
isExpanded / isOpen
Often transient component state.
They can convert
The two aren't walls. Draft text in a comment box is client-originated — but the moment you hit Enter and it's saved, it becomes server-originated for everyone else. The question is simply where the data starts.
How to write it

Describe data with types

Don't just say “username.” Say its type. TypeScript-style notation is the clearest way to pin a field down so whoever reads the design knows exactly what shape arrives:

a field is a name + a type
username: string
age: number
comments: Comment[]   // an array of Comment entities

That last line matters: when a component expects Comment[], everyone knows it renders a list, not a single item.

Worked example

The Facebook-feed entities

Before the abstract boxes, here's the thing we're actually modeling — one feed post. Every region on screen maps to an entity (tagged in the corners):

User
Guilty-Looking Dogs
Portia Smith · 2h · 🌐 Public Group
Post

Is your dog looking guilty? Share your best “I-didn't-eat-it” face below! 🐶

Media
🐶
👍❤️😆 233K432 comments
Like
Comment
Share
Comment
Max's Human
He absolutely did it 😂

Turn that screen into data. Four entities cover the feed; notice how relations (the green types) stitch them together — a Post owns Comment[] and a User author:

Post
idstring
datestring
contentstring
mediaMedia[]
commentsComment[]
authorUser
Comment
idstring
datestring
contentstring
mediaMedia[]
authorIdstring
Media
type"image" | "video"
urlstring
User
idstring
usernamestring
avatarstring

Those cards are only half the story — the relations are what make it a model. Tap an entity to trace what it owns:

A Post owns comments, media, and an author. Tap an entity.
Try it

Classify the data

For each piece of data in the feed, decide where it originates — which tells you whether it belongs in the store/DB or as transient component state:

0/6 sorted
The logged-in user's profile (name, avatar)
Text being typed into the comment box
The page of feed posts just fetched
isLoading while the feed request is in flight
Whether a post's comments are expanded
A post's text before you hit “Post”
Keep state sane

State best-practices

Three habits keep your data model from turning into a bug farm:

1 · Keep component state isolated
Each component's state should be a black box. If you render two posts, one post's isLoading must never affect the other's. Isolated state is what lets you safely repeat a component on the page.
2 · Minimize the number of states
Fewer states are easier to reason about and cheaper to manage. Keep only the state that genuinely represents something you need.
3 · Don't store derived state
If a value can be computed from existing state, compute it — don't store it. isEmpty isn't state; it's items.length === 0. Storing it just gives you a second copy to keep in sync.
derive, don't duplicate
// avoid: a second source of truth
const [isEmpty, setIsEmpty] = useState(true)

// prefer: derive it on the fly
const isEmpty = items.length === 0
Practice

Check your understanding

Q1Sort each scenario
Server-originated or client-originated?
A user's saved order history
Whether a modal is currently open
Search results returned from an API
The current value of a search input
Q2Multiple choice
You need to know if a cart is empty. The best approach?
Q3Multiple choice
Why keep each component's state isolated?
Try it yourself

Design challenge

Model the data for a simple chat window:

  1. Write the Message and Conversation entities with typed fields.
  2. List which data is server-originated vs client-originated.
  3. Find one value you were tempted to store but could derive instead.
Key takeaways
  • A core entity is a nameable block of data (Post, Comment, User) with typed fields, owned by some part of the system.
  • Data is either server-originated (persists in the DB) or client-originated (UI state) — and can convert from one to the other.
  • Describe every field with its type (TS-style) so the shape is unambiguous.
  • Keep component state isolated, minimize the number of states, and never store derived state.
← Previous
5. RADIO — High-Level Design
Next →
7. RADIO — Interface Definition