Skip to content

SimplyCodes · Demand.io/Professional

Building the SimplyCodes blog on a shared Contentful platform

How I built the SimplyCodes blog frontend on a shared Contentful API, with server-rendered articles, typed data, and cached requests.

Role
Primary front-end implementer
Period
July 2024 to February 2025

Context

SimplyCodes needed a blog without making the web application fetch, reshape, and filter raw CMS data. Other company products published similar content, so rebuilding the same model and delivery path for every site would duplicate engineering and infrastructure work.

I was the primary frontend implementer for SimplyCodes. The team built the backend. I turned its Contentful-backed API into the blog index and article pages, including responsive layouts, rich-content rendering, navigation, metadata, and tracked product links.

The work began with the initial Contentful frontend in July 2024. The migration continued in stages until the application moved to Contentful-only article loading in February 2025.

The architectural boundary

We kept CMS access out of the browser. The frontend requested a product-facing blog API that the team built and operated.

Contentful
    |
    v
Team-built blog API
    +-- apply product filters
    +-- paginate article lists
    +-- normalize shared response shapes
    +-- cache API responses
    |
    v
Nuxt frontend
    +-- render index and article pages
    +-- compose product-specific widgets
    +-- generate navigation and metadata
    +-- measure acquisition interactions

This boundary kept credentials and CMS query details out of the client. It also allowed the backend to filter by category or content pillar before returning a page of results, rather than sending the complete article collection to every visitor. The API routes sat behind shared response caching, reducing repeated work against the origin.

Reusing the blog shape

We treated an article as a company-level contract rather than a SimplyCodes-only object. Shared TypeScript definitions described article lists, authors, images, categories, pillars, metadata, and full article responses. The same shared package also contained blog contracts for another company product.

On the SimplyCodes frontend, I consumed those contracts directly in the query and presentation layers. This gave the frontend and backend one vocabulary while still leaving room for product-specific rendering. SimplyCodes could add its own widgets and visual treatment without forking the underlying author and article shapes.

This reuse avoided duplicate work. Teams did not need to model the same blog concepts for each product, and the centralized backend handled filtering and caching once instead of repeating that work in every frontend. We did not record a defensible dollar amount, so I am not attaching a financial figure to the saving.

Implementing the reader experience

The frontend had two primary surfaces: an index for discovery and an article page for reading.

The index translated the current route into category and pillar filters, then sent those filters to the API. Server-side prefetching made the initial article set available in rendered HTML, while cursor-based pagination supported loading more without downloading the entire catalogue. Featured content, article cards, and editor's picks were composed from the same typed responses.

The article page combined the normalized response with a responsive three-column layout. Depending on viewport size, readers received a persistent or mobile table of contents, the article body, editor's picks, author context, recent articles, and sharing controls. I separated article presentation data into a composable so date formatting, reading time, author details, image selection, and canonical URL construction did not accumulate inside the page component.

[Image: SimplyCodes blog index and article page shown at desktop and mobile sizes]

Rendering structured content safely

Contentful rich text needed to support more than paragraphs and images. The renderer mapped structured entries to reusable Vue components, with SimplyCodes-specific extensions for interactive or data-rich content. This allowed editors to compose richer articles while the frontend retained control over markup and presentation.

Embedded blocks also exposed a migration edge case: a block-level widget entered as inline content could produce invalid nested HTML and hydration problems. The query layer normalized those entries before rendering, converting known block-level widgets into the correct rich-text node type. That defensive step protected server rendering without forcing the page component to understand malformed CMS structure.

The table of contents was generated from article headings. I later corrected its labels and deduplication behavior so repeated or formatted headings still produced useful navigation rather than ambiguous links.

Preserving search and SEO behavior

A CMS migration is not complete when article text appears on screen. Blog pages also had to remain useful as search entry points.

I integrated canonical URLs, page titles, descriptions, Open Graph fields, Twitter cards, publication and modification timestamps, and structured article data into the Nuxt rendering path. Because articles were prefetched during server rendering, crawlers and link previews did not depend on a client-only request to understand the page.

I also improved movement through the blog with breadcrumbs, search access, tables of contents, editor's picks, and recent-article links. These features connected migrated content to the rest of the product instead of treating the blog as an isolated CMS output.

Connecting content to growth

The blog also directed readers to the product. After the initial migration, I added product placements and campaign attribution to their calls to action.

This made those placements measurable without mixing growth logic into the content model. Contentful remained responsible for editorial structure, the frontend controlled the interaction and presentation, and attribution parameters connected selected calls to action to the analytics path.

Outcome

The result was a Contentful-backed blog frontend that could render structured articles, product-specific embeds, responsive navigation, and search-oriented metadata on top of a team-built API.

The architecture reduced duplicated implementation across products by sharing blog contracts. Filtering, pagination, and caching also reduced work before responses reached the frontend. SimplyCodes used the same API for editorial reading and tracked paths back into the product.

This case study does not claim a specific traffic increase, cache-hit rate, publishing-time reduction, or dollar saving because those records are not available. The implementation evidence supports a technical outcome. Shared contracts reduced product-specific code, while backend filtering and caching reduced data transfer and repeated origin work.

Reflection

The shared API handled CMS access while SimplyCodes controlled its presentation. That division mattered more than any single component.

Keeping Contentful access, normalization, filtering, and caching behind the API made the frontend simpler and gave other products reusable code. Keeping rendering and acquisition behavior in SimplyCodes let me build for its readers without forcing every product into the same interface.

If I approached the migration again, I would add explicit parity checks for URLs, metadata, embeds, and heading structure at the start of the cutover. Those checks would make migration safety as visible and repeatable as the typed contracts that supported the final experience.

Technologies

  • Contentful
  • Nuxt
  • Vue
  • TypeScript

Skills used

  • Front-end architecture
  • CMS integration
  • Technical SEO
  • Growth engineering
WorkAll case studies

More