DEV Community

Cover image for Day 7 - Turning Static Pages into a Living Product
Sushant Gaurav
Sushant Gaurav

Posted on • Edited on

Day 7 - Turning Static Pages into a Living Product

Moving All Content into JSON: A Product Decision, Not Just a Technical One

One of the first things I did was move all personal data into structured JSON files:

  • Projects
  • Experience
  • Achievements
  • Open-source
  • About
  • Contact info
  • Hero content

At first glance, this might look like over-engineering for a personal portfolio. But this was a very conscious product decision.

I didn’t want my content to be:

  • Hardcoded inside JSX
  • Coupled to UI components
  • Painful to update later

Instead, I wanted:

  • Content to live independently of presentation
  • Pages to become renderers, not owners of data
  • The future possibility of replacing JSON with APIs without rewriting the UI

In other words: I treated my own data like product data, not like “strings in a component”.

This single decision unlocks:

  • CMS-like behaviour
  • Easy migrations to the backend later
  • Testing components without real data
  • And even non-developers updating content someday

That’s a very different mindset from "just build a portfolio".

Pages as Consumers, Not Controllers

Once the JSONs existed, the next step was building pages that consume them.

Not pages that fetch, shape, format, and decide everything.

But pages that simply say:

"Give me data, and I’ll render it."

A good example is the About section.

Instead of writing content directly in JSX, the component now looks like this conceptually:

  • It calls a hook (useAbout)
  • It handles three states: loading, error, and success
  • It renders whatever data it receives

This pattern repeats across:

  • Projects
  • Experience
  • Open Source
  • Achievements
  • Contact info

Which means every page now follows the same mental model:

Data comes from outside. UI just reacts to it.

This is exactly how real-world frontend systems are built — whether the data comes from JSON, REST, GraphQL, or Kafka.

Introducing the First “Real” Feature: Contact Form

Up to this point, everything was informational.

Day 7 introduced the first interactive feature: the Contact form.

This might look like a simple form, but architecturally it’s very important.

Because now the product:

  • Accepts user input
  • Manages internal state
  • Validates data
  • Handles submission
  • Shows feedback

In other words, it behaves like a real application, not a brochure.

Why I Split Logic into Hooks (and Not Inside Components)

The Contact page doesn’t contain business logic directly.

Instead, it uses two hooks:

  • useContactInfo: for static contact data
  • useContactForm: for form state & submission

This separation is intentional.

The component itself only does:

  • Rendering
  • Wiring inputs to handlers
  • Displaying status

All logic lives outside.

That gives me:

  • Reusability (same form logic elsewhere if needed)
  • Testability (logic without UI)
  • Cleaner components
  • Easier future refactors (e.g. replace email with backend API)

This is the same pattern used in production systems:
UI = dumb
Hooks/services = smart

The Contact Form as a Product Surface

The Contact form is also the first place where external users interact with the product.

So I treated it differently from other pages.

Not just visually, but conceptually:

  • Clear call to action
  • Social links for alternate contact paths
  • Feedback message after submission
  • Defensive UI (required fields, email type, etc.)

This is the point where the portfolio stops being "about me"
and starts being "a communication channel".

That’s a huge shift in mindset.

Why This Day Matters More Than It Looks

From the outside, Day 7 looks like:

"Created JSONs, created pages, created contact form."

From the inside, this day fundamentally changed the system:

  • The app moved from static to dynamic
  • Data became independent of UI
  • Components became consumers, not owners
  • The first real user interaction was introduced
  • The architecture now supports future APIs naturally

This is the kind of foundation you normally see in:

  • SaaS dashboards
  • Internal tools
  • Production React apps

Not in personal portfolios.

Architecture Diagram – JSON → Hooks → Pages → Sections → UI

(A simple flow diagram showing how data flows through the system)

Why This Architecture Scales (Even for a “Simple” Portfolio)

The most important thing about Day 7 is not the features themselves.
It’s the direction of the system.

By separating:

  • Data (JSON)
  • Logic (hooks)
  • Presentation (sections & pages)

I’ve unknowingly recreated a very real-world architecture:

Data Layer → Domain Logic → UI Layer

This is the same mental model used in:

  • React + REST APIs
  • React + GraphQL
  • React + tRPC
  • Even micro-frontend systems

The only difference is: today the data is local JSON, tomorrow it can be:

  • A Node API
  • A headless CMS
  • A Firebase backend
  • Or even a database behind a microservice

The UI won’t care.

That’s the real win.

Why JSON First Is Better Than API First (At Early Stages)

Many developers start projects by immediately building a backend.

I intentionally did the opposite.

Because early-stage product development is about:

  • Understanding data shape
  • Iterating content fast
  • Designing UX flows
  • Validating structure

JSON gives me:

  • Zero latency
  • Full control
  • No infra overhead
  • No deployment coupling

And still forces me to think in API contracts.

Each JSON file is basically:

"This is what my future API response will look like."

Which means when I do add a backend, I’m not guessing the schema — I’ve already lived with it.

Hooks as “Invisible APIs”

Another subtle but powerful outcome of Day 7:

Every hook is already an API.

For example:

const { data, loading, error } = useAbout();
Enter fullscreen mode Exit fullscreen mode

This is indistinguishable from:

const { data, loading, error } = useAboutApi();
Enter fullscreen mode Exit fullscreen mode

So later I can:

  • Replace JSON with fetch
  • Keep the same interface
  • Not touch any UI component

That’s exactly how you evolve systems without breaking them.

This is what people mean when they talk about:

"Design for change."

Not overengineering — just building seams into the system.

The Contact Form Is Actually a System Boundary

The Contact form might look trivial, but architecturally it’s huge.

It’s the first place where:

  • External users input data
  • That data leaves the system
  • And side effects happen (email, API, storage)

So this form is actually a system boundary.

Today it:

  • Shows success or warning
  • Maybe sends email

Tomorrow it can:

  • Push to CRM
  • Save to database
  • Trigger workflows
  • Fire analytics events

And none of the UI needs to change.

Only the hook.

That’s real product engineering.

From "Portfolio" to "Product Thinking"

Day 7 is the point where this project stopped being:

"A website that shows my skills".

And started becoming:

"A system that demonstrates how I think about software".

Because now anyone reading the code can see:

  • How data flows
  • How logic is isolated
  • How UI is kept dumb
  • How future changes are anticipated
  • How user interaction is handled

This is exactly what tech leads, staff engineers, and architects care about.

Not:

  • Fancy animations
  • Overused libraries
  • Or perfect pixel alignment

But:

  • Boundaries
  • Ownership
  • Scalability
  • Maintainability

The Meta-Lesson of Day 7

If someone takes only one lesson from this day, it should be this:

Build systems that can grow, not just systems that can run.

Even when the project is small.
Even when you’re alone.
Even when it’s "just a portfolio".

Because the habits you build in small projects
become the architecture you use in big ones.

Day 7 wasn’t about JSON.
It was about thinking like a product engineer.

And that’s the real milestone of this phase.

If you’re following along, the complete source lives here:
👉 GitHub Repository: Portfolio.

Top comments (0)