DEV Community

Cover image for LovedIn: A Case Study
Awoyemi Abiola
Awoyemi Abiola

Posted on • Edited on

LovedIn: A Case Study

Introduction

Hi, I'm Awoyemi Abiola, and this is my case study for the week 5 task of the Rise Academy Frontend track project - LovedIn, In this Case study, we'll cover what love challenges this project solves, who it solves it for, solution and UI design, technical structure and architecture of the project with HTML and CSS, and finally an overall reflection on collaboration and areas to improve. Let's dive in.

Problem Statement

In today's fast-paced digital world, expressing romantic interest has become increasingly complex and anxiety-inducing. Many individuals struggle with:

  • Finding the right words: The pressure of crafting the perfect romantic proposal or expression of interest often leads to missed opportunities or awkward encounters. People spend hours overthinking what to say, how to say it, and when to say it, which can result in never saying anything at all.
  • Personalization challenges: Generic romantic gestures often fail to capture the unique connection between two people, making them feel impersonal or insincere. A simple "Will you be my girlfriend/boyfriend?" text message doesn't convey the depth of thought and care that went into the decision.
  • Lack of memorable format: Traditional text messages or social media DMs lack the special, memorable quality that important relationship milestones deserve. These moments should be cherished and remembered, not lost in a sea of chat history.
  • LovedIn addresses these challenges by providing a structured, thoughtful, and personalized platform that takes the stress out of romantic proposals while maintaining authenticity and sincerity. It gives users the tools to express their feelings in a beautiful, memorable way.

The Primary target audience for LovedIn is a demographic of tech-comfortable young adults (18-35 years old) familiar with online dating culture and value creative and thoughtful expressions of affection.

Solution Design

To solve this problem, we designed a multi-page proposal website with:

  • Interactive Landing Page Experience
  • Personalized Information Collection via a form
  • An auto-generated and customized Proposal page

This flow was chosen to maintain a sense of emotional connection throughout the proposal creation process. Our users would not just be filling a form and getting a link but be crafting a thoughtful and romantic experience for their prospective partners.

UI Design System

Colors

The colour palette leans into romantic and affectionate tones. We aimed to create a visual mood that feels warm, gentle, and emotionally inviting. These colours were chosen to reflect love, softness, and intimacy without feeling loud or overwhelming.

  • Primary: #E22B3B [Scarlet Blush]
  • Secondary: #ED4779 [Wild Strawberry]
  • Accent: #FA88BB [Petal Frost]
  • Background: #F0D1D7 [Pink Carnation]
  • Support: #D86A77 [Blush Rose]


Typography

For fonts we sought after a font that was both expressive and somewhat simple, to balance romance with clarity and ensure emotional expression without sacrificing readability. After deliberation, we decided on Playfair Display for headings and Inter for body text.


HTML & Structural Approach

The website was built using semantic HTML to improve accessibility and SEO.

Key Semantic Elements Used

  • <header> for navigation and hero section
  • <main> for primary content
  • <section> for logical grouping
  • <footer> for closing content
  • <aside> for separate content

CSS Architecture

CSS Variables

To ensure consistency, I used CSS custom properties for colors, fonts, spacing values and transitions in a base css file shared across all pages in the application:

