Author: James Derick Billate
Reviewer:
Creation Date: April 7, 2026
Status: Draft
References:
INTRODUCTION AND GOALS
Problem Summary: This feature primarily focuses on the export and Deliver functionality of WyzQuests. It allows Creators to share their created quests to various learners without requiring those learners to create or sign in to a WyzQuests account. Specifically, it makes the quest publicly interactive. For Embed, it allows Creators to insert their quest on their respective LMS or websites by delivering a pre-generated, size-customizable <iframe /> that can run from various browsers.
Goals and Non-Goals: Public Share gives public access to quest details, but saving learner progress still requires logging in to the application. The system generates a hashed identifier that encapsulates the quest share into a string. For Embed, the iframe can run concurrently with other websites by attaching the generated code to the website itself. On the Creator side, they can revoke/pause, apply or extend expiration, delete the generated link/embed, and see limited analytics such as viewer count, completer count, completion rate, and viewer device information. The Creator cannot customize the hash or link itself and cannot see detailed quest activity of learners from the generated link.
HIGH-LEVEL ARCHITECTURE
System Diagram:
Public Share Link

Public Share Embed
Technologies Used:
Frontend: Next.js, React, TypeScript, Tailwind CSS, Shadcn Components, React Hook Form, Sonner toast, PapaParse for analytics CSV export.
Backend: Next.js API routes, TypeScript, Zod validation, Clerk authentication, agency ownership verification, Supabase.
Database: Postgres through Supabase.
Public Player: /share/[hash] route with QuestPlayer.
DETAILED DESIGN & IMPLEMENTATION
Schema:
Public Share
create table public.public_share ( quest_id uuid not null, hash text not null, created_at timestamp with time zone not null default now(), expires_at timestamp with time zone null, is_live boolean not null default true, revoked_at timestamp with time zone null, type text not null default 'link'::text, constraint share_links_pkey primary key (hash), constraint share_links_quest_id_fkey foreign KEY (quest_id) references quests (id) on delete CASCADE) TABLESPACE pg_default; create index IF not exists idx_share_links_quest_id on public.public_share using btree (quest_id) TABLESPACE pg_default;
Analytics
create table public.public_share_analytics ( hash text not null, view_count integer not null default 0, completer_count integer not null default 0, devices jsonb null, constraint share_link_analytics_pkey primary key (hash), constraint public_share_analytics_hash_fkey foreign KEY (hash) references public_share (hash) on delete CASCADE) TABLESPACE pg_default;
Implementation Notes:
public_share.hashis the public identifier used by/share/{hash}.public_share.typestoreslinkorembed.public_share.expires_atapplies to link shares; embeds currently usenullexpiration.public_share.is_livecontrols paused/reactivated access.public_share_analyticsstores viewer count, completer count, and device analytics.
API Specification:
GET /api/creator/share
Retrieves an existing share link or embed for a quest and includes analytics.
| |
|---|---|
Status | Return |
401 | Unauthorized |
400 | Missing |
403 | Access denied: quest does not belong to you |
404 | No share links found |
500 | Failed to fetch share links |
200 OK | Data: |
POST /api/creator/share
Creates a public share link or embed with a generated hash.
| |
|---|---|
Status | Return |
401 | Unauthorized |
400 | Invalid payload data |
403 | Access denied: quest does not belong to you |
500 | Failed to create share link or analytics record |
201 Created | Data: created |
PATCH /api/creator/share
Updates live state or extends expiration for a public share.
| |
|---|---|
Status | Return |
401 | Unauthorized |
400 | Invalid payload data |
403 | Access denied: quest does not belong to you |
404 | The link does not exist or failed to update link |
200 OK | Link updated |
DELETE /api/creator/share
Deletes a share link or embed record.
| |
|---|---|
Status | Return |
401 | Unauthorized |
400 |
|
403 | Access denied: quest does not belong to you |
404 | Share link not found |
500 | Failed to fetch or delete share link |
200 OK | Link deleted successfully |
GET /api/creator/share/fetch
Fetches both the public share and the quest connected to the hashed ID for the public player.
| |
|---|---|
Status | Return |
400 | Missing hash value parameter |
404 | The link does not exist or the quest does not exist |
500 | Internal Server Error |
200 OK | Data: |
POST /api/creator/share/analytics
Updates public share analytics for viewer, completer, or device events.
| |
|---|---|
Status | Return |
400 | Missing hash value parameter or Invalid payload data |
404 | Device not saved |
500 | Failed to update analytics |
200 OK | Analytics updated or device info saved |
Share Player:
/share/[hash]Loads share data by hash and renders
QuestPlayerwithsharedLink={true}. Ifis_liveis false, the route displays a no-longer-active message.
Core Logic and Workflow:
Select a specific quest.
Initiate Share option.
Choose Link or Embed type.
For Link, set expiration day option and send creation request.
For Embed, generate a share hash and then produce iframe code from the hash, width, and height.
Generate secure random hash.
Assign hash to the quest and share type.
Create initial analytics row.
Fetch share details when the modal reopens.
Display link or embed code.
Allow copy, pause/reactivate, extend expiration, delete, and analytics view.
Current hash generation logic:
const generateRandomHash = (length = 15) => { const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; const array = new Uint8Array(length); crypto.getRandomValues(array); return Array.from(array, (byte) => chars[byte % chars.length]).join("");};
Current embed code format:
<iframe src="{baseUrl}/share/{hash}" width="100%" style="max-width: {width}px;" height="{height}px" loading="lazy" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen></iframe>
INFRASTRUCTURE AND OPERATIONS
Dependencies: [1.1] Project Creation, Clerk Authentication, Quest Details, Supabase Database, Public Share tables, Quest Player, FingerprintJS, PapaParse.
Monitoring and Alerting:
Monitor failed share generation, fetch, update, delete, and analytics requests.
Monitor
/share/{hash}404 rates for broken or deleted shares.Monitor analytics RPC failures for
increment_countandappend_device.No prior documentation regarding deeper monitoring exists; add operational alerting after further testing.
Deployment Plan:
Ensure that all variables have their specific Zod validation configuration and TypeScript initialization.
Ensure staging or production domains use SSL certificates and HTTPS for copy-to-clipboard reliability and secure embedding on HTTPS hosted sites.
Ensure
public_shareandpublic_share_analyticstables exist in the target database.Ensure Supabase RPC functions for analytics are deployed.
Ensure
/share/{hash}routes are accessible without authentication.
TESTING AND QUALITY ASSURANCE
Testing Strategy:
Ensure both public share and analytics rows are present in the database after generation.
Check all queries from the indicated APIs and ensure required columns exist.
If a link cannot be retrieved, check first if duplicate or missing share rows exist.
For expiration date, manually set dates via database for testing only when needed.
Validate that the correct quest is displayed through the link.
Check whether the quest is existing, expired, deleted, archived, revoked, or blocked from share link access.
Generate a Link share and open it while logged out.
Generate an Embed share and paste the iframe into a test HTML page.
Pause and reactivate a Link share.
Delete a Link share.
Delete an Embed share.
Verify viewer count, completer count, and device information update.
Export viewer devices CSV from analytics view.
Known Limitations:
For Link, limitation of 100 users concurrently accessing the public share link.
Saving progress of learners requires logging in.
Creator cannot customize the hash or URL.
Analytics are limited to simple viewer/completer/device information.
HTML custom content exposed through public share must remain sanitized and sandboxed to reduce XSS risk.
MAINTENANCE AND SUPPORT
Troubleshooting:
For fetching quest issues, check Zod validation and regex expression errors first.
Check whether the quest exists in the database.
Check whether the share hash exists in
public_share.Check whether
is_liveis false or the link has expired.Check whether the generated iframe points to the correct
/share/{hash}URL.Check browser console errors for iframe blocking, mixed-content, or CSP issues.
Check analytics RPC functions if view counts or device rows do not update.
Changelog: No prior historical record was documented in GitHub or workspace. If evidence arises during testing, necessary additions to this document must be indicated.
Document version:
1.0 - Draft, Feature already exists on dev server, 04/07/2026
1.1 - Draft, Combined technical documentation for both link and embed type, 04/10/2026
1.2 - Enhanced documentation of Public Share Features, 07/10/2026