Advanced Interactive Design / Final Thematic Website

25/6/2026 - 31/7/2026 (Week 10 - Week 15)

Chang Wing / 0367807 

Advanced Interactive Design / Bachelors of Design (Honours) in Creative Media / Taylor's University

Final Thematic Website


TABLE OF CONTENTS




INSTRUCTIONS





PROCESS DOCUMENTATION


Backup Changes at GitHub

I set up a GitHub repository to backup my website and keep track of different versions of the code. Since I used Antigravity as an AI coding assistant, the generated changes after each prompt could sometimes introduce errors / affect existing code. GitHub allows me to review previous versions and restore earlier codes if errors emerge after Antigravity made changes to the codes.

Figure 1.1 Setup GitHub Repository

I also prompted:

enforce GitHub security best practices, prevent exposing API keys, avoid committing sensitive files, check .gitignore

in Antigravity so it would follow these security practices whenever it generated, modified, or prepared code for Git commits and GitHub uploads.

I also prompted Antigravity to set up a .gitignore file to exclude unnecessary files, such as dependency folders, temporary files, system files and env. files containing sensitive information to reduce unnecessary storage.



Coding with Google Antigravity

I subscribed to the RM97.99/month Google AI Pro plan as the free usage limit was not sufficient for my development needs and used Google Antigravity as an AI coding assistant to support my website development process.


Figure 1.2 My Google Antigravity workspace


Since I was new to setting up a website, whenever I encountered something confusing, I tried to understand the logic behind it to build a better understanding of how things work, this make easier to prevent issues and troubleshoot later on because if AI doesn't know what to fix, I can fix manually. Few examples of questions asked shown in Figure 1.3 & 1.4.


Figure 1.3 Asking for clarification 


Figure 1.4 Asking for clarification


To save tokens and avoid hitting the usage limit before it refreshes, I asked Gemini to generate markdown files whenever necessary for Antigravity. This helps me provide clearer instructions to Antigravity while reducing the number of prompts needed during the coding process.


Figure 1.5 Google Gemini generated Markdowns for Google Antigravity


Figure 1.6 Correcting Markdown prompts generated by Google Gemini


Splash Screen

The code generated by AI was not always perfect, possibly due to limitations in my prompts or the AI's interpretation. I had to manually adjust the CSS styles to better align the UI with my Figma prototype and refine the animations. Figure 1.7 & 1.8 below show the splash screen before and after the manual CSS adjustments:

Figure 1.7  Splash screen before the manual CSS adjustments


Figure 1.8 Splash screen after the manual CSS adjustments


Figure 1.9 Screenshot of CSS adjustments process


Figure 1.10 Screenshot of CSS adjustments process

Figure 1.11 Final Splash Screen design (Colours may vary slightly from the actual website)



Food Page

To help the AI identify the correct food, signboard and landmark SVGs more accurately while keeping the assets organised, I renamed all the files according to the names of the 14 states.

Figure 1.12 Renaming SVG files


Markdown prompt (AI-generated and revised by me) gave to Antigravity to generate the Food Page (home page).

📌 Task Overview
Implement the transition logic from the Splash Screen to the Home Screen Map Interface upon clicking "- Click to Start -". Build the Home Screen UI, interactive map route, horizontally scrollable state highlight card carousel for all 14 Malaysian states/territories, and entrance transitions.

CRITICAL CARD COMPOSITION DIRECTIVE:
Each `.state-card` is a relative container holding 3 OVERLAPPING SVGs (`food.svg`, `signboard.svg`, `landmark.svg`) stacked using absolute positioning to form a single cohesive visual unit:
  1. Base Layer (`food.svg`): Circular food plate placed on the left (`position: relative` or `absolute; left: 0; bottom: 0; z-index: 1`).
  2. Middle Layer (`landmark.svg`): Landmark badge positioned at the bottom-right (`position: absolute; right: 0; bottom: 10px; z-index: 2`).
  3. Top Layer (`signboard.svg`): Blue state signboard badge positioned at the top-right (`position: absolute; right: 15px; top: 0; z-index: 3`).

