๐Ÿงญ WebApp Onboarding โ€“ Welcome Modal, Interactive Tour & Theme Wizard๏ƒ

ืชื”ืœื™ืš ื”-Onboarding ืฉืœ ื”-WebApp ืžื•ืจื›ื‘ ืžืฉืœื•ืฉื” ืจื›ื™ื‘ื™ื ืชืœื•ื™ื™ื ืฉืžื•ืคืขืœื™ื ืขื‘ื•ืจ ืžืฉืชืžืฉื™ื ื—ื“ืฉื™ื ื‘ืœื‘ื“: Welcome Modal, ืกื™ื•ืจ ืื™ื ื˜ืจืืงื˜ื™ื‘ื™ ืžื‘ื•ืกืก Driver.js ื•ื”-Theme Picker Wizard ืฉืžืกื™ื™ื ืืช ื”ื—ื•ื•ื™ื” ืขื ื”ืชืืžื” ืื™ืฉื™ืช. ื”ืขืžื•ื“ ืžืจื›ื– ืืช ื”ื”ืกื‘ืจื™ื ื”ืชืคืขื•ืœื™ื™ื, ืžื ื’ื ื•ื ื™ ื”ืื™ืคื•ืก ื•ื”ื ืงื•ื“ื•ืช ื”ื—ืฉื•ื‘ื•ืช ืœืžืคืชื—ื™ื.


ืจื›ื™ื‘ื™ื ื•ืžื” ื”ื ืขื•ืฉื™ื๏ƒ

ืจื›ื™ื‘

ืžืชื™ ืžื•ืคื™ืข

ื“ื’ืœ/ืžืคืชื—

ืงื‘ืฆื™ ืžืงื•ืจ

Welcome Modal

ื›ื ื™ืกื” ืจืืฉื•ื ื” ืื—ืจื™ ื”ืชื—ื‘ืจื•ืช

has_seen_welcome_modal (DB + sessionStorage)

webapp/templates/base.html, ื”ืงื•ื‘ืฅ webapp/USER_GUIDE.md

Interactive Tour (Driver.js)

ืื—ืจื™ ืฉื”-Welcome Modal ื ืกื’ืจ ื•ื‘ื ืชื™ื‘ /files

localStorage["codekeeper_walkthrough_v1"]

initInteractiveWalkthrough() ื‘ืชื•ืš webapp/templates/base.html

Theme Picker Wizard

ื‘ืกื™ื•ื ื”ืกื™ื•ืจ ืื• ืื—ืจื™ fallback ืฉืœ 9 ืฉื ื™ื•ืช

theme_wizard_seen, user_theme, dark_mode_preference

ืจื›ื™ื‘ #themeWizard + initThemeWizard() ื‘-webapp/templates/base.html


ืชืจืฉื™ื ืื™ื ื˜ืจืืงืฆื™ื”๏ƒ

ืชืจืฉื™ื ื–ืจื™ืžื” โ€“ Onboarding

ืกื“ืจ ื˜ืขื™ื ื”:

  • Welcome Modal ื—ื™ื™ื‘ ืœื”ืกื™ืจ ืืช ืขืฆืžื• ืžื”-DOM (MutationObserver) ืœืคื ื™ ืฉื›ืœ ืจื›ื™ื‘ ืื—ืจ ืžืชื—ื™ืœ.

  • Driver.js ืžืžืชื™ืŸ ืœื ืชื™ื‘ /files ื•ืœืกื™ื•ื ื”-Welcome Modal (waitForWelcomeModal()), ื•ืื– ืžืคืขื™ืœ ืืช ื”ืกื™ื•ืจ ื•ื›ื•ืชื‘ ืืช ื”ื“ื’ืœ codekeeper_walkthrough_v1.

  • Theme Wizard ืžืื–ื™ืŸ ืœ-Driver ื‘ืืžืฆืขื•ืช ThemeWizard.watchDriver() ื•ื›ืš ื ืคืชื— ืžื™ื“ ื›ืฉื”ืกื™ื•ืจ ืžืกืชื™ื™ื. ืื ื”ืกื™ื•ืจ ืœื ืจืฅ, scheduleFallback() ื™ืคืชื— ืื•ืชื• ืœืื—ืจ ~9 ืฉื ื™ื•ืช.

