Skip to content

Chatbot Creation Pages

Purpose: Data source selection and chatbot configuration wizard
Category: Chatbot Setup Flow
Pages: 4 pages
Complexity: Multi-step wizards with state management


Overview

Pages that guide users through creating a new chatbot by collecting training data, selecting purpose, configuring forms, and choosing avatar/voice.


1. 3D Chatbot Data Source

File: src/app/3d-chatbot-data-source/page.tsx (812 lines)
Route: /3d-chatbot-data-source
Type: Protected
Purpose: Multi-step wizard for 3D chatbot creation

⚠️ Most Complex Creation Page - 5-Step Wizard


Wizard Steps (5)

  1. Data - Training Data Collection
  2. Purpose - Chatbot Purpose Selection
  3. Form Setup - Lead Generation Form Configuration
  4. Avatar & Voice - Visual and Voice Selection
  5. Create - Final creation with loading state

State Variables (20+)

Data Sources:

  1. website (string) - Website URL for crawling
  2. file (File[] | null) - Uploaded files
  3. text (string) - Manual text input
  4. qa ({question: string; answer: string}[]) - Q&A pairs
  5. fetchedLinks (string[]) - Crawled URLs (limited to 50)
  6. linkfetched (boolean) - Website crawl status

UI State: 7. activeTab ("website" | "files" | "text" | "qa" | "profile" | "utm") - Data source tab 8. activeToggleTab ("data" | "purpose" | "formsetup" | "avatar" | "create") - Wizard step 9. showPopup (boolean) - Title input popup 10. showNavButtons (boolean) - Previous/Next buttons visibility 11. isLoading (boolean) - General loading state 12. isFetchingLinks (boolean) - Website crawl in progress

Component Completion Tracking: 13. componentCompletion (object) - Track completion of 6 data sources typescript { profile: boolean, website: boolean, files: boolean, text: boolean, qa: boolean, utm: boolean } 14. allComponentsCompleted (boolean) - All data sources done

Chatbot Config: 15. selectedPurpose (string) - Chatbot purpose 16. selectedAvatar (StaticImageData | null) - Selected avatar image 17. selectedAvatarName (string) - Avatar name 18. projectId (string | null) - Current project ID 19. userId (string | null) - Current user ID 20. sessionId (string | null) - Current session ID

Refs: 21. purposeRef - Reference to PurposeComponent 22. avatarRef - Reference to AvatarComponent 23. formSetupRef - Reference to FormSetupComponent 24. fetchController (AbortController) - Cancel fetch operations


Step 1: Data Collection

6 Data Source Options (Tabs):

Profile Tab

Component: ProfileComponent

  • Purpose: Chatbot name and description
  • Features:
  • Chatbot title input
  • Description textarea
  • Save/Skip options
  • Completion tracking: onComplete(completed)

Website Tab

Component: WebsiteComponent

  • Purpose: Crawl and index website content
  • Features:
  • URL input
  • Sitemap URL fetching
  • API: POST /v2/fetch-sitemap-urls
  • Limit: 50 URLs
  • Loading indicator: Bottom-right toast
  • Abort support: Cancel ongoing fetch
  • Completion tracking: Links fetched successfully

Fetch Links Logic:

const fetchLinksFromAPI = async (siteUrl: string) => {
  // Cancel existing fetch
  if (fetchController.current) {
    fetchController.current.abort();
  }

  fetchController.current = new AbortController();

  const formData = new FormData();
  formData.append("project_id", storedProjectId);
  formData.append("user_id", userid);
  formData.append("domain", siteUrl);
  formData.append("session_id", session);

  const response = await fetch("/v2/fetch-sitemap-urls", {
    method: "POST",
    body: formData,
    signal: fetchController.current.signal,
  });

  const data = await response.json();

  if (data.urls) {
    const limitedLinks = data.urls.slice(0, 50); // Limit to 50
    setFetchedLinks(limitedLinks);
    setLinkFetched(true);
    toast.success("Links fetched successfully!");
  }
};

Files Tab

Component: FileUploadComponent

  • Purpose: Upload documents (PDF, DOCX, TXT, etc.)
  • Features:
  • Drag & drop
  • Multiple file selection
  • File type validation
  • Completion tracking: Files uploaded

Text Tab

