This episode covers component-driven architecture and atomic design, feature modules with a scalable folder structure, composition patterns and render props, and design systems for building consistent and reusable UI.

As a project grows, the folder structure and component patterns decide whether your team moves fast or stalls. Episode 18 covers the architecture that makes React scalable: how to break down UI, organize folders, and choose the right composition patterns.
We start with component-driven architecture and atomic design, then feature modules and folder structure, then composition patterns with render props, and finish with design systems for consistency across the whole app.
Atomic design breaks the UI into five levels, from smallest to largest:
atom -> molekul -> organisme -> template -> halamanThe strength of this approach: each level can be tested and reused, and changes at lower levels automatically propagate upward.
Start with the smallest components and move up. Build the lower components first with mock data, make sure they work, then assemble them into pages. This shortens debugging because you know exactly at which level a problem sits.
Two common approaches: folder by type and folder by feature. For a growing project, folder by feature is far more scalable:
src/
├── features/
│ ├── auth/
│ │ ├── AuthPage.jsx
│ │ ├── LoginForm.jsx
│ │ └── authApi.js
│ └── produk/
│ ├── DaftarProduk.jsx
│ ├── KartuProduk.jsx
│ └── produkApi.js
├── components/
│ ├── ui/ # komponen shared (atom)
│ └── layout/ # header, footer, sidebar
├── hooks/
└── utils/features/auth/ groups everything related to authentication — its pages, components, and API. Unused features are easy to remove, and teams can work in parallel without conflicts.
One important rule: features must not import each other's internal components. If two features need the same thing, promote it to components/ui or hooks. This keeps dependencies flowing in one direction and makes testing easier.
Render props is a pattern where a component receives a function that returns JSX, giving full control to the consumer:
function MouseTracker({ render }) {
const [pos, setPos] = React.useState({ x: 0, y: 0 })
return (
<div
onMouseMove={(e) => setPos({ x: e.clientX, y: e.clientY })}
>
{render(pos)}
</div>
)
}
function App() {
return (
<MouseTracker
render={({ x, y }) => <p>Posisi: {x}, {y}</p>}
/>
)
}render={({ x, y }) => <p>Posisi: {x}, {y}</p>} decides how the mouse position is displayed. The MouseTracker component is only responsible for tracking the position; the consumer chooses the presentation.
Modern React more often uses plain composition (props and children) than render props. The render props pattern remains useful when you need to share behavior, not just presentation — and many libraries use it behind the scenes.
Another advanced pattern: compound components — parent and child components that work as a single unit. For example <Select> with <Select.Option>, like the accessible ARIA components from episode 17. Children communicate with the parent through context.
A design system is a collection of components, rules, and tokens that keep things consistent. Its foundation is design tokens: base values like colors and spacing:
export const tokens = {
warna: {
primer: "#2563eb",
teks: "#0f172a",
latar: "#f8fafc",
},
spasi: {
xs: "4px",
md: "16px",
lg: "24px",
},
}tokens.warna.primer is used in all components instead of random hex values. Change one token value, and the whole app changes — consistency maintained from a single source.
Collect the ui/ components into a documented library. Document each component: accepted props, usage examples, and edge cases. A good library speeds up development because the team isn't rewriting the same button.
npm install -D @storybook/react-vitenpm install -D @storybook/react-vite installs Storybook, a tool that displays each component with its mock states. Storybook makes your design system easy to see, test, and develop.
Episode 18 organized your React architecture: component-driven architecture with atomic design, feature modules and a scalable folder structure, composition patterns with render props, and design systems for app-wide consistency.
Key takeaways:
In the next episode, episode 19, we'll cover modern tooling & build automation — Vite as the modern bundler, ESLint and Prettier for code quality, integrating TypeScript into React, and optimizing the build and production bundle. Your project will be built on a solid foundation.