ื”ืชืœื•ืช ื”ื–ื• ืžื•ื ืขืช ื”ืชื ื’ืฉื•ื™ื•ืช: Welcome Modal โ†’ Interactive Tour โ†’ Theme Wizard.


Welcome Modal โ€“ ืจืขื ื•ืŸ ืงืฆืจ๏ƒ

ืžื•ื“ืืœ Welcome ืžื•ืฆื’ ืœืžืฉืชืžืฉื™ื ืฉืžืชื—ื‘ืจื™ื ืœ-WebApp ื‘ืคืขื ื”ืจืืฉื•ื ื” ื•ืžืกืคืง ืงื™ืฉื•ืจื™ื ื™ืฉื™ืจื™ื ืœืžื“ืจื™ื›ื™ื ื”ืžืจื›ื–ื™ื™ื ืžืชื•ืš webapp/USER_GUIDE.md. ืื—ืจื™ ื›ืœ ืคืขื•ืœื” (Primary/Secondary/ื“ืœื’) ื ืฉืœื—ืช ื‘ืงืฉื” ืœ-POST /api/welcome/ack ื•ื”ื“ื’ืœ has_seen_welcome_modal ืžืกื•ืžืŸ ื‘-DB ื•ื’ื ื‘-session.

ืžื˜ืจื•ืช๏ƒ

  • ืœื”ื“ืจื™ืš ืžืฉืชืžืฉื™ื ื—ื“ืฉื™ื ืœืฉื ื™ ืžื“ืจื™ื›ื™ื ืžืจื›ื–ื™ื™ื ืžื”ืจ ื›ื›ืœ ื”ืืคืฉืจ.

  • ืœืžื ื•ืข ื—ื™ื›ื•ืš ื‘ื›ื ื™ืกื” ื”ืจืืฉื•ื ื” โ€“ ืžื•ืคื™ืข ืคืขื ืื—ืช ื‘ืœื‘ื“.

ื–ืจื™ืžืช ืžืฉืชืžืฉ๏ƒ

  1. show_welcome_modal ื‘ืฆื“ ื”ืฉืจืช ืžื—ื–ื™ืจ true โ†’ ื”-template ืžื™ื™ืฆืจ ืืช ื”-modal.

  2. welcomeModalInit() ืžืฆืžื™ื“ ื”ืื–ื ื•ืช ืœื›ืคืชื•ืจื™ื ื•ืœืจืงืข.

  3. ื”ืงืฉื” ืขืœ ื›ืœ ื›ืคืชื•ืจ ืงื•ืจืืช ืœ-/api/welcome/ack ื•ืžืกื™ืจื” ืืช ื”ืžื•ื“ืืœ.

  4. ื”ืžืกืš ืคื ื•ื™ ืœื”ืžืฉืš โ€“ MutationObserver ืžืกืžืŸ ืœื™ืชืจ ื”ืจื›ื™ื‘ื™ื ืฉืืคืฉืจ ืœื”ืชื—ื™ืœ.

ืœืฆื•ืจื›ื™ QA ื ื™ืชืŸ ืœืžื—ื•ืง ืืช ื”ื“ื’ืœ ื™ืฉื™ืจื•ืช ื‘-DB ืื• ืœื ืงื•ืช sessionStorage.has_seen_welcome_modal.

ืกื ื›ืจื•ืŸ ืœืžื“ืจื™ืš ื”ืขื“ื›ื ื™๏ƒ

  • USER_GUIDE.md ื”ื•ื ืžืงื•ืจ ื”ืืžืช โ€“ ืื™ืŸ ืฉื›ืคื•ืœ ื‘-DB.

  • get_internal_share() ืžื—ืคืฉ ืืช ื”ืžื–ื”ื™ื welcome / welcome-quickstart (ื›ื•ืœืœ ื”ืžื–ื”ื™ื ื”ื”ื™ืกื˜ื•ืจื™ื™ื) ื•ืžื—ื–ื™ืจ ืืช ืชื•ื›ืŸ ื”ืงื•ื‘ืฅ.

  • ืื ื”ืงื•ื‘ืฅ ื—ืกืจ, ื”ืžื•ื“ืืœ ืžื•ืกืชืจ ื•ื ืจืฉืžืช ื”ืชืจืื” ื‘-log. ื•ื“ืื• ืฉื”ืงื•ื‘ืฅ ืงื™ื™ื ื‘ื›ืœ Deploy.