Component: TextComponent

  • Purpose: Manual text entry
  • Features:
  • Large textarea
  • Character count (optional)
  • Save/Skip
  • Completion tracking: Text saved

Q&A Tab

Component: QAComponent

  • Purpose: Predefined Q&A pairs
  • Features:
  • Add/remove Q&A pairs
  • Required for step completion
  • Save & Next or Skip & Next
  • Critical: Sets sessionStorage.qa_completed ("true" or "skipped")
  • Completion tracking: Q&A saved or skipped

Q&A Completion Logic:

const isSubmitDisabled = () => {
  if (activeToggleTab === "data") {
    const qaCompleted = sessionStorage.getItem("qa_completed");
    return (
      !qaCompleted || (qaCompleted !== "true" && qaCompleted !== "skipped")
    );
  }
};

UTM Tab

Component: UTMComponent

  • Purpose: UTM parameter configuration
  • Features:
  • UTM source, medium, campaign
  • Link preview
  • Completion tracking: UTM configured

File: Sidebar component
Purpose: Tab switcher for data sources (only visible in Step 1)

Tabs:

  • Profile (default)
  • Website
  • Files
  • Text
  • Q&A
  • UTM

Step 2: Purpose Selection

Component: PurposeComponent
Purpose: Define chatbot's purpose/use case

Features:

  • Predefined purpose options
  • Custom purpose input
  • API: Called via purposeRef.current.submitPurpose()
  • Validation: Must select purpose to proceed

Purpose Options (Examples):

  • Customer Support
  • Lead Generation
  • Product Recommendations
  • FAQ Assistance
  • Appointment Booking

Step 3: Form Setup (Optional)

Component: FormSetupComponent
Purpose: Configure lead generation forms

Features:

  • Form field configuration
  • Required/Optional fields
  • Skip option available
  • API: Called via formSetupRef.current.submitFormSetup()
  • Validation: NOT required (can skip)

Form Fields:

  • Name
  • Email
  • Phone
  • Company
  • Custom fields

Step 4: Avatar & Voice Selection

Component: AvatarComponent
Purpose: Choose 3D avatar and voice

Features:

  • Avatar gallery (7 avatars)
  • Voice preview and selection
  • Combined submission (both avatar + voice)
  • API: Called via avatarRef.current.submitAvatar()
  • Validation: Must select avatar to proceed

Available Avatars:

  • Eva
  • Shayla
  • Myra
  • Chris
  • Jack
  • Anu
  • Emma

Step 5: Create

Purpose: Final chatbot creation with loading animation

Features:

  • Big loader animation (80px spinner)
  • "Creating your Chatbot..." message
  • Automatic redirect on completion
  • Session cleanup:
  • Removes qa_completed
  • Removes website
  • Navigation: Previous/Next buttons hidden

Loading Animation:

.big-loader {
  border: 8px solid #f3f3f3;
  border-top: 8px solid #ff6622;
  border-radius: 50%;
  width: 80px;
  height: 80px;
  animation: spin 1.5s linear infinite;
}

Progress Bar

Desktop:

  • Horizontal progress line
  • 5 step indicators with checkmarks
  • Labels below each step
  • Green for completed, outlined for active, gray for upcoming

Mobile:

  • Simplified horizontal bar (0-100%)
  • Current step indicator with number
  • "Step X of 5" text

Progress Calculation:

width: activeToggleTab === "data"
  ? "0%"
  : activeToggleTab === "purpose"
  ? "25%"
  : activeToggleTab === "formsetup"
  ? "50%"
  : activeToggleTab === "avatar"
  ? "75%"
  : "100%";

Previous Button:

  • Disabled on Step 1 (data)
  • Moves back one step
  • Always visible except on final step

Next Button:

  • Triggers step-specific submission
  • Then moves to next step
  • Validation before proceeding

Next Button Handler:

const handleNextClick = async () => {
  switch (activeToggleTab) {
    case "data":
      // Check qa_completed
      toast.success("Data source configuration completed!");
      break;
    case "purpose":
      await purposeRef.current?.submitPurpose();
      break;
    case "formsetup":
      await formSetupRef.current?.submitFormSetup();
      break;
    case "avatar":
      await avatarRef.current?.submitAvatar();
      break;
  }
  goToNextStep();
};

State Management & Persistence

