Motivation Pop-ups

Author: James Derick Billate
Reviewer:
Creation Date: March 3, 2026
Status: Draft
References: https://github.com/wyzlab/WyzQuests/issues/36

INTRODUCTION & GOALS

Problem Summary: This feature allows Creators to generate custom motivational messages or media to increase learner interactivity while they are enrolled in a quest. It increases stimulus for success and perseverance as quest progress becomes more challenging and complex.

Goals & Non-Goals:

  • Allow Creators to customize motivation pop-ups for individual content cards such as text cards or question cards.

  • Allow motivation content to be text, image, video, gif, or audio.

  • Allow uploaded motivation media to be stored and linked to a specific quest content card.

  • Allow the quest setting motivational_popup to control whether this feature is enabled for a quest.

  • Creators will not be able to access or use this feature if Motivational Popup is disabled in quest settings.

  • This feature does not cover advanced learner analytics or trigger rules beyond the supported card-level behavior.


HIGH-LEVEL ARCHITECTURE

System Diagram:

Blank Diagram Lucidchart (2).png

Technologies Used:

Frontend: Next.js, React, TypeScript, Tailwind CSS, Shadcn Components.

Backend: Next.js API routes and RESTful APIs.

Authentication: Clerk Authentication.

Validation: Zod Validation where applicable and API-side input validation.

Database: Postgres through Supabase.

Storage: Supabase Storage bucket for uploaded motivation media.


DETAILED DESIGN & IMPLEMENTATION

Schema:

CREATE TABLE public.quests (
id uuid NOT NULL DEFAULT gen_random_uuid(),
created_at timestamp with time zone NOT NULL DEFAULT now(),
creator_id uuid NOT NULL,
adventure_id uuid,
title text NOT NULL UNIQUE,
introduction text NOT NULL,
description text,
updated_at timestamp with time zone NOT NULL,
profile_img_url text,
publishing_status text NOT NULL DEFAULT 'draft'::text CHECK (publishing_status = ANY (ARRAY['published'::text, 'draft'::text, 'archived'::text, 'submitted'::text, 'in_review'::text, 'changes_requested'::text, 'approved'::text])),
accessibility_status text NOT NULL DEFAULT 'restricted'::text,
tags ARRAY DEFAULT '{}'::text[],
enrollment_count bigint NOT NULL DEFAULT '0'::bigint,
is_count_visible boolean NOT NULL DEFAULT true,
enrollment_limit bigint,
motivational_popup boolean NOT NULL DEFAULT false,
enrollment_fee bigint NOT NULL DEFAULT '0'::bigint,
duration bigint,
background_img_url text,
background_audio_url text,
mentor_img_link text,
canvas_metadata jsonb NOT NULL DEFAULT '{"edges": [], "nodes": []}'::jsonb CHECK (canvas_metadata IS NOT NULL AND canvas_metadata ? 'nodes'::text AND canvas_metadata ? 'edges'::text AND jsonb_typeof(canvas_metadata -> 'nodes'::text) = 'array'::text AND jsonb_typeof(canvas_metadata -> 'edges'::text) = 'array'::text),
skills ARRAY DEFAULT '{}'::text[],
CONSTRAINT quests_pkey PRIMARY KEY (id),
CONSTRAINT quests_creator_user_id_fkey FOREIGN KEY (creator_id) REFERENCES public.app_users(id),
CONSTRAINT quests_adventure_id_fkey FOREIGN KEY (adventure_id) REFERENCES public.adventures(id)
);
 
CREATE TABLE public.quest_content_cards (
id uuid NOT NULL DEFAULT gen_random_uuid(),
created_at timestamp with time zone NOT NULL DEFAULT now(),
updated_at timestamp with time zone NOT NULL DEFAULT now(),
quest_id uuid NOT NULL,
order_index integer NOT NULL,
content jsonb NOT NULL DEFAULT '{}'::jsonb,
type text NOT NULL,
motivation jsonb DEFAULT '{}'::jsonb,
CONSTRAINT quest_content_cards_pkey PRIMARY KEY (id),
CONSTRAINT quest_content_cards_quest_id_fkey FOREIGN KEY (quest_id) REFERENCES public.quests(id)
);

Data Model

API Specification:

POST /api/creator/(content)/create-quest
Creates a quest. This feature depends on quest creation because motivational pop-ups can only be configured after a quest exists.

GET /api/creator/(content)/get-quest?quest_id={questID}
Fetches the requested quest, including the motivational_popup setting when selected by the query.

PATCH /api/creator/(content)/update-quest
Updates quest-level settings, including motivational_popup.

Status

Return

400

Invalid quest update payload.

401 / 403

Unauthorized or forbidden access.

404

Quest not found or access denied.

500

