smarter way

This commit is contained in:
2026-05-17 20:36:18 +02:00
parent b959c6b535
commit f865315a67
2 changed files with 71 additions and 43 deletions

151
web/generator.php Normal file
View File

@@ -0,0 +1,151 @@
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
header('Content-Type: text/html; charset=UTF-8');
$startedAt = microtime(true);
$apiKey = getenv('LLAMA_API_KEY') ?: '';
$model = getenv('LLAMA_MODEL') ?: 'local-model';
$maxTokens = (int) (getenv('LLAMA_MAX_TOKENS') ?: 4096);
$reasoningEffort = getenv('LLAMA_REASONING_EFFORT') ?: 'none';
$topicHint = isset($_GET['topic']) ? trim((string) $_GET['topic']) : '';
$topicHint = mb_substr($topicHint, 0, 120);
$seed = sprintf('seed-%08x%08x', random_int(0, 0xffffffff), random_int(0, 0xffffffff));
header('HX-Redirect: /' . $seed);
$topicCategories = [
'local restaurant landing page',
'fitness coaching brand site',
'travel destination mini-guide',
'event festival one-page promo',
'indie game launch page',
'architect portfolio page',
'music artist release page',
'bookstore seasonal campaign',
'pet adoption center homepage',
'artisan coffee roaster website',
'online course product page',
'nonprofit donation campaign page',
];
$selectedCategory = $topicCategories[array_rand($topicCategories)];
$bannedTerms = [
'chrono',
'temporal',
'chrono-',
'timewarp',
'timescape',
'timeshift',
'quantum',
'aether',
'epoch',
'singularity',
];
$bannedTermsList = implode(', ', $bannedTerms);
$factory = OpenAI::factory()->withBaseUri('http://localhost:8080/v1');
if ($apiKey !== '') {
$factory = $factory->withApiKey($apiKey);
}
$client = $factory->make();
$systemPrompt = <<<PROMPT
You are a senior creative web designer and front-end engineer.
Task:
- On every run, first choose a unique page concept with a specific topic, visual theme, and style direction.
- Then generate one complete, production-ready HTML document from scratch.
Hard output rules:
- Return only raw HTML. No markdown. No code fences. No explanations.
- Output must begin with <!doctype html> and include full <html>, <head>, and <body>.
- Use Tailwind CSS via CDN in the same HTML document.
- Do not rely on local/external project files. Everything required must be inside this single HTML file.
- Inline any custom CSS and JavaScript in <style> and <script> tags.
- Make the page responsive and fully usable on mobile and desktop.
- Include accessible semantic structure and visible focus states.
Creative direction:
- Avoid generic templates.
- Use bold, intentional typography and layout.
- Include subtle but meaningful animation/interaction.
- Provide complete content, not placeholder lorem ipsum.
Diversity constraints:
- Do not make a sci-fi, futuristic, or time-themed website unless the user explicitly asks for it.
- Avoid these words in brand names, title, headings, and body copy: {$bannedTermsList}
- If no topic is provided by user, choose a grounded real-world business/topic from the requested category.
PROMPT;
$userPrompt = 'Create a complete one-page website now. Use random token: ' . $seed . '.';
if ($topicHint === '') {
$userPrompt .= ' Required category for this run: ' . $selectedCategory . '.';
}
if ($topicHint !== '') {
$userPrompt .= ' Topic request: ' . $topicHint . '.';
}
$request = [
'model' => $model,
'temperature' => 0.95,
'top_p' => 0.95,
'max_tokens' => $maxTokens,
'messages' => [
['role' => 'system', 'content' => $systemPrompt],
['role' => 'user', 'content' => $userPrompt],
],
'reasoning_effort' => $reasoningEffort,
];
try {
$response = $client->chat()->create($request);
$html = trim((string) ($response->choices[0]->message->content ?? ''));
if ($topicHint === '' && preg_match('/\b(?:chrono\w*|temporal\w*|quantum\w*|aether\w*|epoch\w*|singularity\w*|timeshift\w*|timescape\w*|timewarp\w*)\b/i', $html) === 1) {
$request['messages'][] = [
'role' => 'system',
'content' => 'Retry with a completely different, non-sci-fi, non-time-themed concept. Do not use banned words.',
];
$response = $client->chat()->create($request);
$html = trim((string) ($response->choices[0]->message->content ?? ''));
}
$elapsedSeconds = number_format(microtime(true) - $startedAt, 2);
// If the model wraps output in a markdown fence, unwrap it safely.
if (preg_match('/^```(?:html)?\s*(.*?)\s*```$/is', $html, $matches) === 1) {
$html = $matches[1];
}
if ($html === '' || stripos($html, '<html') === false) {
throw new RuntimeException('Model did not return a full HTML document.');
}
$timingBlock = '<div style="position:fixed;right:12px;bottom:12px;z-index:2147483647;background:rgba(17,24,39,.92);color:#fff;padding:8px 10px;border-radius:10px;font:12px/1.3 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;box-shadow:0 8px 20px rgba(0,0,0,.28)">Generated in ' . $elapsedSeconds . 's</div>';
if (stripos($html, '</body>') !== false) {
$html = preg_replace('/<\/body>/i', $timingBlock . '</body>', $html, 1) ?? ($html . $timingBlock);
} else {
$html .= $timingBlock;
}
//echo $html;
file_put_contents(__DIR__ . '/../pages/' . $seed . '.html', $html);
} catch (Throwable $e) {
http_response_code(500);
$message = htmlspecialchars($e->getMessage(), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
echo '<!doctype html><html><head><meta charset="UTF-8"><title>Generation Error</title>';
echo '<script src="https://cdn.tailwindcss.com"></script></head><body class="min-h-screen bg-zinc-950 text-zinc-100 p-8">';
echo '<h1 class="text-2xl font-bold mb-4">Page generation failed</h1>';
echo '<p class="text-zinc-300 mb-3">' . $message . '</p>';
echo '<p class="text-zinc-400 text-sm">Tip: set LLAMA_MODEL to a loaded model and optionally pass ?topic=your-idea in the URL.</p>';
echo '</body></html>';
}

67
web/index.php Normal file
View File

@@ -0,0 +1,67 @@
<?php
$url = array_filter(explode('/',ltrim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH),'/')));
if (count($url) === 1 && str_starts_with($url[0], 'seed-')) {
$file = __DIR__ . '/../pages/' . $url[0] . '.html';
if (file_exists($file)) {
header('Content-Type: text/html; charset=UTF-8');
echo file_get_contents($file);
exit;
}
else {
http_response_code(404);
echo 'Page not found';
exit;
}
}
?>
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Generation Error</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.10/dist/htmx.min.js"></script>
</head>
<body class="min-h-screen bg-zinc-950 text-zinc-100 p-8" hx-get="/generator.php" hx-trigger="load">
<h1 class="text-2xl font-bold mb-4">Page being generated, please wait</h1>
<p class="text-zinc-300 mb-3">
Generating content... this should complete in about 30 seconds.
</p>
<div class="w-full max-w-xl h-3 bg-zinc-800 rounded overflow-hidden mb-2" aria-label="Generation progress">
<div id="progress-bar" class="h-full bg-emerald-500 w-0 transition-[width] duration-100"></div>
</div>
<p id="progress-text" class="text-zinc-400 text-sm mb-3">0%</p>
<script>
(() => {
const durationMs = 30000;
const start = performance.now();
const bar = document.getElementById('progress-bar');
const text = document.getElementById('progress-text');
function tick(now) {
const elapsed = now - start;
const progress = Math.min(elapsed / durationMs, 1);
const percent = Math.round(progress * 100);
bar.style.width = percent + '%';
text.textContent = percent + '%';
if (progress < 1) {
requestAnimationFrame(tick);
}
}
requestAnimationFrame(tick);
})();
</script>
</body>
</html>