@beastmode-develeap/beastmode 0.1.214 → 0.1.216

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,7 +15,7 @@
15
15
  }
16
16
  </script>
17
17
  <!--BOARD_DATA-->
18
- <script>window.__BUILD_STAMP__ = "20260509-230834-09eb714";</script>
18
+ <script>window.__BUILD_STAMP__ = "20260510-004632-5de247d";</script>
19
19
  <link rel="preconnect" href="https://fonts.googleapis.com">
20
20
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
21
21
  <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
@@ -3563,6 +3563,167 @@ input[type="range"]::-webkit-slider-thumb {
3563
3563
  }
3564
3564
  .btn-secondary:hover { background: var(--surface-elevated); border-color: var(--text-muted); }
3565
3565
 
3566
+ /* ================================================================
3567
+ ONBOARDING TOUR & CHECKLIST
3568
+ ================================================================ */
3569
+
3570
+ .tour-backdrop {
3571
+ position: fixed;
3572
+ inset: 0;
3573
+ background: rgba(0, 0, 0, 0.6);
3574
+ z-index: 9000;
3575
+ animation: fadeIn 0.2s ease;
3576
+ }
3577
+ .tour-spotlight {
3578
+ position: fixed;
3579
+ z-index: 9001;
3580
+ border-radius: 8px;
3581
+ box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.6);
3582
+ pointer-events: none;
3583
+ transition: top 0.3s ease, left 0.3s ease, width 0.3s ease, height 0.3s ease;
3584
+ }
3585
+ .tour-tooltip {
3586
+ position: fixed;
3587
+ z-index: 9002;
3588
+ background: var(--bg-card);
3589
+ border: 1px solid var(--border);
3590
+ border-radius: 12px;
3591
+ padding: 24px;
3592
+ max-width: 380px;
3593
+ width: 90vw;
3594
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
3595
+ animation: slideUp 0.25s ease;
3596
+ }
3597
+ .tour-tooltip h3 {
3598
+ font-size: 18px;
3599
+ font-weight: 600;
3600
+ color: var(--text);
3601
+ margin: 0 0 8px 0;
3602
+ }
3603
+ .tour-tooltip p {
3604
+ font-size: 14px;
3605
+ color: var(--text-secondary);
3606
+ line-height: 1.5;
3607
+ margin: 0 0 20px 0;
3608
+ }
3609
+ .tour-step-indicator {
3610
+ display: flex;
3611
+ gap: 6px;
3612
+ margin-bottom: 16px;
3613
+ }
3614
+ .tour-step-dot {
3615
+ width: 8px;
3616
+ height: 8px;
3617
+ border-radius: 50%;
3618
+ background: var(--border);
3619
+ }
3620
+ .tour-step-dot.active {
3621
+ background: var(--accent);
3622
+ }
3623
+ .tour-actions {
3624
+ display: flex;
3625
+ justify-content: space-between;
3626
+ align-items: center;
3627
+ }
3628
+ .tour-actions .tour-skip {
3629
+ background: none;
3630
+ border: none;
3631
+ color: var(--text-muted);
3632
+ cursor: pointer;
3633
+ font-size: 13px;
3634
+ font-family: var(--font-sans);
3635
+ text-decoration: underline;
3636
+ padding: 0;
3637
+ }
3638
+ .tour-actions .tour-skip:hover { color: var(--text); }
3639
+ .tour-actions-right { display: flex; gap: 8px; }
3640
+
3641
+ .onboarding-checklist {
3642
+ background: var(--bg-card);
3643
+ border: 1px solid var(--border);
3644
+ border-radius: 12px;
3645
+ padding: 20px;
3646
+ margin-bottom: 16px;
3647
+ }
3648
+ .onboarding-checklist h3 {
3649
+ font-size: 15px;
3650
+ font-weight: 600;
3651
+ color: var(--text);
3652
+ margin: 0 0 4px 0;
3653
+ }
3654
+ .onboarding-checklist .subtitle {
3655
+ font-size: 13px;
3656
+ color: var(--text-muted);
3657
+ margin: 0 0 16px 0;
3658
+ }
3659
+ .checklist-item {
3660
+ display: flex;
3661
+ align-items: center;
3662
+ gap: 10px;
3663
+ padding: 8px 0;
3664
+ font-size: 14px;
3665
+ color: var(--text-secondary);
3666
+ }
3667
+ .checklist-item.completed {
3668
+ color: var(--text-muted);
3669
+ text-decoration: line-through;
3670
+ }
3671
+ .checklist-check {
3672
+ width: 20px;
3673
+ height: 20px;
3674
+ border-radius: 50%;
3675
+ border: 2px solid var(--border);
3676
+ display: flex;
3677
+ align-items: center;
3678
+ justify-content: center;
3679
+ flex-shrink: 0;
3680
+ font-size: 12px;
3681
+ line-height: 1;
3682
+ }
3683
+ .checklist-check.done {
3684
+ background: var(--success);
3685
+ border-color: var(--success);
3686
+ color: #fff;
3687
+ }
3688
+ .onboarding-progress {
3689
+ height: 4px;
3690
+ background: var(--border);
3691
+ border-radius: 2px;
3692
+ margin: 16px 0 12px;
3693
+ overflow: hidden;
3694
+ }
3695
+ .onboarding-progress-fill {
3696
+ height: 100%;
3697
+ background: var(--accent);
3698
+ border-radius: 2px;
3699
+ transition: width 0.4s ease;
3700
+ }
3701
+ .onboarding-tour-btn {
3702
+ width: 100%;
3703
+ margin-top: 12px;
3704
+ }
3705
+ .onboarding-dismiss {
3706
+ display: block;
3707
+ text-align: center;
3708
+ margin-top: 8px;
3709
+ background: none;
3710
+ border: none;
3711
+ color: var(--text-muted);
3712
+ font-size: 12px;
3713
+ cursor: pointer;
3714
+ font-family: var(--font-sans);
3715
+ width: 100%;
3716
+ padding: 4px 0;
3717
+ }
3718
+ .onboarding-dismiss:hover { color: var(--text); }
3719
+
3720
+ @media (max-width: 900px) {
3721
+ .tour-tooltip {
3722
+ max-width: 90vw;
3723
+ padding: 20px;
3724
+ }
3725
+ }
3726
+
3566
3727
  /* ================================================================
3567
3728
  COSTS PAGE
3568
3729
  ================================================================ */
