Cruise ship sailing at golden hour
OpenSense LabsFrontend Developer

INSPIRATIONAL
CRUISE

Role

Frontend Developer

Timeline

8 Months

Platform

Drupal + React (Decoupled)

Role & Contribution

What I Delivered

Built the Inspirational Cruise tourism site from scratch — architecting a decoupled Drupal setup where React components handle specific frontend routes, are embedded as Drupal blocks, and are composed through Layout Builder by the editorial team for full post-delivery content control.

  • check_circleDesigned a decoupled architecture: React components handle key UI routes, compiled and embedded into Drupal as custom blocks.
  • check_circleIntegrated backend APIs into React components for live cruise itineraries, destination data, and availability — fully driven from BE.
  • check_circleConfigured Layout Builder with the React-backed blocks, giving editors the power to build and update pages without developer involvement.
  • check_circleEngineered formatting pipelines for transactional communications, designing responsive HTML emails for booking confirmations and dynamic PDF generation for articles and itineraries.
Key Achievement

Architecture

Decoupled

trending_up

"React routes embedded as Drupal blocks, composed through Layout Builder — editorial freedom without sacrificing frontend control." — Developer

Architectural Solution

merge_type

Decoupled React in Drupal Blocks

Architected a decoupled pattern where specific React components handle frontend routes independently, then are compiled and registered as Drupal blocks — bridging modern React UX with Drupal's content and permissions layer.

view_quilt

Layout Builder for Editorial Control

Registered the React-backed blocks within Drupal's Layout Builder, enabling the content team to assemble, rearrange, and publish pages post-delivery — with zero developer involvement for routine content updates.

api

Backend API Integration

Integrated cruise itinerary, destination, and availability data from backend APIs into React components — with loading states, error boundaries, and response caching to ensure consistent UX even under variable API latency.

accessibility_new

Accessibility & Performance

Improved WCAG 2.1 compliance across the component library — keyboard navigation, ARIA roles, focus management — alongside performance gains through lazy loading and optimised React bundle delivery.

palette

Editor-Controlled Dynamic Styling

Engineered a dynamic theming system where content editors pick accent colours and style options directly in Drupal fields — the frontend maps these values to CSS custom properties, making every event page visually unique without touching code.

Innovation Spotlight

Key Features

Cruise destination listing with API-driven content

Decoupled Cruise Engine

route

Engineered a dedicated React frontend engine for cruise exploration. It securely queries backend booking APIs for live itineraries, cabin availability, and pricing — rendering lightning-fast, paginated results independent of the CMS lifecycle.

Drupal Layout Builder with React blocks

Hybrid Layout Builder

dashboard_customize

Transformed Drupal's Layout Builder into a hybrid composition tool. Content editors can drop high-performance React applications (packaged as custom blocks) directly into marketing layouts, marrying rich interactive features with editorial freedom.

Dynamic colour coded landing page

Content-Driven Theming

format_paint

Built a clever styling bridge where editors define accent colours via Drupal fields on specific landing pages. The Drupal theme layer parses these and injects CSS custom properties to dynamically reskin React components on the fly, entirely code-free.

Digital document and email template representation

Automated PDF & Email Systems

picture_as_pdf

Designed and integrated robust automated document pipelines — producing fully-responsive, heavily-styled HTML emails for booking confirmations and dynamically generating polished, downloadable PDFs for cruise itineraries and long-form articles.

speed

Performance Metrics

Performance

+35%
↑ Post-optimisation

Frontend speed gain

Accessibility

AA
↑ Full compliance

WCAG 2.1 compliant

LCP

<2.5s
↑ from 4.3s

Largest Contentful Paint

Architecture

Decoupled

React + Drupal hybrid

Technical Highlights

The core architectural challenge was bridging React's component model with Drupal's block and layout system — so editors could assemble pages visually while React handled the interactive, API-driven UI. Every technical decision served that boundary.

codeReact-to-Drupal Block Bridge

Each React app is compiled to a self-contained bundle, registered as a Drupal custom block with a mount point, and hydrated client-side. This pattern kept React and Drupal concerns cleanly separated while making every component available in Layout Builder.

cachedAPI Response Caching in React

Backend API calls in React components are wrapped with a lightweight cache layer — preventing duplicate requests across block re-renders and Layout Builder previews, keeping the editorial experience fast and the API load minimal.

CruiseBlock.jsx
// React component registered as a Drupal block
// Drupal renders <div id="cruise-listings" /> in the block template
// React hydrates it client-side with API data

import { useEffect, useState } from 'react';

export default function CruiseListings({ apiEndpoint, limit = 9 }) {
  const [cruises, setCruises] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch(`${apiEndpoint}?limit=${limit}`)
      .then(r => r.json())
      .then(data => { setCruises(data); setLoading(false); })
      .catch(() => setLoading(false));
  }, [apiEndpoint, limit]);

  if (loading) return <CruiseSkeleton count={limit} />;

  return (
    <ul className="cruise-grid" role="list">
      {cruises.map(c => <CruiseCard key={c.id} cruise={c} />)}
    </ul>
  );
}

Lessons Learned

01

Decoupled Doesn't Mean Disconnected

React and Drupal need clear contracts at their boundary. Defining the block mount point, data props, and hydration strategy upfront prevented integration rework that would have consumed the final sprint.

02

Layout Builder Changes the Scope Conversation

Once editors could build pages themselves via Layout Builder, they stopped requesting developer changes for content updates — which freed the team to focus on new feature delivery rather than routine maintenance.

03

API Errors Need UI Contracts Too

Backend API failures during build caused blank React components in Layout Builder previews. Adding error boundaries and skeleton states made failures visible and manageable — not silent and confusing for editors.

04

Accessibility in Hybrid Architectures Needs Extra Attention

When React manages focus and Drupal manages routing, focus management can fall through the gap. Explicitly handling focus restoration after React-driven route transitions was essential for WCAG 2.1 keyboard compliance.

Ready to Build?

From complex backend architecture to award-winning front-end experiences. Let's build the future together.