:root {
  /* ========== COLORS ========== */

  /* Primary Colors */
  --color-primary: #e22b3b;
  --color-primary-bg: #f0d1d7;

  /* Secondary Colors */
  --color-secondary: #ed4779;
  --color-secondary-bg: #fff6f8;

  /* Accent Colors */
  --color-accent: #fa88bb;

  /* Support Colors */
  --color-support: #d86a77;

  /* Neutral Colors */
  --color-white: #ffffff;
  --color-gray-50: #f9fafb;
  --color-gray-100: #f3f4f6;
  --color-gray-200: #e5e7eb;
  --color-gray-300: #d1d5db;
  --color-gray-400: #9ca3af;
  --color-gray-500: #6b7280;
  --color-gray-600: #4b5563;
  --color-gray-700: #374151;
  --color-gray-800: #1f2937;
  --color-gray-900: #111827;
  --color-black: #000000;

  /* ========== TYPOGRAPHY ========== */

  /* Font Families */
  --font-display: "Playfair Display", serif;
  --font-body: "Inter", sans-serif;

  /* Base Font Size */
  --font-size-base: 16px;

  /* Font Sizes - Type Scale */
  --font-size-xs: 0.75rem; /* 12px */
  --font-size-sm: 0.875rem; /* 14px */
  --font-size-md: 1rem; /* 16px */
  --font-size-lg: 1.125rem; /* 18px */
  --font-size-xl: 1.25rem; /* 20px */
  --font-size-2xl: 1.5rem; /* 24px */
  --font-size-3xl: 1.875rem; /* 30px */
  --font-size-4xl: 2.25rem; /* 36px */
  --font-size-5xl: 3rem; /* 48px */
  --font-size-6xl: 3.75rem; /* 60px */
  --font-size-7xl: 4.5rem; /* 72px */

  /* Heading Scales */
  --heading-h1: var(--font-size-5xl);
  --heading-h2: var(--font-size-4xl);
  --heading-h3: var(--font-size-3xl);
  --heading-h4: var(--font-size-2xl);
  --heading-h5: var(--font-size-xl);
  --heading-h6: var(--font-size-lg);

  /* Font Weights */
  --font-weight-normal: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;
  --font-weight-extrabold: 800;

  /* Line Heights */
  --line-height-tight: 1.25;
  --line-height-normal: 1.5;
  --line-height-relaxed: 1.75;

  /* ========== SPACING & SHAPES ========== */

  /* Spacing Scale - Padding/Margin */
  --spacing-xs: 0.25rem; /* 4px */
  --spacing-sm: 0.5rem; /* 8px */
  --spacing-md: 1rem; /* 16px */
  --spacing-lg: 1.5rem; /* 24px */
  --spacing-xl: 2rem; /* 32px */
  --spacing-2xl: 2.5rem; /* 40px */
  --spacing-3xl: 3rem; /* 48px */
  --spacing-4xl: 4rem; /* 64px */
  --spacing-5xl: 5rem; /* 80px */
  --spacing-6xl: 6rem; /* 96px */

  /* Border Radius */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-xl: 16px;
  --radius-2xl: 20px;
  --radius-full: 9999px;

  /* Border Widths */
  --border-width-thin: 1px;
  --border-width-medium: 2px;
  --border-width-thick: 4px;

  /* ========== SHADOWS ========== */

  --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
  --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
  --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
  --shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
  --shadow-colored: 0 6px 20px rgba(226, 43, 59, 0.25);
  --shadow-subtle: 0 0 0 3px rgba(226, 43, 59, 0.15);

  /* ========== TRANSITIONS ========== */
  --transition-fast: 150ms ease-in-out;
  --transition-base: 250ms ease-in-out;
  --transition-slow: 350ms ease-in-out;

  /* ========== LINEAR GRADIENTS ========== */
  --gradient-primary: linear-gradient(
    135deg,
    var(--color-primary-bg),
    var(--color-secondary-bg)
  );
  --gradient-secondary: linear-gradient(
    135deg,
    var(--color-secondary-bg),
    var(--color-primary-bg)
  );
  --gradient-transparent: linear-gradient(
    rgba(255, 192, 203, 0.6),
    rgba(255, 182, 193, 0.6)
  );
}
Enter fullscreen mode Exit fullscreen mode

This approach ensured consistency and cohesiveness for shared elements on the website, reducing repetition as much as possible.

Flex display was used across the application for a consistent layout and seamless responsiveness

  display: flex;
  align-items: center;
  justify-content: space-between;
Enter fullscreen mode Exit fullscreen mode

A particularly challenging component was the navigation bar. My initial implementation for the navbar was not in tune with semantic standards, or a non-repetitive HTML structure. This was fixed and improved to take all these into consideration, keeping all links as direct descendants of the nav element.

      <div class="navigation">
        <a href="index.html" class="logo">
          <img src="assets/images/logo.png" alt="LovedIn logo" width="200" />
        </a>

        <nav id="nav-links-container" aria-label="Main navigation">
          <a href="#features" class="navlink">Features</a>
          <a href="stories.html" class="navlink">Stories</a>
          <a href="login.html" class="btn btn-primary auth-btn navlink"
            >Sign In</a
          >
          <a href="index.html#get-started" class="btn btn-primary navlink"
            >Get Started</a
          >
        </nav>
      </div>