ืื™ืš ืœืขื“ื›ืŸ๏ƒ

  1. ืขืจื›ื• ืืช webapp/USER_GUIDE.md (ืœื“ื•ื’ืžื”: ืขื“ื›ื•ืŸ โ€ืžื” ื—ื“ืฉโ€œ).

  2. ื•ื“ืื• ืฉื”ืขืžื•ื“ /share/welcome?view=md ืžืฆื™ื’ ืืช ื”ืฉื™ื ื•ื™.

  3. ืื™ืŸ ืฆื•ืจืš ืœื”ืจื™ืฅ Job ื ืคืจื“ โ€“ ื”ืžื•ื“ืืœ ื™ืžืฉื•ืš ืืช ื”ื˜ืงืกื˜ ืื•ื˜ื•ืžื˜ื™ืช.

ืงื™ืฉื•ืจื™ ืžื“ืจื™ื›ื™ื (Anchors)๏ƒ

  • Primary: /share/welcome?view=md

  • Secondary: /share/welcome-quickstart?view=md

Best Practices โ€“ ืกื™ืžื•ืŸ ืžืฉืชืžืฉื™ื ื—ื“ืฉื™ื๏ƒ

  • ืกืžื ื• has_seen_welcome_modal ื’ื ื‘-session ื›ื“ื™ ืœืžื ื•ืข ื”ื‘ื”ื•ื‘ ืงืœื™ื™ื ื˜.

  • ื ื™ืชืŸ ืœืขืฉื•ืช reuse ืฉืœ ื”ื“ื’ืœ ืขื‘ื•ืจ ืคื™ืฆืณืจื™ื โ€ื—ื“ ืคืขืžื™ื™ืโ€œ ื ื•ืกืคื™ื.

session: { has_seen_welcome_modal: true }
DB: users.has_seen_welcome_modal = true

ื“ื•ื’ืžืช JS โ€“ ืžื•ื“ืืœ ืขื Ajax๏ƒ

function welcomeModalInit() {
  const modal = document.getElementById('welcome-modal');
  if (!modal) return;

  async function ackAndHide() {
    try {
      const res = await fetch('/api/welcome/ack', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({})
      });
      if (!res.ok) throw new Error('ack failed');
      try { sessionStorage.setItem('has_seen_welcome_modal', '1'); } catch (e) {}
      modal.style.display = 'none';
    } catch (e) {
      console.warn('welcome ack error', e);
    }
  }

  const primary = modal.querySelector('[data-action="primary"]');
  const secondary = modal.querySelector('[data-action="secondary"]');
  const skip = modal.querySelector('[data-action="skip"]');

  if (primary) primary.addEventListener('click', ackAndHide);
  if (secondary) secondary.addEventListener('click', ackAndHide);
  if (skip) skip.addEventListener('click', (ev) => {
    ev.preventDefault();
    ackAndHide();
  });
}

window.addEventListener('DOMContentLoaded', () => {
  try {
    if (sessionStorage.getItem('has_seen_welcome_modal') === '1') return;
  } catch (e) {}
  welcomeModalInit();
});

API ืงืฉื•ืจ๏ƒ

  • POST /api/welcome/ack โ€“ ืžืกืžืŸ ืืช ื”ื“ื’ืœ ื•ืžื—ื–ื™ืจ { "ok": true }.

  • POST /api/shared/save โ€“ ืœืฉื™ืชื•ืฃ ื•ื”ืคืฆื” ืฉืœ ื”ืžื“ืจื™ื›ื™ื ืขืฆืžื.


Interactive Tour (Driver.js)๏ƒ

ื”ืกื™ื•ืจ ื”ืื™ื ื˜ืจืืงื˜ื™ื‘ื™ ื—ื™ ื‘ืื•ืชื• ืงื•ื‘ืฅ (webapp/templates/base.html) ืชื—ืช initInteractiveWalkthrough(). ื”ื•ื ืžื‘ื•ืกืก ืขืœ Driver.js ื•ืžื“ื’ื™ืฉ ืืช ื”ืคืขื•ืœื•ืช ื”ืžืจื›ื–ื™ื•ืช ื‘ืžืกืš ื”ืงื‘ืฆื™ื.