Failed to update quest.

200 OK

Quest updated successfully.

POST /api/creator/quest-content-cards/create
Creates an individual content card for the quest. Motivation can only be attached once a content card exists.

PUT /api/creator/quest-content-cards/update
Updates an existing content card, including the motivation JSON payload.

Required or supported data:

  • id

  • content

  • motivation

  • order_index

Status

Return

400

Invalid quest update payload.

401 / 403

Unauthorized or forbidden access.

404

Card, quest, or ownership record not found.

500

Failed to update content card.

200 OK

Content card updated successfully with motivation data.

POST /api/creator/quest-content-cards/upload-motivation-media
Uploads motivation media for a specific quest content card.

Required Data: file, card_id, quest_id, and motivation_type via FormData.

Upload path: public-assets/quests/{quest_id}/content-cards/{card_id}/motivation.{fileExt}

Valid motivation_type values: image, video, gif, audio

Status

Return

400

Missing required fields, Invalid motivation type, or Invalid file type or file size.

401 / 403

Unauthorized or forbidden access.

404

Quest not found, card not found, or access denied.

500

Failed to upload file or Failed to update content card with motivation media

200 OK

Motivation media uploaded successfully.

Core Logic and Workflow:

  • Creator signs in.

  • Creator creates or opens an existing quest.

  • Creator enables Motivational Popup in quest settings where required.

  • Creator opens Outline or content card editing.

  • Creator selects a content card.

  • Creator clicks the spark icon.

  • Creator chooses motivation type: text, image, video, gif, or audio.

  • For text, Creator inputs the message and saves.

  • For media, Creator uploads a valid file.

  • API validates quest ownership and card ownership.

  • Media upload stores the file in Supabase Storage.

  • Card update stores the motivation JSON in quest_content_cards.motivation.

  • Quest Player reads the stored motivation and displays it to learners on the designated card.


INFRASTRUCTURE & OPERATIONS

Dependencies:

The motivational pop-ups can only be accessed and created once the Creator has initiated quest creation and content card creation. Therefore, the following features are dependencies of 3.5 Motivation Pop-ups:

  • [1.7] Quest Creation

  • [3.3] Activity Cards

  • Clerk Authentication.

  • Supabase Database.

  • Supabase Storage.

Monitoring & Alerting: No major monitoring was documented before this enhancement. At minimum, logs should be checked for failed validation, failed card updates, failed storage uploads, and failed learner display retrieval.

Deployment Plan:

  • Ensure necessary migration files are safely migrated in Supabase.

  • Ensure quests.motivational_popup exists and defaults to false.

  • Ensure quest_content_cards.motivation exists and accepts JSON-formatted data.

  • Ensure call-to-actions are working properly and navigation to the feature is accessible.

  • Ensure media upload storage bucket permissions support the intended public media access.

  • After verification, deploy safely to production.


TESTING & QUALITY ASSURANCE

Testing Strategy:

  • Ensure motivational pop-ups have a designated column under the quests table. This is where the decision of adding motivational pop-ups to the quest will be stored as true or false.

  • Ensure motivational pop-ups also have a designated column under quest_content_cards that only accepts JSON-formatted data. This is where the motivation messages and media will be stored when displayed.

  • Ensure buttons that help Creators navigate this feature are visible and working.

  • Ensure text motivation can be saved to a card.

  • Ensure image, video, gif, and audio media can be uploaded where supported.

  • Ensure uploaded media URL is stored in the card motivation data.

  • Ensure motivation pop-ups are displayed on the Learner's screen on designated content cards.

Known Limitations:

  • Advanced learner analytics for motivation pop-up views or dismissals are not included.

  • Exploration mode node-level motivation configuration is outside the current documented scope.


MAINTENANCE & SUPPORT

Troubleshooting:

  • If media uploading such as image, video, gif, or audio is not accepted by the system, check the validation rules and confirm the file type is included in the acceptable file formats.

  • If text or media content is not accepted by the system, reload the site. If running locally, run npm run dev again to refresh local API endpoints.

  • If motivational pop-ups are not stored, confirm that quest_content_cards.motivation and quests.motivational_popup exist in the database.

  • If media uploads succeed but do not display, confirm the stored file_url is publicly accessible and the Quest Player is reading the motivation data.

  • If authorization fails, confirm the Creator owns the quest or has valid agency-scoped access.

Changelog: No prior historical record was documented, neither in GitHub nor via workspace. If such evidence arises during the testing process, necessary additions to this document must be indicated.


Document version:

1.0 - Draft, feature already exists on dev server before and after initial dev review, 03/04/2026

1.1 - Enhanced documentation of Motivation Pop-ups, 07/10/2026

1.2 - Minimal enhancements, 07/14/2026


Was this article helpful?