Target Path: /Users/torpedo/Downloads/AdvancedInteractiveFinalWebsite
Canvas Size: Fixed 1440px × 800px (16:9 Aspect Ratio)
Font Setup: 
  - Primary UI & Nav Font: 'Lilita One' (Regular, 32px, #FFFFFF) for Navbar Links & Title
  - Body & Auxiliary UI: 'Sniglet' (Regular, #FFFFFF)
Global Timing Function: ease-in-out for all entry, exit, slide transitions, and idle loops.

==========================================================================
📁 ASSET FILE NAMING CONVENTION & DIMENSIONS (public/assets/)
==========================================================================
All vector illustrations are located in `public/assets/` following this schema:

1. State Highlight Card Assets (14 sets total):
   - Food Illustration (`[statename]-food.svg`): width: ~328px; height: ~335px;
   - State Signboard (`[statename]-signboard.svg`): width: ~172px; height: ~143.5px;
   - State Landmark (`[statename]-landmark.svg`): width: ~151px; height: ~137px;

   Exact State Slugs:
   `perlis`, `kedah`, `penang`, `perak`, `selangor`, `kuala-lumpur`, `negeri-sembilan`, `melaka`, `johor`, `pahang`, `terengganu`, `kelantan`, `sabah`, `sarawak`

2. Map & Pin Assets:
   - Blue Route Line: `public/assets/map-route.svg`
   - Active Red Location Symbol: `public/assets/map-location-symbol.svg`

==========================================================================
⚠️ CRITICAL UI PROTECTION DIRECTIVE (DO NOT OVERRIDE CSS)
==========================================================================
- DO NOT ALTER OR DELETE any existing CSS UI rules, color variables (`:root`), border styling, or container dimensions from `style.css`.
- Preserve existing border colors, button styling, toggle switch styles, and card container definitions exactly as configured.
- Only ADD new classes or append missing keyframes needed for the Home Screen Map Interface without mutating established base styling.

==========================================================================
1. TRANSITION SEQUENCE (Splash Screen -> Home Screen)
==========================================================================
When the user clicks the `.start-button-ui` ("- Click to Start -"):

1. Splash Screen Exit (Reverse Entrance Animations):
   - Reverse entrance animations over 1.2s (`ease-in-out`) to clear splash screen assets:
     * Logo: Slides back UP
     * Top Cloud: Slides back LEFT
     * Right Cloud: Slides back RIGHT
     * Left Cloud: Slides back LEFT
     * Nasi Lemak Plate: Slides back OUT to the left edge
     * Hibiscus Flower: Slides back OUT to the right edge
     * Flag: Slides back OUT to the right edge
   - Keep warm amber background (`#F6A51E`) intact throughout transition.

2. Full-Screen Transition Rider Animation:
   - Mount/Animate `.transition-scooter-container` holding `public/assets/transition-scooter.gif`:
     * Container Dimensions: `width: 831px; height: 584px;`
     * Motion Path: Drives across canvas from far left off-screen (`translateX(-900px)`) to far right off-screen (`translateX(1500px)`) over 1.2s (`ease-in-out`).
     * Behavior: Hidden (`display: none`) immediately once out of frame.

3. Home Screen Entrance:
   - Mount/Show Home Screen container (`#home-screen`) as transition scooter exits.
   - Top Navigation Bar (`.home-nav`): Slides down from `top: -80px` to `top: 0px` over 0.6s (`ease-in-out`).
   - Route Path & Carousel: Slides in from the right (`translateX(100%)` to `translateX(0)`) over 0.8s (`ease-in-out`).
   - Small Route Scooter (`.route-scooter-container` holding `public/assets/route-scooter.gif`):
     * Container Dimensions: `width: 202px; height: 142px;`
     * Entrance: Drives in from `translateX(-300px)` to `translateX(120px)` over 1.0s (`ease-in-out`), settling statically on top of the starting state (Perlis).

==========================================================================
2. HOME SCREEN LAYOUT STRUCTURE & STACKING HIERARCHY
==========================================================================

A. Fixed Top Navigation Bar (.home-nav)
   - Height: 80px | Width: 100% | Background: Transparent
   - Left: Logo asset (`public/assets/nav-logo.svg` or placeholder) + Text: "Malaysian Food Adventure" (Font: 'Lilita One', 32px, #FFFFFF).
   - Center Navigation Links: Horizontal list (`Food` | `About` | `Story` | `Guide`).
     * Style: Font: 'Lilita One', 32px, White `#FFFFFF`.
     * Hover: Subtle text glow / scale up (`transform: scale(1.05)` with `ease-in-out`).
   - Right Utility:
     * Music Control: "Music On" label + Pill Switch
     * Music Note Icon Placeholder (`<div class="music-icon-placeholder"></div>`).

B. Main Horizontal Food Route / Route Map (.map-route-container)
   [Z-INDEX STACKING HIERARCHY]:
   
   - Layer 1 (z-index: 1 - Background Route Path): 
     * SVG Image: `<img src="public/assets/map-route.svg" class="map-route-svg" />`
     * MUST sit visually BEHIND the food card carousel (`z-index: 1`).
     
   - Layer 2 (z-index: 2 - Active Location Pin): 
     * SVG Image: `<img src="public/assets/map-location-symbol.svg" class="map-pin-svg" />`
     * Position: Dynamically translates along coordinate nodes (14 waypoint nodes) on `map-route.svg` when a state card is selected or scrolled into view.
     
   - Layer 3 (z-index: 3 - Small Route Scooter - `.route-scooter-container`):
     * Dimensions: `width: 202px; height: 142px;`
     * Holds `public/assets/route-scooter.gif` at active state location.
     * NO CSS IDLE VIBRATION: Do NOT apply any `@keyframes` vertical oscillation (`translateY`) to this container.
     
   - Layer 4 (z-index: 10 - State Cards Horizontally Scrollable Carousel): 
     * Flex container with horizontal scrolling enabled (`overflow-x: auto`, `scroll-snap-type: x mandatory`).
     * Only 2 to 3 state cards are rendered in visible viewport at a time.
     
     * OVERLAPPING COMPOSITION CSS FOR `.state-card`:
       ```css
       .state-card {
         position: relative;
         width: 420px;
         height: 380px;
         flex-shrink: 0;
         scroll-snap-align: center;
       }

       /* Base Layer - Food Plate */
       .card-food-svg-container {
         position: absolute;
         left: 0;
         bottom: 0;
         width: 328px;
         height: 335px;
         z-index: 1;
       }

       /* Middle Layer - Landmark Badge */
       .card-landmark-svg-container {
         position: absolute;
         right: 10px;
         bottom: 20px;
         width: 151px;
         height: 137px;
         z-index: 2;
       }

       /* Top Layer - State Signboard */
       .card-signboard-svg-container {
         position: absolute;
         right: 30px;
         top: 10px;
         width: 172px;
         height: 143.5px;
         z-index: 3;
       }

       .card-food-svg-container img,
       .card-landmark-svg-container img,
       .card-signboard-svg-container img {
         width: 100%;
         height: 100%;
         object-fit: contain;
       }
       ```

     * Card HTML Template:
       ```html
       <div class="state-card" data-index="0" data-state="perlis" data-pin-x="180" data-pin-y="340">
         <div class="card-food-svg-container">
           <img src="public/assets/perlis-food.svg" alt="Perlis Food" />
         </div>
         <div class="card-landmark-svg-container">
           <img src="public/assets/perlis-landmark.svg" alt="Perlis Landmark" />
         </div>
         <div class="card-signboard-svg-container">
           <img src="public/assets/perlis-signboard.svg" alt="Perlis Signboard" />
         </div>
       </div>
       ```

     * Complete List of 14 Cards:
       1. Perlis (`perlis-food.svg`, `perlis-landmark.svg`, `perlis-signboard.svg`)
       2. Kedah (`kedah-food.svg`, `kedah-landmark.svg`, `kedah-signboard.svg`)
       3. Penang (`penang-food.svg`, `penang-landmark.svg`, `penang-signboard.svg`)
       4. Perak (`perak-food.svg`, `perak-landmark.svg`, `perak-signboard.svg`)
       5. Selangor (`selangor-food.svg`, `selangor-landmark.svg`, `selangor-signboard.svg`)
       6. Kuala Lumpur (`kuala-lumpur-food.svg`, `kuala-lumpur-landmark.svg`, `kuala-lumpur-signboard.svg`)
       7. Negeri Sembilan (`negeri-sembilan-food.svg`, `negeri-sembilan-landmark.svg`, `negeri-sembilan-signboard.svg`)
       8. Melaka (`melaka-food.svg`, `melaka-landmark.svg`, `melaka-signboard.svg`)
       9. Johor (`johor-food.svg`, `johor-landmark.svg`, `johor-signboard.svg`)
       10. Pahang (`pahang-food.svg`, `pahang-landmark.svg`, `pahang-signboard.svg`)
       11. Terengganu (`terengganu-food.svg`, `terengganu-landmark.svg`, `terengganu-signboard.svg`)
       12. Kelantan (`kelantan-food.svg`, `kelantan-landmark.svg`, `kelantan-signboard.svg`)
       13. Sabah (`sabah-food.svg`, `sabah-landmark.svg`, `sabah-signboard.svg`)
       14. Sarawak (`sarawak-food.svg`, `sarawak-landmark.svg`, `sarawak-signboard.svg`)

C. Bottom Pagination Bar (.bottom-pagination)
   - Position: Absolute, bottom 40px, horizontally centered (`left: 50%`, `transform: translateX(-50%)`).
   - Content: Row of 14 circular pagination dots (`width: 12px`, `height: 12px`, white with 50% opacity).
   - Active Indicator: Active dot expands into rounded capsule/pill shape (`width: 32px`, `opacity: 1`, `#FFFFFF`, `transition: all 0.3s ease-in-out`).

==========================================================================
3. IDLE & INTERACTION ANIMATIONS (script.js & style.css)
==========================================================================
1. Route Scooter State: Static CSS coordinates after drive-in sequence completes.
2. Food Plate Cards Floating: Gentle breathing float for circular state cards (`translateY(-6px)` to `0px` every 4s `ease-in-out`). Apply float to `.state-card` wrapper so all 3 composite SVGs move together seamlessly.
3. Card Hover Effect: Hovering over any `.state-card` scales the entire composite unit up smoothly to 108% (`transform: scale(1.08)`) over 0.3s using `ease-in-out`.
4. Interactive State Selection, Horizontal Scrolling & Map Pin Movement:
   - On Scroll / Drag / Dot Click:
     * Determine active state centered in view.
     * Update bottom pagination dots (activate corresponding 1 of 14).
     * Animate Red Pin (`public/assets/map-location-symbol.svg`): Translate smoothly to target node coordinate on blue route over `0.4s ease-in-out`.
     * Apply subtle arrival bounce (`scale(1.2)` to `scale(1.0)`).

==========================================================================
4. CODE & ARCHITECTURE REQUIREMENTS
==========================================================================
- Google Fonts Import: Guarantee `@import url('https://fonts.googleapis.com/css2?family=Lilita+One&family=Sniglet:wght@400;800&display=swap');` is present in `style.css`.
- Timing Function Standard: Apply `ease-in-out` across all CSS transitions and animations.
- Relative Overlapping Sizing: Enforce `.state-card` relative positioning with z-indexed child wrappers (`z-index: 1` food, `z-index: 2` landmark, `z-index: 3` signboard) to replicate exact overlapping design.
- Scrollable Carousel CSS: Set `.state-card-carousel` to `display: flex; overflow-x: auto; flex-wrap: nowrap; scroll-snap-type: x mandatory;` with hidden scrollbars.
- Two-Scooter Container Classes: Ensure `.transition-scooter-container` (831px × 584px) and `.route-scooter-container` (202px × 142px) are defined separately.


NOTE: I noticed that after submitting a new prompt, Antigravity would sometimes overwrite the manual CSS refinements I had already made by reverting parts of the code to an earlier generated version. To prevent this, I explicitly informed the AI about my manual changes and instructed it to inspect the latest style.css before making further modifications. This helped preserve my existing work while allowing Antigravity to build on the most up-to-date version of the project.

Example prompt: "I have updated style.css and index.html."

and MAKE SURE pushed commit to GitHub.


Figure 1.13 below shows the first homepage generated using the Markdown prompt, although it followed the overall requirements, the composition and layout were not as intended. I had to refine the prompt and manually adjust the generated code to align the UI with my Figma prototype.


Figure 1.13 First homepage generated using the Markdown prompt, very weird composition


Figure 1.14 Manual coding process

Figure 1.15 Final Food Page design (Colours may vary slightly from the actual website)



Pagination Bar (Food Page)

The bottom pagination bar was designed with several UX-friendly micro-interactions to create a ease navigation experience across all 14 Malaysian states. The active pagination indicator expands from a 12px circle into a 32px pill to provide clear visual feedback of the user's current position.

To prevent jittery transitions when users quickly move their cursor across multiple pagination dots, a 130ms hover debounce was implemented in JavaScript so that state transitions only occur when the cursor intentionally pauses over a target. When a pagination dot is hovered for 130ms or clicked, multiple interface elements are synchronised simultaneously:
  • The carousel scrolls to the selected state card,
  • The map location pin moves to the corresponding destination with a bounce animation
  • The route scooter travels to the selected location and automatically flips direction based on its movement
  • The active pagination indicator updates accordingly
In addition, subtle hover feedback was added by slightly scaling the pagination dot using transform: scale(1.3) to provide immediate visual confirmation while preserving a minimal interface without excessive visual effects.

Figure 1.16 Pagination bar in Food Page



Music Control Panel

To allow users to conveniently control the website’s BGM, a side panel was added so users could easily manage the music such as switching or pausing songs and turning the BGM on or off.

The AI-generated version (Figure 1.17) did not have the correct composition or elements compared to my Figma UI design, so I manually adjusted the CSS and worked with AI to make further corrections until it matched my intended design.


Figure 1.17 First hamburger menu generated using Markdown prompt, weird looking


Figure 1.18 Figma Version


Figure 1.19 Final Music Control Panel design (Colours may vary slightly from the actual website)


UX Consideration: 

-The currently playing song will automatically scroll into view when the hamburger menu is opened, ensuring it is always visible to the user

- When users click the pause button in the music control panel, the song pauses without turning off the BGM toggle, allowing them to resume the same song easily

Figure 1.20 Follow up AI prompts for Antigravity to make correction



Randomised BGM

I wanted users to hear "Terukir Di Bintang" by Yuna the first time they visit the website, as I felt it was the most suitable track for introducing the overall mood of the website. Using a consistent song for the first visit also gives users a more intentional introduction to the website rather than immediately introducing randomness.

After the first visit, the BGM is randomised from the 12-track playlist whenever users return to or reload the website, this adds an element of surprise so the experience feels slightly different each time instead of becoming repetitive, it also encourages users to discover the different songs included in the playlist.


AI Prompt:

Configure the background music (BGM) system logic so that:
1. First-Ever Visit (New Device/Laptop): Plays the designated default track (`terukir-bintang.mp3`) on initial site load.
2. Subsequent Visits (Same Laptop/Browser): Randomly selects and plays 1 song from the 12-track playlist every time the user opens or reloads the website from then on. 




Food Detail Page

After selecting a food from the Food Page, users will be directed to its corresponding Food Detail Page, where they can learn more about the dish, including its background and its ingredients.


Figure 1.21 Food Detail Page (Figma Design)


Summarised prompt gave to Antigravity:

1. Visual Layout & Design System

  • Typography ('Lilita One' and 'Sniglet').
  • 2-Column Layout:
    • Left Section (.dish-left-content): Positioned at left: 100px, top: 140px. Houses the curved directive text, 460px dish plate SVG (detail-nasi-lemak.svg), location signboard badge (kuala-lumpur-signboard.svg), and ingredient inspector overlay.
    • Right Section (.dish-right-content): Positioned at left: 720px, top: 160px with width 492px. Houses the Nasi Lemak title (56px Lilita One), body description (font-size: 21px, line-height: 26px, margin-bottom: 50px), and dark pill "It's Story →" CTA button.

2. Navigation & History Rules

  • Top Bar Action Controls:
    • Top-Left Back Button: Styled matching .about-back-btn (80px dark circular button). Triggers window.history.back() to return to the food map.
    • Top-Right Hamburger Button: Opens the Navigation Side Drawer
  • Click Trigger: Restricted exclusively to clicking the Kuala Lumpur food SVG plate.
  • Back Navigation to Food Page:
    • Static Placement (No Carousel Slide): Instantly retains the active card, character position, red map pin, and scroll position without sliding or scrolling animations.
    • Scoped Entrance Animations: Entrance slide keyframes are scoped exclusively to the initial Splash Screen start sequence.

3. Entrance Motion & Animation Physics

  • Dish Plate SVG Entrance: Spins counter-clockwise (rotate(-120deg)rotate(0deg) with spring overshoot) while sliding inward from off-screen left (translateX(-420px)translateX(0)).
  • Location Signboard Badge: Slides up from bottom frame (translateY(220px)translateY(0)).
  • Curved Hover Directive Text: Tilts and rotates counter-clockwise from rotate(20deg) to rotate(-12deg).
  • Right Content Column: Slides inward from off-screen right (translateX(520px)translateX(0)).
  • Solid Opacity (No Fade-In): Elements slide in at solid opacity: 1 throughout motion (using animation-fill-mode: both to prevent pre-render content flashes).

4. Interactive Ingredient Inspector & Overlay

  • Hover Trigger: Smooth opacity fade (opacity: 0opacity: 1 over 0.3s ease-in-out) when hovering over the dish plate SVG container.
  • Minimalist Text Labels:
    • Pure white (#FFFFFF) 'Sniglet' font (18px, bold, text-shadow) with NO white background pill containers, boxes, padding, or drop shadows.
    • Multiline formatting:
      • "Coconut<br>Milk Rice"
      • "Egg"
      • "Fried<br>Anchovies"
      • "Sambal<br>(Chilli<br>Sauce)"
      • "Cucumber"
  • 2px SVG Bent Pointer Lines: Clean 2px white stroke vector lines with distinct degree angle elbows and varying line lengths routing from text to target ingredients.
  • 10px Hollow Target Dots: Lines terminate cleanly at the outer perimeter outline of 10px circular white dots (r="4", stroke 2px, no fill inside).

5. Curved Text

    • The curved prompt text "Hover to view ingredients!" should be positioned above the food SVG plate with the following layout and transformation properties:
      • Curved Arc Angle Rotation: The text is rotated counter-clockwise using a CSS transform (transform: rotate(-12deg)), giving it a tilted, curved appearance over the top-left portion of the plate.
      • Positioning: It is absolutely positioned inside the left content container directly above the large dish SVG (at approximate coordinates top: 20px; left: 40px)


    The position and container wrapper sizes generated by the AI are not precisely accurate as in the Figma design, so I proceed to manually make changes in the CSS codes:

    Figure 1.22 Manually adjusting CSS in VS code


    Figure 1.23 Manually adjusting CSS in VS code



    The placement of the ingredient labels and their pointer line need tweaking as well, 


    Figure 1.24 AI-generated version

    Figure 1.25 Figma Version


    After asking AI the meaning of the codes generated, I proceed to make changes in CSS code to adjust the ingredient labels and their pointer line


    Figure 1.26 AI explanation of CSS code of the SVG Pointer Line and Target Dot

    Figure 1.27 Manually adjusting the CSS code of the SVG Pointer Line and Target Dot

    Figure 1.28 Follow up AI prompts


    Figure 1.29 Final Food Detail Page design (Colours may vary slightly from the actual website)



    Story Page

    Summarised prompt gave to Antigravity:

    3-Slide Story Selection Page (#story-screen)

    • Role & Architecture:
      Acts as an independent intermediary selection screen between the main top navigation / side drawer menu and the detailed food origin stories.

    • Full-Widescreen Stage Container (.selection-stage-container):
      Uses a 100% viewport width stage with a 300% width track (selection-carousel-track) so cards slide horizontally across the widescreen canvas without any pixel clipping or cut-offs.

    • Pinned Navigation Controls:
      Chevron arrow buttons (#selection-prev-btn and #selection-next-btn) remain pinned inside the visible screen bounds at left: 60px and right: 60px (z-index: 50).

    • The 3 Carousel Selection Slides:

      1. Slide 1 — Kuala Lumpur (Nasi Lemak):

        • Subtitle "Kuala Lumpur" ('Sniglet', 22px white) + Title "Nasi Lemak" ('Lilita One', 60px white).

        • Vector card graphic (./assets/story-page/nasi-lemak-story.svg, 440px unclipped height).

        • Interaction: Clicking Slide 1's card or title smoothly routes to the 8-Slide Nasi Lemak Story Page (#story-detail-screen).

        • Previous Arrow (<) hidden on Slide 1.

      2. Slide 2 — Terengganu (Keropok Lekor):

        • Subtitle "Terengganu" + Title "Keropok Lekor".

        • Vector card graphic (./assets/story-page/keropok-lekor-story.svg).

        • Both Previous (<) and Next (>) Arrows visible.

      3. Slide 3 — Placeholder:

        • Display title "More stories coming soon..." centered in white bold 'Lilita One' font (52px).

        • Next Arrow (>) hidden on Slide 3.


    2. 8-Slide Nasi Lemak Story Detail Page (#story-detail-screen)

    • Role & Stage Frame:
      Dedicated narrative reader stage (900px × 500px) presenting the origin story of Nasi Lemak with top action bar controls (Back Arrow and Hamburger Menu ).

    • Slide-by-Slide Narrative Content:

      • Slide 1: ./assets/story-page/story01.svg — Long ago, in a small village near Melaka, lived a kind widow named Mak Kuntum and her young daughter, Seri.

      • Slide 2: ./assets/story-page/story02.svg — One morning, Seri decided to cook rice for lunch. She carefully measured everything, but just as she reached for the water...

      • Slide 3: ./assets/story-page/story03.png — A bowl of creamy coconut milk tipped over and splashed into the pot!

      • Slide 4: ./assets/story-page/story04.svg — The rice began to fill the house with a warm, sweet fragrance. Seri peeked into the pot. The rice looked soft, fluffy, and unlike anything she had ever cooked before.

      • Slide 5: ./assets/story-page/story05.svg — When Mak Kuntum returned home, she immediately noticed the delicious smell. She smiled and asked,

      • Slide 6: ./assets/story-page/story06.svg — "Apa kau masak ni, Seri?" ("What did you cook, Seri?")

      • Slide 7: ./assets/story-page/story07.svg — Seri shyly replied, "Nasi le, Mak." ("Rice, Mother.")

      • Slide 8 (Final Dish Celebration & CTA):

        • Image: ./assets/story-page/nasi-lemak-side-view.svg.

        • Narrative concluding paragraphs detailing how the accidental coconut rice recipe evolved into Malaysia's iconic national dish served with sambal, anchovies, peanuts, cucumber, and egg.

        • CTA Button: "Discover Where to Eat →" (#discover-where-to-eat-btn) featuring immediate visibility and subtle 2-bounce micro-interaction (bounceCtaBtnTwice) that opens the Recommended Eateries Guide Page (#guide-page).


    3. Routing & Browser History Architecture

    • navigateToStory(pushHistory = true) mounts #story-screen and pushes { screen: 'story-selection' } to history.

    • navigateToStoryDetail(pushHistory = true) mounts #story-detail-screen and pushes { screen: 'nasi-lemak-story' } to history.

    • Complete browser Back / Forward popstate support allows seamless navigation back from Story Detail →→ Story Selection →→ Home Page.


    Figure 1.30 Follow up AI prompts


    Figure 1.31 Follow up AI prompts


    The Food Story Selection Page (Figure 1.31) allows users to choose the food story they are interested in exploring and learn more about its background and cultural significance.


    Figure 1.31 Final Food Story Selection Page design (Colours may vary slightly from the actual website)


    Figure 1.32 Final Food Story Slides Page design (Colours may vary slightly from the actual website)



    Featured Songs Page

    Markdown prompt (AI-generated and revised by me) gave to Antigravity:

    ## 📌 Task Overview
    Implement the **Featured Songs Page**  accessed when clicking the **"Discover Featured Songs →"** CTA button at the bottom of the Music side drawer. Build the 12-track paginated grid (3 carousel pages, 4 tracks per page), custom top navigation controls, bottom-right pagination arrows, and interactive audio play/pause controls.

    ---

    ## 🚀 1. ROUTE TRANSITIONS & NAVIGATION FLOW

    * **Navigating TO Featured Songs Page:**
      * **Trigger:** Clicking the **"Discover Featured Songs →"** button at the bottom of the side music drawer.
      * **Action:** 
        * Automatically close the side drawer.
        * Smoothly unmount the current screen and display `#featured-songs-page`.
    * **Top Navigation Controls:**
      * **Top-Left Back Button, reuse the back button, Clicking it triggers dynamic history back navigation.
      * **Top-Right Hamburger Button (`≡`):** Reuse the hamburger-menu-btn to toggle open the side navigation drawer

    ---

    ## 🎨 2. UI LAYOUT & VISUAL COMPOSITION

    ### A. Canvas & Typography
    * **Canvas Frame:** Same background
    * **Page Title:** Centered at top, `"Featured Songs"` rendered in pure white (`#FFFFFF`) using `'Lilita One'` display font (~56px).
    * **Footer Caption Text:** Left-aligned text below the card grid:
      * *"Discover the Malaysian artists music featured throughout your food adventure."*
      * Rendered in pure white (`#FFFFFF`) using font family `'Sniglet'` (~16px).

    ### B. Song Card Grid (2 × 2 Grid per Page)
    * Each page displays 4 song cards arranged in a 2-column, 2-row grid.
    * **Card Container Styling:**
      * Pure white background (`#FFFFFF`) with rounded corners (`border-radius: 16px`).
      * Horizontal layout with track details on the left and audio control icon on the right.
      * Subtle hover state: slight lift or scale on hover.
    * **Card Information Hierarchy:**
      * **Song Title:** Bold primary text (18px–20px, dark color `#1E1E1E`, font supporting Latin & Chinese characters).
      * **Artist Name:** Secondary text below song title (14px, muted `#555555`).
      * **Play/Pause Icon:** Play button (`▶` / SVG icon) toggling to Pause (`⏸` / SVG icon) when active.

    ---

    ## 🎵 3. PAGINATED TRACK DATA (12 SONGS TOTAL)

    ### 📄 Page 1 (Index 0):
    1. **Terukir Di Bintang** – Yuna
    2. **What's The Rush** – CLAUDIA, Gun Boi Kaz
    3. **在加纳共和国离婚** – DIOR Daying, Firdhaus
    4. **Taiko** – Santesh

    ### 📄 Page 2 (Index 1):
    1. **Angin Kencang** – Noh Salleh
    2. **Sempurna** – Insomniacks
    3. **Dinda** – MASDO
    4. **不完美的昨天** – JE Pong

    ### 📄 Page 3 (Index 2):
    1. **Amma Paatu** – Mugen Rao
    2. **小天地** – Bell 宇田
    3. **drip** – DOLLA
    4. **Sudi** – DOLLA, Yonnyboii

    ---

    ## ⏱️ 4. SLIDING BEHAVIOR & INTERACTION CONTROLS

    ### A. Horizontal Carousel Mechanics
    * Track container holds 3 discrete pages (`width: 300%`).
    * Navigating between pages shifts the carousel track horizontally using `transform: translateX(-0%)`, `translateX(-33.333%)`, or `translateX(-66.666%)`.
    * Motion curve: smooth ease-in-out transition (`transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1)`).

    ### B. Dynamic Navigation Arrow Visibility
    * **Arrow Button Styling:** same styling as left and right chevron button containing the same left and right chevron icon inside 
    * **Visibility Rules:**
      * **Page 1 (Start):** Previous Arrow (`<`) is **hidden**; Next Arrow (`>`) is **visible**.
      * **Page 2 (Middle):** Both Previous (`<`) and Next (`>`) arrows are **visible**.
      * **Page 3 (End):** Previous Arrow (`<`) is **visible**; Next Arrow (`>`) is **hidden**.

    ### C. Audio Playback Sync
    * Clicking `▶` on any card plays that song preview and switches its icon to `⏸`.
    * Only one track can play at a time—playing a track immediately pauses any currently playing track.
    * If a song is actively playing when switching carousel pages, its playing state and pause icon remain synced.


    Figure 1.33 Follow up AI prompts

    Figure 1.34 Follow up AI prompts

    Figure 1.35 Follow up AI prompts

    Figure 1.36 Follow up AI prompts


    The Featured Songs Page showcases songs by Malaysian artists as an additional feature for users who are interested in exploring the Malaysian music used in the website. Users can click on a song card to be directed to its corresponding YouTube link.

    I did not include album covers because the music page is not the main purpose of the website, I wanted to keep the layout simple and informative rather than making the songs feel like products or song ad being promoted.


    Figure 1.37 Final Featured Songs Page Page design
    (
    Colours may vary slightly from the actual website)




    Guide Page

    Markdown prompt (AI-generated and revised by me) gave to Antigravity:

    ## 📌 Task Overview
    Implement the **Guide Page** ( showcasing recommended eateries across Malaysia. Build the complete page layout, individual restaurant card components, exact descriptive copy, social/map icon actions, circular food badge illustrations loaded from respective `./assets/[statename]-food.svg`, top navigation controls, and an interactive continuous horizontal click-and-drag carousel track.

    ---

    ## 📁 1. ASSET MAPPING, RESTAURANT DETAILS & EXACT TEXT COPY

    Bind each restaurant card to its exact storefront image file path, official eatery name, descriptive text review, footer action icons, and circular dish vector badge loaded from `./assets/state-food.svg`:

    | # | Restaurant Name | Dish / State | Storefront Image Asset Path (`./assets/guide-page/`) | Exact Description / Review Text | Footer Icons & Dish Badge (`./assets/state-food.svg`) |
    |---|---|---|---|---|---|
    | **1** | **Ah Sang Bak Kut Teh** | Bak Kut Teh (Selangor) | `./assets/guide-page/ah-sang-bak-kut teh.jpg` | A local favourite in Sungai Way, Ah Sang Bak Kut Teh is loved for its aromatic herbal soup, tender pork, and authentic Klang-style bak kut teh. | Map Pin, Globe/Website, Instagram, Circular *Bak Kut Teh* Badge (`./assets/state-food.svg` / `./assets/selangor-food.svg`) |
    | **2** | **Nasi Lemak Burung Hantu** | Nasi Lemak (Kuala Lumpur) | `./assets/guide-page/georgetown-cropped-NLBH.jpg` | Famous for its fragrant basmati coconut rice, signature sambal, and crispy ayam berempah, NLBH has become a favourite among locals looking for a satisfying plate of nasi lemak at any time of day. | Map Pin, Globe/Website, Instagram, Circular *Nasi Lemak* Badge (`./assets/state-food.svg` / `./assets/kuala-lumpur-food.svg`) |
    | **3** | **Restoran Selera Nogori** | Masak Lemak Cili Api (Negeri Sembilan) | `./assets/guide-page/restoran-selera-nogori.png` | RSN is a local favourite known for its authentic Negeri Sembilan cuisine, especially its rich and spicy masak lemak cili api, served with a wide variety of traditional dishes at affordable prices. | Map Pin, Globe/Website, Instagram, Circular *Masak Lemak Cili Api* Badge (`./assets/state-food.svg` / `./assets/negeri-sembilan-food.svg`) |
    | **4** | **Kedai Kopi Chung Wah** | Chicken Rice Balls (Melaka) | `./assets/guide-page/kedai-kopi-chung-wah.jpg` | KKCW is one of Melaka's most famous chicken rice ball spots, located at the entrance of Jonker Street. Known for its tender chicken and flavourful rice balls, it often draws long queues from both locals and tourists. | Map Pin, Globe/Website, Instagram, Circular *Chicken Rice Balls* Badge (`./assets/state-food.svg` / `./assets/melaka-food.svg`) |
    | **5** | **Foon Yew Laksa** | Laksa Johor (Johor) | `./assets/guide-page/foon-yew-laksa.png` | A beloved Johor eatery with decades of history, Foon Yew Laksa is famous for its thick, fragrant laksa Johor and customizable bowls with fresh yong tau foo add-ons. | Map Pin, Globe/Website, Instagram, Circular *Laksa Johor* Badge (`./assets/state-food.svg` / `./assets/johor-food.svg`) |
    | **6** | **Lieniey Nasi Kerabu Tumis** | Nasi Kerabu (Kelantan) | `./assets/guide-page/lieniey.png` | Located in Kota Bharu, Lieniey Nasi Kerabu Tumis is loved for its Golok-style nasi kerabu, smoky grilled chicken or beef, and its signature spicy sambal tumis. | Map Pin, Globe/Website, Instagram, Circular *Nasi Kerabu* Badge (`./assets/state-food.svg` / `./assets/kelantan-food.svg`) |
    | **7** | **Keropok Warisan Losong** | Keropok Lekor (Terengganu) | `./assets/guide-page/keropok-warisan-losong.webp` | A traditional favourite in Kuala Terengganu, Keropok Warisan Losong has been serving authentic keropok lekor since 1983, known for its soft texture, rich fish flavour, and signature chilli dip. | Map Pin, Globe/Website, Instagram, Circular *Keropok Lekor* Badge (`./assets/state-food.svg` / `./assets/terengganu-food.svg`) |

    ---

    ## 🚀 2. ROUTE TRANSITIONS & TOP NAVIGATION CONTROLS

    * **Access / Entry Points to guide-page:**
      1. Clicking **"Guide"** on the main top navigation bar .
      2. Selecting **"Guide"** inside the side drawer menu.
      3. Clicking the **"Discover Where to Eat →"** CTA button on Slide 8 of the Story page.
    * **Top Navigation Controls:**
      * **Top-Left Back Button (`←`):** Reuse circular button. Clicking it triggers dynamic history back navigation.
      * **Top-Right Hamburger Button (`≡`):** Reuse circular button toggling the side navigation drawer.

    ---

    ## 🏪 3. RESTAURANT CAROUSEL LAYOUT & CARD ANATOMY

    * **Horizontal Carousel Container:**
      * Positioned below top navigation: `position: absolute; top: 120px; left: 0; width: 100%; height: calc(100% - 140px);`.
      * Layout: `display: flex; gap: 32px; padding: 20px 60px; overflow-x: auto; overflow-y: hidden;`.
      * Viewport distribution renders ~3 full cards plus 1 partially visible card on the right edge to visually afford horizontal scrollability.
      * Drag cursor: `cursor: grab; user-select: none;`.

    * **Card Composition & Dimensions:**
      * **Card Wrapper:** `flex: 0 0 380px; height: 520px; display: flex; flex-direction: column;`.
      * **Storefront Image (Top):**
        * Image container: `height: 240px; border-radius: 16px; overflow: hidden;`.
        * Image tag: `width: 100%; height: 100%; object-fit: cover;` referencing the respective storefront file path from `./assets/guide-page/`.
      * **Restaurant Name (Middle-Top):**
        * Display typography (font: `'Lilita One'`, 24px, color `#1E1E1E`, margin `16px 0 8px 0`).
      * **Description Text (Middle-Bottom):**
        * Body text font: `'Sniglet'`, 15px–16px, line-height `1.4`, color `#333333`.
      * **Bottom Footer Row (`.card-footer-icons`):**
        * Layout: `display: flex; align-items: center; justify-content: space-between; margin-top: auto; padding-top: 12px;`.
        * **Left Action Icons:** Location Map Pin SVG icon, Website / Globe SVG icon, and Instagram / Social SVG icon.
        * **Right Food Badge Indicator:** Circular dish badge SVG (`44px × 44px`) displaying the corresponding state food vector loaded from `./assets/state-food.svg` (or `./assets/[statename]-food.svg`).

    ---

    ## 🖱️ 4. CLICK-AND-DRAG SLIDING BEHAVIOR

    * **Smooth Mouse-Drag & Touch Mechanics:**
      * Implement active drag state listeners on guide-carousel:
        * `mousedown`: Record initial `pageX` and `scrollLeft`, set `isDragging = true` and `cursor: grabbing`.
        * `mousemove`: When `isDragging` is active, calculate horizontal delta `(e.pageX - startX)` and update `.scrollLeft = scrollLeft - delta`.
        * `mouseup` / `mouseleave`: Set `isDragging = false` and reset `cursor: grab`.
    * **Drag Conflict Prevention:**
      * Prevent native image/link dragging by attaching `ondragstart = (e) => e.preventDefault()` on all `img` and `svg` elements inside the carousel.
    * **Scroll Physics:**
      * Support trackpad gesture scrolling and mobile touch swiping with smooth momentum deceleration.



    Figure 1.38 Follow up AI prompts

    Figure 1.39 Follow up AI prompts

    Figure 1.40 Follow up AI prompts


    The Guide Page recommends places where users can find and try the featured dishes (especially for the foreigners). The page was intentionally kept simple, using short descriptions instead of overly promotional content to prevent it from feeling like advertisement. Links to each shop’s location, website, and social media are also provided for users who want to find out more.

    Lastly, when users click on the food illustration at the bottom right of each card, they will be navigated back to the corresponding Food Detail Page.


    Figure 1.41 Final Guide Page design (Colours may vary slightly from the actual website)





    FINAL THEMATIC WEBSITE

    Netlify Link: 
    http://malaysian-food-adventure.netlify.app/

    *Note: The website currently includes the complete user flow for Kuala Lumpur’s featured food only. This means that on the Food Page, only the Kuala Lumpur food is clickable and has a completed Food Detail Page. On the Story Selection Page, only the Kuala Lumpur Nasi Lemak story is currently selectable. Similarly, on the Guide Page, only the Kuala Lumpur Nasi Lemak listing has completed location, website, and social media links.

    The other states and their food content are included as part of the overall design.



    FEEDBACK

    Final Thematic Website

    Week 11 (02/07/2026)
    Feedback: They look great! All good please proceed.





    REFLECTION

    Throughout this module, it was probably the most interesting module for me this semester because I got to learn how to animate and build an interactive website using Adobe Animate. However, for the final project, I decided not to use Adobe Animate and instead tried a VS Code + Google Antigravity vibe coding approach because I have been seeing more designers starting to use vibe coding, so I wanted to explore this approach myself and see how it could fit into my own design workflow.

    This approach was surprisingly useful and made me realise how capable AI can be when working with code. It allowed me to quickly debug issues without having to go through every file manually, and small things like typos in the codes could be fixed quickly with AI. It also helped me build and test interactions more quickly, which made the overall development process more efficient.

    Of course, there were also quite a lot of challenges when vibe coding. I realised that I cannot simply tell AI what I want and expect it to generate exactly what I have in mind, the prompt has to be very specific, otherwise it might misunderstand my intention and generate something completely weird and different. A lot of my time was actually spent writing and refining prompts, reviewing the results and explaining to the AI what needed to be corrected.

    I also still manually adjusted a lot of the CSS and code myself because for smaller visual changes, asking AI to fix every single thing was sometimes less efficient because it could fix one problem but accidentally change something else, so instead of relying on AI for everything, I found that it was faster to manually adjust certain parts when I already knew exactly what needed to be changed.

    Overall, what I learnt from this project is that vibe coding is not about letting AI do everything for me, it works better as a tool that helps speed up my workflow, while I still need to make the design decisions, understand what the code is doing, and check whether the result actually matches my intention. I also learnt that knowing how to write a good prompt is becoming an important skill when working with AI. I think the biggest takeaway from this project is that I now have a better understanding of how I can combine my design skills with AI and coding in my future projects and use AI to support my workflow rather than relying on it to do everything for me.






















    Comments