ืžืชื™ ื”ืกื™ื•ืจ ื ืคืชื—?๏ƒ

  • ืžืฉืชืžืฉ ืžื—ื•ื‘ืจ (session.user_id).

  • ื›ืชื•ื‘ืช: /files (ืžื•ื’ื“ืจ ื‘-AUTO_PATHS).

  • localStorage["codekeeper_walkthrough_v1"] !== '1'.

  • ืงื™ื™ืžื™ื ืืœืžื ื˜ื™ื ืคืขื™ืœื™ื (ื ื‘ื“ืง ืขโ€œื™ buildSteps() ื•-isElementTourVisible()).

  • ื”-Welcome Modal ื›ื‘ืจ ื”ื•ืกืจ (MutationObserver).

ืฉืœื‘ื™ ื”ืกื™ื•ืจ๏ƒ

ืฉืœื‘

ืืœืžื ื˜ (ID)

ืชื™ืื•ืจ

ืคืชื™ื—

โ€”

ืžืกืจ โ€ื‘ืจื•ื›ื™ื ื”ื‘ืื™ืโ€œ ื•ื”ืกื‘ืจ ืงืฆืจ ืขืœ ืžื˜ืจืช ื”ืกื™ื•ืจ.

ื™ืฆื™ืจืช ืงื•ื‘ืฅ ื—ื“ืฉ

#tourCreateButton (webapp/templates/files.html)

ืžืฆื™ื’ ืืช ื›ืคืชื•ืจ ื”ื”ืขืœืื” ื•ื”ื•ืกืคืช ืงื‘ืฆื™ื/ืงื˜ืขื™ ืงื•ื“.

ื—ื™ืคื•ืฉ ื’ืœื•ื‘ืœื™

#globalSearchInput

ืžืกื‘ื™ืจ ืขืœ ื”ื—ื™ืคื•ืฉ ืœืคื™ ืฉื, ืชื•ื›ืŸ, ืชื’ื™ื•ืช ื•ืฉืคื•ืช.

ื”ืื•ืกืคื™ื ืฉืœื™

#tourCollectionsNav (ื“ืœื’ ื‘ืžื•ื‘ื™ื™ืœ)

ืžื“ื’ื™ืฉ ืืช ืชืคืจื™ื˜ ื”ืื•ืกืคื™ื ื•ื™ืชืจื•ื ื•ืช ื”ืฉื™ืชื•ืฃ.

Outro

โ€”

ื”ื•ื“ืขืช ืกื™ื•ื ืขื ืจืžื– ืœื”ืคืขืœื” ื—ื•ื–ืจืช.

ืœื”ื•ืกืคืช ืฉืœื‘ ื—ื“ืฉ โ€“ ืขื“ื›ื ื• ืืช buildSteps() ื•ื”ืงืคื™ื“ื• ืฉื”ืืœืžื ื˜ ืžืงื‘ืœ ืžื–ื”ื” ืงื‘ื•ืข ื•ื’ืœื•ื™.

ื”ืคืขืœื” ื™ื“ื ื™ืช ื•ืื™ืคื•ืก๏ƒ

  • URL: ?tour=restart ืื• ?tour=start โ†’ ืžืืคืก ืืช codekeeper_walkthrough_v1, ืžืคืขื™ืœ ืืช ื”ืกื™ื•ืจ ื•ืžื•ื—ืง ืืช ื”ืคืจืžื˜ืจ ืžื”-URL ื‘ืืžืฆืขื•ืช history.replaceState.

  • Console API:

    • window.CodeKeeperTour.start() โ€“ ืžืคืขื™ืœ ืืช ื”ืกื™ื•ืจ ื‘ืžืงื•ื.

    • window.CodeKeeperTour.reset() โ€“ ืžื•ื—ืง ืืช ื”ื“ื’ืœ ื”ืžืงื•ืžื™.

    • window.CodeKeeperTour.hasSeen() โ€“ ืฉื™ืžื•ืฉื™ ืœ-QA.

  • ื ื™ืงื•ื™ ื™ื“ื ื™: ืžื—ื™ืงืช localStorage.codekeeper_walkthrough_v1 ืžืฉื™ื’ื” ืืช ืื•ืชื• ืืคืงื˜.