Enter fullscreen mode Exit fullscreen mode
.navigation {
  max-width: 1144px;
  margin: 0 auto var(--spacing-3xl);
  background: var(--color-secondary-bg);
  border-radius: var(--radius-full);
  padding: var(--spacing-md) var(--spacing-lg);
  display: flex;
  align-items: center;
  justify-content: space-between;
  box-shadow: var(--shadow-md);
}

#nav-links-container {
  display: flex;
  align-items: center;
  gap: var(--spacing-3xl);
}
Enter fullscreen mode Exit fullscreen mode

Visuals

Responsiveness

JavaScript Implementation

Our application's interactivity is powered by three vanilla ES6+ JavaScript files app.js, proposal.js, and stories.js each scoped to a specific page with no external libraries or frameworks.

app.js Home Page Logic

Handles the landing page's proposal form and hamburger navigation menu.

Proposal Form Submission

Captures the partner's name and relationship type, validates both fields, then redirects to proposal.html with the values encoded as URL query parameters. Incomplete submissions trigger an alert.

Modal & Sharing

After a valid URL is generated, a modal offers two options: share via the Web Share API (with a clipboard fallback) or preview the proposal. The modal can be closed by clicking outside it, pressing Escape, or using the close button.

Hamburger Menu

Toggles an active class on the nav container to show/hide links on mobile. Updates aria-expanded for accessibility. The menu closes automatically when a link is clicked or the user taps outside the nav.

proposal.js Proposal Page Logic

Powers the interactive experience recipients see when they open a shared proposal link.

URL Parameter Parsing

Reads name and type query parameters via URLSearchParams and dynamically updates the proposal heading (e.g. "Will you be my girlfriend, Sarah") if both values are present.

Yes / No Interaction

  • Yes hides the proposal state and reveals a celebratory success message.
  • No deliberately unclikable; moves to a random screen position on mouseenter or touchstart, making it playfully impossible to select.

Keyboard & Navigation

Escape navigates back to the previous page. A Back Home button in the success state redirects to the landing page.

stories.js Stories Page Logic

Dynamically renders the stories page from a local data array, simulating a backend data layer.

Mock Data

Stories are stored as an array of objects, each containing couple names, location, image URL, alt text, a quote, and a date.

DOM Rendering

On page load, the script iterates over the stories array and creates an <article> element for each entry using template literals, then appends it to the stories grid. No story content is hardcoded in the HTML.

Logic Flow

Journey Steps
Proposal Creation User fills form, app.js validates builds URL with query params, modal opens, user shares or previews
Proposal Experience Recipient opens link, proposal.js parses params, heading personalised Yes reveals success state; No escapes cursor
Stories Page Page loads,stories.js reads local array iterates stories, injects article cards into DOM

Edge Case Handling

Edge Case Handling
Empty form submission Alert shown; form not submitted
Missing URL parameters Heading update skipped; default placeholder shown
Web Share API unavailable Falls back to clipboard copy; uses native prompt as last resort
Modal elements not present All modal logic guarded with null checks
Stories grid not found Checks for grid container before populating
No button on touch devices Evasion triggered on both mouseenter and touchstart

Reflection

Overall, this was a very interesting project for me, I learnt a lot about collaboration with Git and Github, and even more about standards for writing semantic HTML, and structured design systems with CSS.

That said, collaboration did not come without its challenges, particularly around maintaining a standardized approach to implementing features and pages on the application due to differing perspectives for each collaborator, we were able to overcome this via clear and concise discussions and meetings before and throughout the task delivery processes, where I properly communicated to my partner, and her to me, clear and concise requirements for each week's task.

In a version 2.0, I would work towards improving semantics and optimizing SEO and accessibility for the project to near perfection, as these are the areas we received feedback for improvement.

Contributors

This project was developed collaboratively with;

You can view their version of this case study here

Special thanks to Sophia Ahuoyiza - Github for issue submissions and feedback which helped greatly improve this project.

Top comments (0)