React Component Architecture — Designing Structure with AI

 


A Pretty Screen With Tangled Code Is Still a Mess

The color palette is finished. Stars drift in the background. The card-flip animation is smooth. All 78 images are secured. Now it is time to assemble all these elements into a working app. But if you start coding without a plan, you will inevitably regret it.

In frontend development, component architecture is the structural framework of a building. No matter how stunning the exterior, if the frame is weak, walls collapse every time you add a feature or fix a bug. Especially in a project like a tarot app — with multiple reading modes and complex state transitions — the initial architecture determines how fast everything else proceeds.

Start with the User Flow

Before dividing components, I mapped out the user's screen flow. The journey has three stages: select a reading mode on the home screen, draw cards, and view the results. Breaking each stage down further reveals the details.

On the home screen, the user picks one of four reading modes: one-card, three-card, Celtic Cross, or free selection. Selecting a mode transitions to the card selection screen, where the user picks the required number of cards from a face-down spread. Once all cards are chosen, the flip animation plays, and the selected cards' meanings and interpretations appear.

When communicating this flow to AI, separating "screens" from "data" was essential. I described the screen flow — home, card selection, results — alongside a separate data flow: selected mode, drawn card array, each card's position and orientation, and interpretation text.

Tips for Requesting Component Architecture from AI

Asking AI "design the component structure for a tarot app" directly produces generic results. App, Header, Footer, Card, Reading — the kind of structure anyone could think of. It is usable but misses the project's specific requirements.

An effective request provides three pieces of information. First, describe the screen flow concretely. Second, specify what data each screen needs. Third, identify what state must be shared between screens.

For example: "The card selection screen and the results screen need to use the same card data, and in Celtic Cross mode, each card's position affects the interpretation." Providing this level of detail transforms AI's suggestions into something far more specific and useful — including type definitions that incorporate card position, and a reading session state management structure.

Managing Reading Sessions with Context API

Choosing a state management tool was another important decision. External libraries like Redux, Zustand, or Jotai were options, but I decided React's built-in Context API would suffice. The tarot app's state is complex but not "global." It only needs to be shared within a single reading session.

I created a ReadingContext that manages the reading mode, selected cards, each card's position and orientation, and interpretation results in one place. Starting a new reading resets the Context. Selecting a card updates the state. The results screen reads all the data from there.

AI was especially helpful with the Context splitting strategy. Initially, I planned to put everything in one large Context. AI suggested that "separating reading configuration (mode, card count) from reading results (selected cards, interpretations) can reduce unnecessary re-renders." Indeed, the mode selection screen never needs result data to change, so the split made sense.

Do Not Try to Nail the Perfect Structure Upfront

The easiest trap in component architecture is trying to build the perfect structure from day one. Anticipating unimplemented features and building flexible abstractions that accommodate every possibility leads to over-abstracted code that is actually uncomfortable to use in practice.

For this project, I intentionally took a "just enough" approach. I started by building a structure that only supports one-card mode. Draw one card, flip it, show the interpretation — the simplest possible flow. Once that was complete, I added three-card mode, and the architecture naturally expanded during the process.

I communicated this approach explicitly to the AI. "For now, only one-card mode needs to work. I plan to add three-card and Celtic Cross later, but you do not need to account for that now." Scoping the request clearly leads AI to suggest clean code without unnecessary abstractions.

Refactoring Is Not Failure — It Is Natural

When expanding from one-card to three-card mode, some component restructuring was needed, as expected. A results screen built for a single card now needed to display three cards side by side. Each card needed a position label (past, present, future).

You could view this negatively: "I got the initial structure wrong, so now I need to refactor." But the reality is the opposite. Because I built a simple structure that worked for one-card first, it was clear exactly what needed to change. If I had built an abstract architecture accommodating all three modes from the start, modifications would have been harder, not easier.

Refactoring with AI was efficient too. "I want to adapt this one-card component to work for three-card mode. The changes are: cards arrive as an array, and each card needs a position label." From there, AI produced a concrete modification plan based on the existing code. Because it understood the existing code's context, the suggestions were practical rather than theoretical.

Time Spent on Component Naming

It might seem minor, but I spent considerable time naming components. CardDisplay, CardView, or CardReveal? Each name implies a different role. Display suggests static rendering. View implies a broader screen unit. Reveal conveys the flip action.

When you ask AI for naming alternatives, it provides multiple options along with explanations of each name's nuances. The final choice is the developer's, but AI is useful for broadening the candidate pool. Working alone, you might cycle through two or three options. With AI, you can rapidly compare five or more.

I settled on conventions: Screen suffix for full-page components, functional names for reusable UI elements, and Layout suffix for structural containers. HomeScreen, CardSpread, ReadingLayout. This consistent naming lets you infer each component's role just by scanning the file list.

Once Structure Is Set, Speed Picks Up

After organizing the component architecture, subsequent development was noticeably faster. When adding new features, the question "which component does this belong in?" came up less frequently. When requesting feature implementation from AI, I could give specific instructions like "add a position label to the card inside the ReadingLayout component."

Two lessons from this experience. First, investing in architectural conversation with AI during the design phase saves significant time later. Second, incremental expansion is actually faster and safer than a perfect initial design. The second lesson applies to all software development, AI collaboration or not.

Next Up

With the component structure in place, it is time to tackle concrete layout implementation. The next part covers the most challenging layout problem in this project: the Celtic Cross. Arranging 10 cards in a traditional cross pattern on screen using CSS Grid — I will share the trial and error and the discoveries along the way.

댓글

이 블로그의 인기 게시물

사랑을 직접 올리지 않는 설계

감정을 변수로 옮기다 — 3계층 감정 모델

시작의 충동 — "타로 웹앱을 만들어볼까?"