Session Storage Keys:

  • selected_project_id - Current project
  • user_id - User ID
  • session_id - Session ID
  • chatbotTitle - Chatbot name
  • website - Website URL
  • includedLinks - Fetched URLs (JSON)
  • selectedPurpose - Purpose selection
  • selection_avatar - Avatar name
  • avatarType - Avatar type
  • selection_voice - Voice selection
  • qa_completed - "true" or "skipped"
  • continueChatbot - "true" or "false"

State Restoration (Continue Flow)

Purpose: Resume incomplete chatbot creation

API: GET /v2/check-selection-state?user_id={id}&project_id={id}&session_id={id}

State Mapping:

const checkState = async () => {
  const result = await fetch("/v2/check-selection-state");

  // Map API state to wizard step
  if (result.state === "start") newTab = "data";
  else if (result.state === "sitemap_urls_fetched") newTab = "purpose";
  else if (result.state === "chatbot_purpose_selected") newTab = "formsetup";
  else if (result.state === "form_setup_completed") newTab = "avatar";
  else if (
    result.state === "avatar_selected" ||
    result.state === "voice_selected"
  )
    newTab = "create";

  setActiveToggleTab(newTab);
};

Continue vs New:

  • Continue (continueChatbot="true"): Advances one step beyond last saved
  • New (continueChatbot="false"): Stays on last saved step

Data Fetching on Load

API: GET /v2/get-selection?user_id={id}&project_id={id}

Purpose: Load existing chatbot configuration

Data Restored:

  • chatbot_type
  • sitemap_urls.urls[]website, includedLinks
  • chatbot_purposeselectedPurpose
  • selection_avatarselectedAvatarName
  • avatar_type
  • selection_voice

Title Popup

Purpose: Optional chatbot title input

Features:

  • Appears 1 second after page load
  • Modal overlay
  • Skip option with confirmation
  • Skip confirmation: "Skipping this step is irreversible. Are you sure?"

TitleInput Component:

const TitleInput = ({ onSave, onSkip }) => {
  const [title, setTitle] = useState("");

  const handleSubmit = (e) => {
    if (title.trim()) {
      sessionStorage.setItem("chatbotTitle", title);
      toast.success("Title saved successfully!");
      setShowPopup(false);
    }
  };
};

Components Used

  • ProtectedLayout - Auth wrapper
  • Sidebar - Data source tabs
  • ProfileComponent - Chatbot profile
  • WebsiteComponent - URL crawler
  • FileUploadComponent - File uploader
  • TextComponent - Text input
  • QAComponent - Q&A pairs
  • UTMComponent - UTM parameters
  • PurposeComponent - Purpose selection
  • FormSetupComponent - Form configuration
  • AvatarComponent - Avatar & voice selection
  • BackButton - Navigation
  • ToastContainer - Notifications

API Endpoints

  1. POST /v2/fetch-sitemap-urls - Crawl website
  2. GET /v2/check-selection-state - Get wizard state
  3. GET /v2/get-selection - Get chatbot config
  4. Purpose, Form Setup, Avatar submissions (called via component refs)

Validation Rules

Step Required Validation
Data ✅ Q&A completed or skipped qa_completed in sessionStorage
Purpose ✅ Purpose selected selectedPurpose !== ""
Form Setup ❌ Optional Can skip
Avatar ✅ Avatar selected selectedAvatar !== null

Responsive Design

Desktop:

  • Sidebar + content side-by-side
  • Full progress bar with labels
  • Previous/Next buttons at top

Mobile:

  • Sidebar overlay/modal
  • Simplified progress bar
  • Compact step indicator
  • Previous/Next buttons still visible

CSS Breakpoints:

  • md: - 768px and up
  • sm: - 640px and up
  • Mobile-first design

Loading States

Website Fetching:

{
  isFetchingLinks && (
    <div className="fixed bottom-4 right-4 bg-white text-black p-2 rounded-md">
      <div className="loader mr-2"></div>
      <span>Fetching links...</span>
    </div>
  );
}

Final Creation:

{activeToggleTab === "create" && (
  <div className="big-loader mb-8"></div>
  <h2>Creating your Chatbot...</h2>
  <p>Please wait while we set up your AI assistant</p>
)}

Security & Auth

  • ProtectedLayout - Requires authentication
  • Session-based - Uses sessionStorage
  • Project-scoped - project_id validation
  • API authentication - JWT tokens