ืชื—ื–ื•ืงื” ืœืžืคืชื—ื™ื๏ƒ

  • Driver.js ื ื˜ืขืŸ ื“ืจืš window.driver.js.driver. ืื ื”ืงื•ื‘ืฅ ืœื ื ื˜ืขืŸ โ€“ getDriverFactory() ื™ื—ื–ื™ืจ null ื•ืชืจืื• ืฉื’ื™ืืช ืงื•ื ืกื•ืœ.

  • ื”ื”ื’ื“ืจื•ืช (stageBackground, ื˜ืงืกื˜ื™ ื”ื›ืคืชื•ืจื™ื, smoothScroll) ื ืžืฆืื•ืช ื‘ืื•ืชื• ื‘ืœื•ืง โ€“ ืื™ืŸ ืฆื•ืจืš ืœืฉื ื•ืช ืืช Driver.js ืขืฆืžื•.

  • ThemeWizard.watchDriver(driver) ื ืงืจื ืื—ืจื™ driver.drive() โ€“ ืืœ ืชืกื™ืจื• ืืช ื”ืงืจื™ืื” ื›ื“ื™ ืœืฉืžื•ืจ ืขืœ ื”ืกื“ืจ ืžื•ืœ ื”ื•ื•ื™ื–ืืจื“.

  • ื”ืชืืžื•ืช RTL ืžื•ื‘ื ื•ืช ื‘ืงื•ื‘ืฅ (/* ื”ืชืืžื•ืช RTL ืœ-Driver.js */). ืื ืžื•ืกื™ืคื™ื ืฉืœื‘ื™ื ื—ื“ืฉื™ื, ื•ื“ืื• ืฉื”ื˜ืงืกื˜ื™ื ืงืฆืจื™ื ืžืกืคื™ืง ืœืžืกื›ื™ื ืฆืจื™ื.

Troubleshooting โ€“ โ€ืœืžื” ื”ืกื™ื•ืจ ืœื ืžื•ืคื™ืข?โ€œ๏ƒ

  1. ื‘ื“ืงื• localStorage.getItem('codekeeper_walkthrough_v1').

  2. ื•ื“ืื• ืฉืืชื ื‘ื ืชื™ื‘ /files ื•ืžื—ื•ื‘ืจื™ื.

  3. ื•ื™ื“ืื• ืฉืื™ืŸ ืžื•ื“ืืœื™ื ืื—ืจื™ื ืคืชื•ื—ื™ื โ€“ ื”-MutationObserver ื™ืžืชื™ืŸ ืœื”ื™ืขืœืžื•ืช ืฉืœื”ื.

  4. ื—ืคืฉื• ื‘ืงื•ื ืกื•ืœ ื”ื•ื“ืขื” ืœื’ื‘ื™ window.driver โ€“ ื‘ืžื™ื“ื” ื•ื”ืกืคืจื™ื™ื” ืœื ื ื˜ืขื ื”, ื”ืกื™ื•ืจ ืœื ื™ื•ืคืขืœ.

  5. Content blockers ืฉื—ื•ืกืžื™ื localStorage ืขืœื•ืœื™ื ืœืžื ื•ืข ืกื™ืžื•ืŸ ื“ื’ืœ; ื‘ืžืงืจื” ื›ื–ื” ?tour=restart ืขืฉื•ื™ ืฉืœื ืœืขื‘ื•ื“.

ืฆื™ืœื•ืžื™ ืžืกืš / GIF๏ƒ

Interactive Tour Overlay

ื”ืชืจืฉื™ื ืžื“ื’ื™ื ืืช Driver.js ื‘ืขืช ื”ื“ื’ืฉืช ื›ืคืชื•ืจ ื™ืฆื™ืจืช ื”ืงื•ื‘ืฅ, ื™ื—ื“ ืขื ื›ืคืชื•ืจื™ โ€ื”ื‘ืโ€œ ื•โ€œื“ืœื’โ€œ ื‘ืขื‘ืจื™ืช.


Theme Picker Wizard (Personalization)๏ƒ

ื•ื™ื–ืืจื“ ื”ืคืจืกื•ื ืœื™ื–ืฆื™ื” ืžืฉืœื™ื ืืช ืชื”ืœื™ืš ื”-Onboarding ื•ืžืืคืฉืจ ืœื‘ื—ื•ืจ Theme ื›ื‘ืจ ื‘ื‘ื™ืงื•ืจ ื”ืจืืฉื•ืŸ, ื›ื•ืœืœ ืชืฆื•ื’ื” ื—ื™ื” ื•ืงืจื™ืื” ืœ-API ืœืฉืžื™ืจืช ื”ื”ืขื“ืคื”.

