Components should not own the content
A portfolio becomes difficult to maintain when project titles, biography sentences, and blog excerpts live inside JSX. The UI starts to look like a brochure that can only be edited by a developer who remembers which file holds which paragraph.
A better split is:
Data → types → access functions → components → pages
Why this matters before a CMS exists
You do not need Supabase on day one. You do need a boundary.
If pages call getProjects() instead of importing a hardcoded array inside a card component, you can later replace the local data source without rewriting the grid, the filters, or the case study layout.
The UI does not need to know whether the function reads a TypeScript file or a PostgreSQL table.
Server Components first
For a mostly static site, React Server Components are the default. They can fetch content, render HTML, and keep client JavaScript limited to theme toggling, menus, and forms.
Client components are for interaction. They are not a place to hide data fetching because it felt convenient.
Metadata belongs with the route
Title, description, canonical URL, and Open Graph data should be generated from the same content that the page renders. If a project title changes, the metadata should change with it.
That is another reason content needs a typed access layer. SEO should not be a second copy of the truth.
Static now, cached later
A portfolio can be statically generated while the data is local. When a database appears, the public site can still be cached and revalidated. Visitors should not pay for an admin-only write path.
The public website and the future dashboard can share types without sharing rendering.
Related articles

Understanding OpenTelemetry
A practical introduction to traces, metrics, and why instrumentation should be part of the service, not a later operations task.

From commit to container with GitHub Actions
A compact CI path for Java services: build, test, package with Docker, and keep secrets out of the repository.