@@ -4043,7 +4204,7 @@ function Sidebar({ currentHash, factoryName, theme, onToggleTheme, selectedProje
4043
4204
  ];
4044
4205
 
4045
4206
  return html`
4046
- <aside class=${'sidebar' + (mobileOpen ? ' open' : '')}>
4207
+ <aside class=${'sidebar' + (mobileOpen ? ' open' : '')} data-tour="sidebar">
4047
4208
  <div class="sidebar-brand">
4048
4209
  <svg class="brand-logo-svg" viewBox="0 0 400 320" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="BeastMode — Dark Factory">
4049
4210
  <g transform="translate(200,130)">
@@ -4093,7 +4254,8 @@ function Sidebar({ currentHash, factoryName, theme, onToggleTheme, selectedProje
4093
4254
  ${links.map(link => html`
4094
4255
  <li key=${link.path}>
4095
4256
  <a href=${link.path}
4096
- class=${currentHash === link.path || (link.path !== '#/' && currentHash.startsWith(link.path)) ? 'active' : ''}>
4257
+ class=${currentHash === link.path || (link.path !== '#/' && currentHash.startsWith(link.path)) ? 'active' : ''}
4258
+ data-tour=${link.path === '#/help' ? 'help-link' : null}>
4097
4259
  <${Icon} name=${link.icon} />
4098
4260
  ${link.label}
4099
4261
  </a>
@@ -4134,11 +4296,15 @@ function statusBadgeClass(status) {
4134
4296
  function DashboardPage({ selectedProject, onProjectChange }) {
4135
4297
  const [status, setStatus] = useState(null);
4136
4298
  const [recentItems, setRecentItems] = useState([]);
4299
+ const [allItems, setAllItems] = useState([]);
4137
4300
  const [runs, setRuns] = useState([]);
4138
4301
  const [projects, setProjects] = useState([]);
4139
4302
  const [runnerData, setRunnerData] = useState({ count: 0, offline: 0 });
4140
4303
  const [loading, setLoading] = useState(true);
4141
4304
  const [error, setError] = useState(null);
4305
+ const [onboardingDismissed, setOnboardingDismissed] = useState(() => {
4306
+ try { return !!localStorage.getItem('beastmode-onboarding-dismissed'); } catch (_) { return false; }
4307
+ });
4142
4308
 
4143
4309
  useEffect(() => {
4144
4310
  function fetchDashboard() {
@@ -4149,7 +4315,10 @@ function DashboardPage({ selectedProject, onProjectChange }) {
4149
4315
  api('GET', '/api/projects').catch(() => ({ projects: [] })),
4150
4316
  ]).then(([s, boardData, runsData, projectsData]) => {
4151
4317
  setStatus(s);
4152
- const sorted = (boardData.items || [])
4318
+ const allBoardItems = boardData.items || [];
4319
+ setAllItems(allBoardItems);
4320
+ const sorted = allBoardItems
4321
+ .slice()
4153
4322
  .sort((a, b) => new Date(normalizeDt(b.updated_at || b.created_at) || 0) - new Date(normalizeDt(a.updated_at || a.created_at) || 0))
4154
4323
  .slice(0, 10);
4155
4324
  setRecentItems(sorted);
@@ -4336,6 +4505,48 @@ function DashboardPage({ selectedProject, onProjectChange }) {
4336
4505
  </div>
4337
4506
 
4338
4507
  <div class="page-dashboard-sidebar">
4508
+ ${!onboardingDismissed && (() => {
4509
+ const hasProject = projects.length >= 1;
4510
+ const hasItem = allItems.length >= 1;
4511
+ const hasDone = allItems.some(i => (i.status || '').toLowerCase() === 'done');
4512
+ const checks = [
4513
+ { label: 'Add a project', done: hasProject },
4514
+ { label: 'Create your first task', done: hasItem },
4515
+ { label: 'Complete a task', done: hasDone },
4516
+ ];
4517
+ const completedCount = checks.filter(c => c.done).length;
4518
+ const allDone = completedCount === checks.length;
4519
+ const dismiss = () => {
4520
+ try { localStorage.setItem('beastmode-onboarding-dismissed', 'true'); } catch (_) {}
4521
+ setOnboardingDismissed(true);
4522
+ };
4523
+ return html`
4524
+ <div class="onboarding-checklist" data-testid="onboarding-checklist">
4525
+ <h3>Getting Started</h3>
4526
+ <p class="subtitle">Complete these steps to get up and running</p>
4527
+ ${allDone ? html`
4528
+ <p style="font-size:14px;color:var(--success);font-weight:600;margin:8px 0 0;" data-testid="onboarding-congrats">
4529
+ You're all set! BeastMode is ready to build.
4530
+ </p>
4531
+ ` : html`
4532
+ <div class="onboarding-progress">
4533
+ <div class="onboarding-progress-fill" style=${'width:' + ((completedCount / checks.length) * 100) + '%'}></div>
4534
+ </div>
4535
+ ${checks.map((c, i) => html`
4536
+ <div key=${i} class=${'checklist-item' + (c.done ? ' completed' : '')} data-testid=${'checklist-item-' + i}>
4537
+ <div class=${'checklist-check' + (c.done ? ' done' : '')}>${c.done ? '✓' : ''}</div>
4538
+ <span>${c.label}</span>
4539
+ </div>
4540
+ `)}
4541
+ <button class="btn btn-primary btn-pill onboarding-tour-btn" data-testid="onboarding-tour-btn"
4542
+ onClick=${() => { if (typeof window.__bmStartTour === 'function') window.__bmStartTour(); }}>
4543
+ Take the guided tour
4544
+ </button>
4545
+ `}
4546
+ <button class="onboarding-dismiss" data-testid="onboarding-dismiss" onClick=${dismiss}>Dismiss</button>
4547
+ </div>
4548
+ `;
4549
+ })()}
4339
4550
  <div class="card">
4340
4551
  <div class="card-header">
4341
4552
  <h3>Recent Activity</h3>
@@ -6981,7 +7192,7 @@ function BoardPage({ selectedProject }) {
6981
7192
 
6982
7193
  ${error && html`<div class="error-msg">${error}</div>`}
6983
7194
 
6984
- <div class="board-header-row">
7195
+ <div class="board-header-row" data-tour="board-header">
6985
7196
  <div class="board-stats-bar">
6986
7197
  <span class="stat-label">${viewMode === 'pipeline' ? 'Pipeline' : 'Board'}</span>
6987
7198
  <span class="stat-item"><strong>${totalItems}</strong>${isFiltered ? '/' + items.length : ''} total</span>
@@ -7044,7 +7255,7 @@ function BoardPage({ selectedProject }) {
7044
7255
  `}
7045
7256
  </div>
7046
7257
 
7047
- <button class="btn btn-primary" onClick=${() => setShowCreateDialog(true)}>
7258
+ <button class="btn btn-primary" data-tour="add-item" onClick=${() => setShowCreateDialog(true)}>
7048
7259
  <${Icon} name="plus" size=${14} />
7049
7260
  New Task
7050
7261
  </button>
@@ -9032,10 +9243,33 @@ function HooksTab() {
9032
9243
  // ================================================================
9033
9244
 
9034
9245
  function HelpPage() {
9246
+ const startTour = () => {
9247
+ navigate('#/board');
9248
+ setTimeout(() => {
9249
+ if (typeof window.__bmStartTour === 'function') window.__bmStartTour();
9250
+ }, 300);
9251
+ };
9035
9252
  return html`
9036
9253
  <div>
9037
9254
  <h2 style="margin:0 0 24px;font-size:22px;font-weight:700;color:var(--text-primary);">Help & Documentation</h2>
9038
9255
 
9256
+ <div style="margin-bottom: 24px; padding: 16px; background: var(--surface-elevated);
9257
+ border: 1px solid var(--border); border-radius: 8px;
9258
+ display: flex; align-items: center; justify-content: space-between;"
9259
+ data-testid="help-tour-card">
9260
+ <div>
9261
+ <div style="font-weight: 600; color: var(--text); margin-bottom: 4px;">
9262
+ Interactive Tour
9263
+ </div>
9264
+ <div style="font-size: 13px; color: var(--text-muted);">
9265
+ Walk through the key features of BeastMode step by step.
9266
+ </div>
9267
+ </div>
9268
+ <button class="btn btn-primary" data-testid="help-start-tour" onClick=${startTour}>
9269
+ Start Tour
9270
+ </button>
9271
+ </div>
9272
+
9039
9273
  <div class="settings-section">
9040
9274
  <h3>Getting Started</h3>
9041
9275
  <div style="line-height:1.8;color:var(--text-secondary);">
@@ -10861,6 +11095,211 @@ function FactoryStatusBar() {
10861
11095
  // App Root
10862
11096
  // ================================================================
10863
11097
 
11098
+ // ================================================================
11099
+ // Onboarding Tour
11100
+ // ================================================================
11101
+
11102
+ const TOUR_STEPS = [
11103
+ {
11104
+ target: null,
11105
+ title: 'Welcome to BeastMode',
11106
+ body: "BeastMode turns your ideas into working software — describe what you want in plain language, and the pipeline writes the spec, code, and tests. Let's take a quick tour.",
11107
+ placement: 'center',
11108
+ },
11109
+ {
11110
+ target: '[data-tour="sidebar"]',
11111
+ title: 'Navigation',
11112
+ body: 'Use the sidebar to move between pages. The Board is where your tasks live. The Dashboard shows factory health and stats.',
11113
+ placement: 'right',
11114
+ },
11115
+ {
11116
+ target: '[data-tour="board-header"]',
11117
+ title: 'Your Task Board',
11118
+ body: 'Tasks flow through the pipeline from left to right: Ready → Working on it → Review → Done. BeastMode handles each stage automatically.',
11119
+ placement: 'bottom',
11120
+ },
11121
+ {
11122
+ target: '[data-tour="add-item"]',
11123
+ title: 'Create a Task',
11124
+ body: 'Click here to create a new task. Describe what you want to build — BeastMode writes the spec, plans the work, and implements it.',
11125
+ placement: 'bottom-start',
11126
+ },
11127
+ {
11128
+ target: '[data-tour="help-link"]',
11129
+ title: 'Need Help?',
11130
+ body: 'Visit the Help page anytime for guides on task types, pipeline stages, and troubleshooting tips.',
11131
+ placement: 'right',
11132
+ },
11133
+ {
11134
+ target: null,
11135
+ title: "You're Ready!",
11136
+ body: 'Start by creating your first task. BeastMode takes it from there. You can restart this tour anytime from the Help page.',
11137
+ placement: 'center',
11138
+ },
11139
+ ];
11140
+
11141
+ function OnboardingTour() {
11142
+ const [currentStep, setCurrentStep] = useState(null);
11143
+ const [targetRect, setTargetRect] = useState(null);
11144
+
11145
+ // Auto-launch on first visit.
11146
+ useEffect(() => {
11147
+ let cancelled = false;
11148
+ try {
11149
+ if (localStorage.getItem('beastmode-tour-completed')) return;
11150
+ } catch (_) { return; }
11151
+ if (!location.hash || location.hash === '#/' || location.hash === '#') {
11152
+ navigate('#/board');
11153
+ }
11154
+ const t = setTimeout(() => {
11155
+ if (!cancelled) setCurrentStep(0);
11156
+ }, 600);
11157
+ return () => { cancelled = true; clearTimeout(t); };
11158
+ }, []);
11159
+
11160
+ // Expose manual launcher globally for Dashboard checklist + Help page button.
11161
+ useEffect(() => {
11162
+ window.__bmStartTour = () => setCurrentStep(0);
11163
+ return () => { try { delete window.__bmStartTour; } catch (_) {} };
11164
+ }, []);
11165
+
11166
+ // Recalculate target rect on step change and on resize.
11167
+ useEffect(() => {
11168
+ if (currentStep === null) {
11169
+ setTargetRect(null);
11170
+ return;
11171
+ }
11172
+ const step = TOUR_STEPS[currentStep];
11173
+ function measure() {
11174
+ if (!step || !step.target) {
11175
+ setTargetRect(null);
11176
+ return;
11177
+ }
11178
+ const el = document.querySelector(step.target);
11179
+ if (!el) {
11180
+ setTargetRect(null);
11181
+ return;
11182
+ }
11183
+ const r = el.getBoundingClientRect();
11184
+ setTargetRect({ top: r.top, left: r.left, right: r.right, bottom: r.bottom, width: r.width, height: r.height });
11185
+ }
11186
+ measure();
11187
+ let timer = null;
11188
+ const onResize = () => {
11189
+ if (timer) clearTimeout(timer);
11190
+ timer = setTimeout(measure, 100);
11191
+ };
11192
+ window.addEventListener('resize', onResize);
11193
+ window.addEventListener('scroll', onResize, true);
11194
+ return () => {
11195
+ window.removeEventListener('resize', onResize);
11196
+ window.removeEventListener('scroll', onResize, true);
11197
+ if (timer) clearTimeout(timer);
11198
+ };
11199
+ }, [currentStep]);
11200
+
11201
+ const completeTour = useCallback(() => {
11202
+ try { localStorage.setItem('beastmode-tour-completed', 'true'); } catch (_) {}
11203
+ setCurrentStep(null);
11204
+ }, []);
11205
+
11206
+ // Escape to skip.
11207
+ useEffect(() => {
11208
+ if (currentStep === null) return;
11209
+ const onKey = (e) => {
11210
+ if (e.key === 'Escape') {
11211
+ e.preventDefault();
11212
+ completeTour();
11213
+ }
11214
+ };
11215
+ document.addEventListener('keydown', onKey);
11216
+ return () => document.removeEventListener('keydown', onKey);
11217
+ }, [currentStep, completeTour]);
11218
+
11219
+ if (currentStep === null) return null;
11220
+
11221
+ const step = TOUR_STEPS[currentStep];
11222
+ const isLast = currentStep === TOUR_STEPS.length - 1;
11223
+ const padding = 8;
11224
+
11225
+ // Spotlight position
11226
+ const spotlightStyle = targetRect ? {
11227
+ top: (targetRect.top - padding) + 'px',
11228
+ left: (targetRect.left - padding) + 'px',
11229
+ width: (targetRect.width + padding * 2) + 'px',
11230
+ height: (targetRect.height + padding * 2) + 'px',
11231
+ } : null;
11232
+
11233
+ // Tooltip position
11234
+ const tooltipWidth = 380;
11235
+ const tooltipApproxHeight = 220;
11236
+ const margin = 16;
11237
+ let tooltipStyle = {};
11238
+ if (!targetRect || step.placement === 'center') {
11239
+ tooltipStyle = {
11240
+ top: '50%',
11241
+ left: '50%',
11242
+ transform: 'translate(-50%, -50%)',
11243
+ };
11244
+ } else if (step.placement === 'right') {
11245
+ let top = targetRect.top + targetRect.height / 2 - tooltipApproxHeight / 2;
11246
+ let left = targetRect.right + margin;
11247
+ top = Math.max(margin, Math.min(top, window.innerHeight - tooltipApproxHeight - margin));
11248
+ left = Math.max(margin, Math.min(left, window.innerWidth - tooltipWidth - margin));
11249
+ tooltipStyle = { top: top + 'px', left: left + 'px' };
11250
+ } else if (step.placement === 'bottom') {
11251
+ let top = targetRect.bottom + margin;
11252
+ let left = targetRect.left + targetRect.width / 2 - tooltipWidth / 2;
11253
+ top = Math.max(margin, Math.min(top, window.innerHeight - tooltipApproxHeight - margin));
11254
+ left = Math.max(margin, Math.min(left, window.innerWidth - tooltipWidth - margin));
11255
+ tooltipStyle = { top: top + 'px', left: left + 'px' };
11256
+ } else if (step.placement === 'bottom-start') {
11257
+ let top = targetRect.bottom + margin;
11258
+ let left = targetRect.left;
11259
+ top = Math.max(margin, Math.min(top, window.innerHeight - tooltipApproxHeight - margin));
11260
+ left = Math.max(margin, Math.min(left, window.innerWidth - tooltipWidth - margin));
11261
+ tooltipStyle = { top: top + 'px', left: left + 'px' };
11262
+ } else {
11263
+ tooltipStyle = { top: '50%', left: '50%', transform: 'translate(-50%, -50%)' };
11264
+ }
11265
+
11266
+ const styleStr = (obj) => Object.entries(obj).map(([k, v]) => {
11267
+ const kebab = k.replace(/[A-Z]/g, m => '-' + m.toLowerCase());
11268
+ return kebab + ':' + v;
11269
+ }).join(';');
11270
+
11271
+ return html`
11272
+ <div>
11273
+ <div class="tour-backdrop" onClick=${completeTour}></div>
11274
+ ${spotlightStyle ? html`<div class="tour-spotlight" style=${styleStr(spotlightStyle)}></div>` : null}
11275
+ <div class="tour-tooltip" data-testid="tour-tooltip" style=${styleStr(tooltipStyle)} onClick=${(e) => e.stopPropagation()}>
11276
+ <div class="tour-step-indicator">
11277
+ ${TOUR_STEPS.map((_, i) => html`
11278
+ <span key=${i} class=${'tour-step-dot' + (i === currentStep ? ' active' : '')}></span>
11279
+ `)}
11280
+ </div>
11281
+ <h3>${step.title}</h3>
11282
+ <p>${step.body}</p>
11283
+ <div class="tour-actions">
11284
+ <button class="tour-skip" data-testid="tour-skip" onClick=${completeTour}>Skip Tour</button>
11285
+ <div class="tour-actions-right">
11286
+ ${currentStep > 0 && html`
11287
+ <button class="btn" data-testid="tour-back" onClick=${() => setCurrentStep(s => s - 1)}>Back</button>
11288
+ `}
11289
+ <button class="btn btn-primary" data-testid="tour-next" onClick=${() => {
11290
+ if (isLast) {
11291
+ completeTour();
11292
+ } else {
11293
+ setCurrentStep(s => s + 1);
11294
+ }
11295
+ }}>${isLast ? 'Get Started' : 'Next'}</button>
11296
+ </div>
11297
+ </div>
11298
+ </div>
11299
+ </div>
11300
+ `;
11301
+ }
11302
+
10864
11303
  function App() {
10865
11304
  const hash = useHash();
10866
11305
  const { theme, toggle: toggleTheme } = useTheme();
@@ -10942,6 +11381,7 @@ function App() {
10942
11381
  <${FactoryStatusBar} />
10943
11382
  ${page}
10944
11383
  </main>
11384
+ <${OnboardingTour} />
10945
11385
  </div>
10946
11386
  `;
10947
11387
  }
@@ -1 +1 @@
1
- 09eb71470e076891f6ed9304e081cc9372bad7fc
1
+ 5de247da4bd212025aff128ba45b5fbe9dfc535b
@@ -1 +1 @@
1
- 20260509-230834-09eb714
1
+ 20260510-004632-5de247d
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beastmode-develeap/beastmode",
3
- "version": "0.1.214",
3
+ "version": "0.1.216",
4
4
  "description": "BeastMode Dark Factory — turn intent into verified software",
5
5
  "type": "module",
6
6
  "bin": {