HEX
Server: LiteSpeed
System: Linux houston.panomity.com 6.8.0-100-generic #100-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan 13 16:40:06 UTC 2026 x86_64
User: nudepix (1011)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //tmp/home-activation-strip.cjs
const fs = require('fs');
const file = 'web/src/modules/home/HomePage.jsx';
let body = fs.readFileSync(file, 'utf8');
const marker = "const challengeCards = [";
const component = String.raw`
const ActivationQuickstart = ({ stats }) => {
  const votes7d = Number(stats?.recent7d?.votes || 0);
  const photos = Number(stats?.totals?.activePhotos || 0);
  const trackQuickstart = (target, meta = {}) => {
    trackEvent('home_activation_strip_click', {
      source: 'home',
      surface: 'activation_quickstart',
      entryPoint: target,
      meta: {
        votes7d: String(votes7d),
        activePhotos: String(photos),
        ...meta
      }
    }, { transport: 'beacon' });
  };

  return (
    <section className="mt-5 overflow-hidden rounded-2xl border border-emerald-200 bg-gradient-to-br from-emerald-50 via-white to-coral-50 shadow-sm" data-growth-marker="home-activation-quickstart">
      <div className="grid gap-0 lg:grid-cols-[0.86fr_1.14fr]">
        <div className="p-4 sm:p-5 lg:p-6">
          <span className="inline-flex rounded-full bg-emerald-100 px-3 py-1 text-xs font-black uppercase tracking-[0.16em] text-emerald-800">Schnellster Start</span>
          <h2 className="mt-3 text-2xl font-black leading-tight text-slate-950">Bewerte 3 Fotos, dann teste dein eigenes</h2>
          <p className="mt-2 text-sm leading-6 text-slate-700">So verstehst du sofort, welche Stimmen du später bekommst. Danach öffnest du deine Galerie bewusst statt unsicher abzubrechen.</p>
          <div className="mt-4 flex flex-col gap-2 sm:flex-row">
            <Link
              to="/rate/random?cat=all&entry=home_activation_quickstart"
              className="btn min-h-12 border-0 bg-emerald-600 text-white hover:bg-emerald-700"
              onClick={() => trackQuickstart('rate_random', { step: 'rate_first' })}
            >
              Jetzt 3 Fotos bewerten
            </Link>
            <Link
              to={buildUploadPath('home_activation_after_vote')}
              className="btn min-h-12 border-coral-200 bg-white text-coral-700 hover:bg-coral-50"
              onClick={() => trackQuickstart('upload_after_vote', { step: 'upload_after_rate' })}
            >
              Danach eigenes Foto testen
            </Link>
          </div>
        </div>
        <div className="grid gap-2 bg-white/70 p-4 sm:grid-cols-3 sm:p-5 lg:p-6">
          {[
            ['1', 'Foto ansehen', 'Nur die Wirkung bewerten, kein Kommentarzwang.'],
            ['2', '3 Stimmen geben', 'Du hilfst echten Menschen beim Auswählen.'],
            ['3', 'Eigenes Foto wählen', 'Galerie bleibt privat bis zur Vorschau.']
          ].map(([step, title, text]) => (
            <div key={step} className="rounded-xl border border-slate-200 bg-white p-4 shadow-sm">
              <div className="flex h-9 w-9 items-center justify-center rounded-full bg-slate-950 text-sm font-black text-white">{step}</div>
              <p className="mt-3 font-black text-slate-950">{title}</p>
              <p className="mt-1 text-xs leading-5 text-slate-600">{text}</p>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
};

`;
if (!body.includes('const ActivationQuickstart')) {
  if (!body.includes(marker)) throw new Error('challengeCards marker not found');
  body = body.replace(marker, component + marker);
}
body = body.replace(
"      <Hero items={profileItems} online={online} stats={communityStats} />\n      <CommunityStats stats={communityStats} />\n      <VoteChallenge stats={communityStats} />",
"      <Hero items={profileItems} online={online} stats={communityStats} />\n      <CommunityStats stats={communityStats} />\n      <ActivationQuickstart stats={communityStats} />\n      <VoteChallenge stats={communityStats} />"
);
fs.writeFileSync(file, body);

const smokeFile = 'scripts/growth-smoke-check.mjs';
let smoke = fs.readFileSync(smokeFile, 'utf8');
const insertionPoint = "  const uploadChunk = files.find((asset) => /^UploadPage-.*\\.js$/.test(asset));";
const homeCheck = [
"  const homeChunk = files.find((asset) => /^index-.*\\.js$/.test(asset));",
"  if (!homeChunk) {",
"    failures.push('public_html/assets: missing index home chunk');",
"  } else {",
"    const homeBody = await fs.readFile(path.join(assetsDir, homeChunk), 'utf8');",
"    for (const needle of ['home-activation-quickstart', 'home_activation_strip_click', 'Jetzt 3 Fotos bewerten', 'Danach eigenes Foto testen']) {",
"      if (!homeBody.includes(needle)) failures.push(`${homeChunk}: missing ${needle}`);",
"    }",
"    console.log(`OK home-chunk ${homeChunk}`);",
"  }",
""
].join('\n');
if (!smoke.includes('home-activation-quickstart')) {
  if (!smoke.includes(insertionPoint)) throw new Error('smoke insertion point not found');
  smoke = smoke.replace(insertionPoint, homeCheck + insertionPoint);
}
fs.writeFileSync(smokeFile, smoke);