ืกืงื™ืจื” ื›ืœืœื™ืช๏ƒ

  • ืžื•ืคืขืœ ืจืง ืœืžืฉืชืžืฉื™ื ืžื—ื•ื‘ืจื™ื ื•ื‘ื ืชื™ื‘ /files.

  • theme_wizard_seen ืžื•ื ืข ื”ืฆื’ื” ื—ื•ื–ืจืช; ืฉืžื™ืจื” ืื• ื“ืœื’ ืฉื ื™ื”ื ืžืกืžื ื™ื ืืช ื”ื“ื’ืœ.

  • Live Preview ืžืชื‘ืฆืข ื‘ืืžืฆืขื•ืช ืขื“ื›ื•ืŸ document.documentElement.dataset.theme ื‘ื–ืžืŸ ืืžืช.

ื˜ืจื™ื’ืจื™ื ื•ื”ื’ื ื•ืช๏ƒ

  1. waitForWelcome() ืžืžืชื™ืŸ ืฉื”ืžื•ื“ืืœ ื”ืจืืฉื™ ื™ื™ืฆื ืžื”-DOM.

  2. ืื ื”ืกื™ื•ืจ ืจืฅ โ€“ ThemeWizard.watchDriver() ืžืื–ื™ืŸ ืœืื™ืจื•ืข destroyed ืฉืœ Driver.js ื•ืจืง ืื– ืคื•ืชื— ืืช ื”ื•ื•ื™ื–ืืจื“.

  3. ืื ื”ืกื™ื•ืจ ืœื ื”ื•ืคืขืœ (ืื™ืŸ ืืœืžื ื˜ื™ื/ืžืฉืชืžืฉ ืขืœ ืžื•ื‘ื™ื™ืœ) โ€“ scheduleFallback() ืคื•ืชื— ืืช ื”ื•ื•ื™ื–ืืจื“ ืœืื—ืจ ~9 ืฉื ื™ื•ืช.

  4. ื ื™ืชืŸ ืœืคืชื•ื— ื‘ื›ืคื™ื™ื” ื“ืจืš ?theme_wizard=restart ืื• window.ThemeWizard.open().

ืžืžืฉืง ื•ื—ื•ื•ื™ื™ืช ืžืฉืชืžืฉ๏ƒ

  • ืฉืœื•ืฉ ืืคืฉืจื•ื™ื•ืช ื‘ืจื™ืจืช ืžื—ื“ืœ: Nebula, Rose Pine Dawn, Classic (data-theme-option).

  • ืจื™ื—ื•ืฃ/ืคื•ืงื•ืก/ืงืœื™ืง ืžื—ืœื™ืคื™ื ืืช ื”-theme ื‘ื–ืžืŸ ืืžืช.

  • Live Preview ืžืžื•ืงื ื‘ืฆื“ ื™ืžื™ืŸ (ืชืœื•ืช ื‘-CSS), ื•ื”ืชื•ื›ืŸ ื›ื•ืœื• ืชื•ืžืš RTL.

  • ื ื’ื™ืฉื•ืช:

    • Tab ื ืฉืžืจ ื‘ืชื•ืš ื”-dialog (focus trap).

    • Enter / Space ื‘ื•ื—ืจื™ื Theme.

    • Esc ืกื•ื’ืจ ืืช ื”ื•ื•ื™ื–ืืจื“ ื‘ืœื™ ืœืฉืžื•ืจ.

  • ื›ืคืชื•ืจื™ื:

    • ืฉืžื•ืจ ื•ื”ืžืฉืš (data-action="save") โ€“ ืžืคืขื™ืœ persistTheme() + ืงืจื™ืื” ืœ-POST /api/ui_prefs.

    • ื“ืœื’ / ืื™ื™ืงื•ืŸ ื”ืกื’ื™ืจื” / ืงืœื™ืง ืขืœ ื”ืจืงืข โ€“ ืกื•ื’ืจื™ื ืœืœื ืฉืžื™ืจื” ืืš ืžืกืžื ื™ื theme_wizard_seen.