Dependencies

  • next/navigation (useRouter)
  • next/image (Image, StaticImageData)
  • react (useState, useEffect, useRef)
  • react-toastify (toast, ToastContainer)
  • Custom components (11 components)

Environment Variables

NEXT_PUBLIC_API_BASE_URL=https://api.machineavatars.com

2. Text Chatbot Data Source

File: src/app/chatbot-data-source/page.tsx (604 lines)
Route: /chatbot-data-source
Type: Protected
Purpose: 4-step wizard for text chatbot creation (NO avatar, NO voice)

Simpler than 3D: Excludes avatar and voice selection steps


Wizard Steps (4)

  1. Data - Training Data Collection
  2. Purpose - Chatbot Purpose Selection
  3. Form Setup - Lead Generation Form Configuration (OPTIONAL)
  4. Create - Final creation with loading state

Progress: 0% → 33% → 66% → 100%


State Variables (16)

Data Sources:

  1. website (string) - Website URL
  2. file (File[] | null) - Uploaded files
  3. text (string) - Manual text
  4. qa ({question: string; answer: string}[]) - Q&A pairs
  5. fetchedLinks (string[]) - Crawled URLs (LIMITED TO 25)
  6. linkfetched (boolean) - Crawl status

UI State: 7. activeTab (TabType) - Data source tab: "website" | "files" | "text" | "qa" | "profile" 8. activeToggleTab ("chatbotType" | "data" | "purpose" | "create") - Current step 9. isFetchingLinks (boolean) - Website crawl in progress 10. componentCompletion (object) - Track 5 data sources 11. allComponentsCompleted (boolean) - All sources done

Config: 12. selectedPurpose (string) - Chatbot purpose 13. projectId (string | null) 14. userId (string | null) 15. sessionId (string | null) 16. purposeRef (useRef) - Reference to PurposeComponent

Fetch Controller:

  • fetchController (AbortController) - Cancel fetch

Key Difference from 3D Chatbot

URL Limit: 25 URLs (vs 50 for 3D)

const limitedLinks = data.urls.slice(0, 25); // Text chatbot limit

API Endpoint: Different state check

const response = await fetch(
  `/v2/check-text-selection-state?user_id=${userId}&project_id=${projectId}&session_id=${sessionId}`
);

No Avatar/Voice: Steps removed completely


Progress Bar Calculation

Desktop:

width: activeToggleTab === "chatbotType"
  ? "0%"
  : activeToggleTab === "data"
  ? "33%"
  : activeToggleTab === "purpose"
  ? "66%"
  : "100%";

Mobile:

Step {steps.indexOf(activeToggleTab) + 1} of {steps.length}  // of 4

Data Sources (5 Tabs)

Identical to 3D chatbot:

  1. Profile - Chatbot name/description
  2. Website - URL crawler (25 URLs)
  3. Files - PDF/DOCX upload
  4. Text - Manual text
  5. Q&A - Q&A pairs

NO UTM tab (unlike 3D)


Validation Rules

| Step | Required | Validation | | ---------- | ---------------------- | ------------------------ | --- | ---- | --- | ----------- | --- | -------------- | | Data | ✅ At least one source | website !== "" | | file | | text !== "" | | qa.length > 0 | | Purpose | ✅ Purpose selected | selectedPurpose !== "" | | Form Setup | ❌ Optional | Can skip |


Components Used

Same as 3D chatbot:

  • ProfileComponent
  • WebsiteComponent
  • FileUploadComponent
  • TextComponent
  • QAComponent
  • PurposeComponent
  • Sidebar

3. Voice Chatbot Data Source

File: src/app/voice-chatbot-data-source/page.tsx (656 lines)
Route: /voice-chatbot-data-source
Type: Protected
Purpose: 5-step wizard for voice chatbot creation (includes voice selection)

⭐ Voice-First: Adds voice selection step before creation


Wizard Steps (5)

  1. Data - Training Data Collection
  2. Purpose - Chatbot Purpose Selection
  3. Form Setup - Lead Generation Form (OPTIONAL)
  4. Voice - Voice Selection
  5. Create - Final creation

Progress: 0% → 25% → 50% → 75% → 100%


State Variables (19)

All text chatbot variables PLUS:

Voice Selection: 17. selectedVoice (string) - Selected voice name (default: "Esther Howard") 18. selectedAvatarName (string) - Avatar name (stored but not displayed) 19. voiceRef (useRef<VoiceComponentHandle>) - Reference to VoiceComponent


Voice Selection Step

Component: VoiceComponenttt
Purpose: Choose AI voice for chatbot

Features:

  • Voice preview and playback
  • Multiple voice options
  • Default: "Esther Howard"
  • API: Called via voiceRef.current?.submitVoice()
  • Validation: Must select voice to proceed

Voice Component Submission:

case "voice":
  await voiceRef.current?.submitVoice();
  break;

Progress Bar (5 Steps)

width: activeToggleTab === "chatbotType"
  ? "0%"
  : activeToggleTab === "data"
  ? "25%"
  : activeToggleTab === "purpose"
  ? "50%"
  : activeToggleTab === "voice"
  ? "75%"
  : "100%";

State Restoration Logic

API: GET /v2/check-selection-state (different from text chatbot)

State Mapping:

if (continueChatbot === "false") {
  if (result.state === "start") newTab = "chatbotType";
  if (result.state === "sitemap_urls_fetched") newTab = "data";
  else if (result.state === "chatbot_purpose_selected") newTab = "purpose";
  else if (result.state === "avatar_selected") newTab = "voice";
} else if (continueChatbot) {
  if (result.state === "start") newTab = "data";
  else if (result.state === "sitemap_urls_fetched") newTab = "purpose";
  else if (result.state === "chatbot_purpose_selected") newTab = "voice";
  else if (result.state === "avatar_selected") newTab = "voice";
  else if (result.state === "voice_selected") newTab = "create";
}

Session Storage Keys

All text chatbot keys PLUS:

  • selection_voice - Voice selection
  • selection_avatar - Avatar name (stored but not used in UI)
  • avatarType - Avatar type

Validation Rules

Step Required Validation
Data ✅ At least one source Same as text
Purpose ✅ Purpose selected Same as text
Form Setup ❌ Optional Same as text
Voice ✅ Voice selected selectedVoice !== ""

URL Limit

Same as text: 25 URLs (not 50 like 3D)

const limitedLinks = data.urls.slice(0, 25);

Summary Comparison

Feature 3D Chatbot Text Chatbot Voice Chatbot
File 812 lines 604 lines 656 lines
Steps 5 4 5
Data Sources 6 (+ UTM) 5 5
URL Limit 50 25 25
Avatar Selection ✅ Yes ❌ No ❌ No
Voice Selection ✅ Yes ❌ No ✅ Yes
Form Setup Optional Optional Optional
Progress Width 0/25/50/75/100% 0/33/66/100% 0/25/50/75/100%
State API /v2/check-selection-state /v2/check-text-selection-state /v2/check-selection-state

Common Patterns (All 3 Wizards)

  1. Multi-step progress bar (desktop + mobile)
  2. Component refs for step submissions
  3. Session storage for state persistence
  4. State restoration for continue flow
  5. AbortController for fetch cancellation
  6. Validation before step advancement
  7. Toast notifications for user feedback
  8. Responsive design with breakpoints
  9. Loading animations (small + big loader)
  10. Protected layout wrapper

4. Chatbot Setup Wizard

File: src/app/chatbot/page.tsx
Route: /chatbot
Type: Protected
Purpose: Alternative or legacy chatbot setup flow

Note: Not analyzed - appears to be legacy implementation or alternative flow


Total Creation Code: ~2,100 lines (3D: 812 + Text: 604 + Voice: 656 + Legacy: ~400)


Summary

Page Lines Steps Complexity
3D Chatbot Data Source 812 5 ⭐⭐⭐⭐⭐
Text Chatbot Data Source ~600 4 ⭐⭐⭐⭐
Voice Chatbot Data Source ~600 4 ⭐⭐⭐⭐
Chatbot Wizard ~400 3 ⭐⭐⭐

Total: ~2,400 lines of wizard code


Common Patterns

  1. Multi-step wizards with progress tracking
  2. Component refs for step submissions
  3. Session storage for state persistence
  4. State restoration for continue flow
  5. Validation before step advancement
  6. Loading indicators for async operations
  7. Toast notifications for user feedback

"From data to avatar, every step documented."