ื”ืชืžื“ื” ื•ืกื ื›ืจื•ืŸ ืฉืจืช๏ƒ

  • localStorage.user_theme โ€“ ืขืจื›ืช ื”ื ื•ืฉื ืฉื ื‘ื—ืจื”.

  • localStorage.dark_mode_preference โ€“ ื ืฉืžืจืช ืจืง ืขื‘ื•ืจ ืขืจื›ื•ืช ื›ื”ื•ืช (mapDarkModePreference).

  • ื‘ืงืฉื” ืœ-POST /api/ui_prefs ืฉื•ืœื—ืช { theme } ื•ืžืืคืฉืจืช ืœืฉืจืช ืœื˜ืขื•ืŸ ืืช ื”-theme ื›ื‘ืจ ื‘ืฉืœื‘ ื”-render ื”ื‘ื.

๐Ÿ› ๏ธ Debugging & Reset๏ƒ

  • URL: ?theme_wizard=restart (ืื• start). ื”ืคืจืžื˜ืจ ื ืžื—ืง ืžื”ื›ืชื•ื‘ืช ืื—ืจื™ ื”ืคืชื™ื—ื”.

  • Console:

    • window.ThemeWizard.open() โ€“ ืคื•ืชื— ืืช ื”ื•ื•ื™ื–ืืจื“.

    • window.ThemeWizard.resetSeen() โ€“ ืžื•ื—ืง ืืช ื”ื“ื’ืœ.

    • window.ThemeWizard.hasSeen() โ€“ ืžื—ื–ื™ืจ ืกื˜ื˜ื•ืก.

    • window.ThemeWizard.scheduleFallback() โ€“ ืžืคืขื™ืœ ืžื—ื“ืฉ ืืช ืžื ื’ื ื•ืŸ ื”ื–ืžืŸ.

  • ื ื™ืงื•ื™ ื™ื“ื ื™: ืžื—ืงื• ืืช theme_wizard_seen, user_theme, dark_mode_preference ื›ื“ื™ ืœื“ืžื•ืช ืžืฉืชืžืฉ ื—ื“ืฉ.

ืžื“ืจื™ืš ื‘ื“ื™ืงื•ืช (QA)๏ƒ

  1. ืคืชื—ื• ื—ืœื•ืŸ Incognito ืื• ื ืงื• ืืช ื›ืœ ืžืคืชื—ื•ืช ื”-onboarding ื‘-localStorage.

  2. ืืคืฉืจื• ืœ-Welcome Modal ืœื”ื•ืคื™ืข ื•ืœื”ื™ืกื’ืจ, ื•ื“ืื• ืฉื”ืกื™ื•ืจ ืจืฅ. ื‘ืกื™ื•ื, ืฆืคื• ืฉื”ื•ื•ื™ื–ืืจื“ ื ืคืชื— ืื•ื˜ื•ืžื˜ื™ืช.

  3. ื‘ื“ืงื• Live Preview โ€“ ื›ืœ ื‘ื—ื™ืจื” ืฆืจื™ื›ื” ืœืฉื ื•ืช ืืช data-theme ื•ืืช ื”-CSS.

  4. ืœื—ืฆื• โ€ืฉืžื•ืจ ื•ื”ืžืฉืšโ€œ ื•ื‘ื“ืงื• ื‘-Network ืฉื”ืชืงื‘ืœื” ืชืฉื•ื‘ืช 200 ืž-/api/ui_prefs. ืจืขื ื ื• ื›ื“ื™ ืœื•ื•ื“ื ืฉื”ื‘ื—ื™ืจื” ื ืฉืžืจื”.

  5. ืœื—ืฆื• โ€ื“ืœื’โ€œ โ€“ ื•ื“ืื• ืฉื”ื•ื•ื™ื–ืืจื“ ืœื ื—ื•ื–ืจ ืœืื—ืจ ืจืขื ื•ืŸ (ื›ื™ theme_wizard_seen ืกื•ืžืŸ).

  6. ื‘ื“ืงื• ?theme_wizard=restart โ†’ ืืžื•ืจ ืœืคืชื•ื— ื‘ื›ืคื™ื™ื” ื•ืœืžื—ื•ืง ืืช ื”ืคืจืžื˜ืจ ืžื”-URL.

  7. ื”ืชื ืชืงื• (Guest) โ€“ ื•ื•ื“ืื• ืฉื”ื•ื•ื™ื–ืืจื“ ืœื ืžื•ืฆื’ ืœืžืฉืชืžืฉื™ื ืื ื•ื ื™ืžื™ื™ื.

ืฆื™ืœื•ืžื™ ืžืกืš๏ƒ

Theme Wizard Preview

ื”ืžื—ืฉื” ืฉืœ ื”ื•ื•ื™ื–ืืจื“ ืขื ืฉืœื•ืฉ ืขืจื›ื•ืช ื”ื ื•ืฉื, ื›ืคืชื•ืจื™ ื”ืคืขื•ืœื” ื•-Live Preview.

ืงื™ืฉื•ืจื™ื ืจืœื•ื•ื ื˜ื™ื™ื๏ƒ

  • webapp/overview.rst โ€“ ื”ืกื‘ืจ ืžืœื ืขืœ ืžืกืš ื”ื”ื’ื“ืจื•ืช (ืฉื™ื ื•ื™ Theme ื™ื“ื ื™ ืœืื—ืจ ืžื›ืŸ).

  • webapp/static-checklist.rst โ€“ ืงื•ื•ื™ื ืžื ื—ื™ื ืœื ื™ื’ื•ื“ื™ื•ืช ื•ื ื’ื™ืฉื•ืช UI.

  • webapp/api-reference.rst โ€“ ืคืจื˜ื™ื ื ื•ืกืคื™ื ืขืœ POST /api/ui_prefs.


Troubleshooting ืžืจื•ื›ื– โ€“ โ€ืœืžื” ืฉื•ื ื“ื‘ืจ ืœื ืงื•ืคืฅ ืœื™?โ€œ๏ƒ

  1. ื‘ื“ืงื• localStorage โ€“ codekeeper_walkthrough_v1, theme_wizard_seen, user_theme, dark_mode_preference. ืžื—ื™ืงื” ืชื—ื–ื™ืจ ืืช ื”ื”ืจืฆื”.

  2. ื ืชื™ื‘ ื•ืกื˜ื˜ื•ืก ื›ื ื™ืกื” โ€“ ืฉื ื™ ื”ืจื›ื™ื‘ื™ื ืจืฆื™ื ืจืง ื‘-/files ื•ืœืžืฉืชืžืฉ ืžื—ื•ื‘ืจ.

  3. ืžื•ื“ืืœื™ื ืื—ืจื™ื โ€“ ื›ืœ ืžื•ื“ืืœ ืฉื—ื•ืกื ืืช ื”ื“ืฃ ื™ืขื›ื‘ ืืช ื”ืกื™ื•ืจ/ื”ื•ื•ื™ื–ืืจื“ ืขื“ ืœื”ืกืจืชื•.

  4. Driver.js ืœื ื–ืžื™ืŸ โ€“ ืœืœื ื”ืกืคืจื™ื™ื” ืœื ื™ื•ืคืขืœ ืกื™ื•ืจ; Theme Wizard ื™ื•ืคืขืœ ืจืง ืื—ืจื™ fallback.

  5. ื—ื•ืกืžื™ ืชื•ื›ืŸ โ€“ ื”ืจื—ื‘ื•ืช ืฉืžื•ื ืขื•ืช ื’ื™ืฉื” ืœ-localStorage ืื• ืœ-MutationObserver ืขืœื•ืœื•ืช ืœืฉื‘ื•ืจ ืืช ื”ืจืฆืฃ.

  6. ื‘ื“ื™ืงืช Console APIs โ€“ CodeKeeperTour.start() ื•-ThemeWizard.open() ื”ืŸ ื”ื“ืจืš ื”ืงืœื” ืœื•ื•ื“ื ืฉื”ืงื•ื“ ื˜ืขื•ืŸ.


ืžื“ื™ื” ื•ื”ืจื—ื‘ื•ืช๏ƒ

  • ืชืจืฉื™ื ื–ืจื™ืžื”: docs/images/onboarding-flow.svg.

  • ืฆื™ืœื•ื ืกื™ื•ืจ Driver.js: docs/images/interactive-tour-overview.svg.

  • ืฆื™ืœื•ื Theme Wizard: docs/images/theme-wizard-preview.svg.

  • ืœืื—ืจ ื”ื•ืกืคืช ืžื“ื™ื” ื—ื“ืฉื”, ื”ืจื™ืฆื• make html ื‘ืชื•ืš docs/ ื›ื“ื™ ืœื•ื•ื“ื ืฉืื™ืŸ ืื–ื”ืจื•ืช Sphinx.