@@ -80,7 +80,10 @@ func main() {
8080}
8181
8282func generate404 () error {
83- return os .WriteFile ("site/404.html" , []byte (notFoundTemplate ), 0644 )
83+ return os .WriteFile ("site/404.html" , []byte (`<!DOCTYPE html>
84+ <html><head><meta charset="utf-8"><meta http-equiv="refresh" content="0;url=/"><title>Redirecting…</title></head>
85+ <body><p>Redirecting to <a href="/">homepage</a>…</p></body></html>
86+ ` ), 0644 )
8487}
8588
8689func generateSitemap (cfg Config ) error {
@@ -593,8 +596,8 @@ a:focus-visible { outline: 2px solid var(--accent-light); outline-offset: 2px; b
593596 return;
594597 }
595598
596- // Redirect to the docs page — 404.html shows loading until docs are ready
597- window.location.href = data.docs_url ;
599+ // Redirect to the skeleton loading page — served by the worker
600+ window.location.href = data.generating_url ;
598601 } catch (e) {
599602 showFeedback('Network error. Please try again.', 'error');
600603 submitBtn.classList.remove('loading');
@@ -621,304 +624,3 @@ a:focus-visible { outline: 2px solid var(--accent-light); outline-offset: 2px; b
621624</html>
622625`
623626
624- const notFoundTemplate = `<!DOCTYPE html>
625- <html lang="en">
626- <head>
627- <meta charset="utf-8">
628- <meta name="viewport" content="width=device-width, initial-scale=1">
629- <title>Generating — Supermodel Architecture Docs</title>
630- <link rel="preconnect" href="https://fonts.googleapis.com">
631- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
632- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
633- <style>
634- :root {
635- --bg: #0f1117;
636- --bg-card: #1a1d27;
637- --border: #2a2e3e;
638- --text: #e4e4e7;
639- --text-muted: #9ca3af;
640- --accent: #6366f1;
641- --accent-light: #818cf8;
642- --font: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
643- --mono: 'JetBrains Mono', 'Fira Code', monospace;
644- }
645- * { margin: 0; padding: 0; box-sizing: border-box; }
646- body {
647- font-family: var(--font);
648- background: var(--bg);
649- color: var(--text);
650- min-height: 100vh;
651- display: flex;
652- flex-direction: column;
653- align-items: center;
654- justify-content: center;
655- -webkit-font-smoothing: antialiased;
656- }
657- a { color: var(--accent-light); text-decoration: none; }
658- a:hover { text-decoration: underline; }
659-
660- .loading-container {
661- text-align: center;
662- max-width: 480px;
663- padding: 24px;
664- }
665-
666- /* Eye logo animation */
667- .eye-wrap {
668- width: 120px;
669- height: 104px;
670- margin: 0 auto 32px;
671- position: relative;
672- }
673- .eye-wrap svg {
674- width: 120px;
675- height: 104px;
676- color: var(--accent-light);
677- }
678- .eye-wrap svg path {
679- animation: eyePulse 2.4s ease-in-out infinite;
680- }
681- @keyframes eyePulse {
682- 0%, 100% { opacity: 0.4; }
683- 50% { opacity: 1; }
684- }
685-
686- /* Scanning line */
687- .scan-line {
688- position: absolute;
689- top: 0;
690- left: 10%;
691- width: 80%;
692- height: 2px;
693- background: linear-gradient(90deg, transparent, var(--accent-light), transparent);
694- animation: scan 2.4s ease-in-out infinite;
695- border-radius: 1px;
696- }
697- @keyframes scan {
698- 0% { top: 15%; opacity: 0; }
699- 10% { opacity: 1; }
700- 90% { opacity: 1; }
701- 100% { top: 85%; opacity: 0; }
702- }
703-
704- .loading-title {
705- font-size: 22px;
706- font-weight: 700;
707- margin-bottom: 8px;
708- }
709- .loading-repo {
710- font-family: var(--mono);
711- font-size: 16px;
712- color: var(--accent-light);
713- margin-bottom: 24px;
714- }
715-
716- /* Progress steps */
717- .steps {
718- text-align: left;
719- margin: 0 auto;
720- display: inline-block;
721- }
722- .step {
723- display: flex;
724- align-items: center;
725- gap: 10px;
726- padding: 6px 0;
727- font-size: 14px;
728- color: var(--text-muted);
729- transition: color 0.3s;
730- }
731- .step.active { color: var(--text); }
732- .step.done { color: var(--accent-light); }
733- .step-icon {
734- width: 20px;
735- height: 20px;
736- flex-shrink: 0;
737- display: flex;
738- align-items: center;
739- justify-content: center;
740- }
741- .step-spinner {
742- width: 16px;
743- height: 16px;
744- border: 2px solid var(--border);
745- border-top-color: var(--accent-light);
746- border-radius: 50%;
747- animation: spin 0.8s linear infinite;
748- }
749- @keyframes spin {
750- to { transform: rotate(360deg); }
751- }
752- .step-check { color: var(--accent-light); }
753- .step-dot {
754- width: 8px;
755- height: 8px;
756- border-radius: 50%;
757- background: var(--border);
758- }
759-
760- .loading-hint {
761- margin-top: 32px;
762- font-size: 13px;
763- color: var(--text-muted);
764- }
765-
766- /* 404 state (not a repo path) */
767- .not-found {
768- text-align: center;
769- max-width: 480px;
770- padding: 24px;
771- }
772- .not-found h1 {
773- font-size: 72px;
774- font-weight: 700;
775- color: var(--border);
776- line-height: 1;
777- margin-bottom: 16px;
778- }
779- .not-found p {
780- color: var(--text-muted);
781- font-size: 16px;
782- margin-bottom: 24px;
783- }
784-
785- .hidden { display: none; }
786-
787- @media (max-width: 768px) {
788- .loading-title { font-size: 18px; }
789- .loading-repo { font-size: 14px; }
790- }
791- </style>
792- </head>
793- <body>
794- <!-- Loading state (repo generation in progress) -->
795- <div class="loading-container hidden" id="loading">
796- <div class="eye-wrap">
797- <svg viewBox="0 0 90 78" fill="none" xmlns="http://www.w3.org/2000/svg">
798- <path d="M90 61.1124C75.9375 73.4694 59.8419 78 44.7554 78C29.669 78 11.8614 72.6122 0 61.1011V16.9458C11.6168 6 29.891 0 44.9887 0C62.77 0 78.8723 6.97959 89.9887 16.9458V61.1124H90ZM88.1881 38.9553C77.7923 22.8824 59.8983 15.7959 44.7554 15.7959C29.6126 15.7959 13.4515 21.9008 1.556 38.9444C12.5382 54.69 26.9 62.5085 44.7554 62.0944C67.6297 61.5639 77.6495 51.9184 88.1881 38.9553ZM44.7554 16.3475C32.4756 16.3475 22.3888 26.6879 22.2554 38.9388C34.3765 38.9162 44.7554 29.1429 44.7554 16.3475C44.7554 29.1429 55.1344 38.9162 67.2554 38.9388C67.1202 26.5216 57.1141 16.3475 44.7554 16.3475ZM44.7554 61.5639C44.7554 48.4898 34.3765 38.9613 22.2554 38.9388C22.3888 51.1897 32.4756 61.5639 44.7554 61.5639C57.0352 61.5639 67.122 51.1897 67.2554 38.9388C55.1344 38.9613 44.7554 48.4898 44.7554 61.5639Z" fill="currentColor"/>
799- </svg>
800- <div class="scan-line"></div>
801- </div>
802- <div class="loading-title">Generating Architecture Docs</div>
803- <div class="loading-repo" id="loading-repo"></div>
804- <div class="steps" id="steps">
805- <div class="step" data-step="fork">
806- <div class="step-icon"><div class="step-dot"></div></div>
807- <span>Forking repository</span>
808- </div>
809- <div class="step" data-step="analyze">
810- <div class="step-icon"><div class="step-dot"></div></div>
811- <span>Analyzing codebase</span>
812- </div>
813- <div class="step" data-step="graph">
814- <div class="step-icon"><div class="step-dot"></div></div>
815- <span>Building code graphs</span>
816- </div>
817- <div class="step" data-step="deploy">
818- <div class="step-icon"><div class="step-dot"></div></div>
819- <span>Deploying documentation</span>
820- </div>
821- </div>
822- <div class="loading-hint">This usually takes 2–5 minutes. The page will refresh automatically.</div>
823- </div>
824-
825- <!-- Genuine 404 state -->
826- <div class="not-found hidden" id="not-found">
827- <h1>404</h1>
828- <p>This page doesn't exist.</p>
829- <a href="/">Browse all repositories →</a>
830- </div>
831-
832- <script>
833- (function() {
834- var path = window.location.pathname.replace(/\/+$/, '').replace(/^\/+/, '');
835- var segments = path.split('/').filter(Boolean);
836-
837- // If the path looks like a repo name (single segment, no dots suggesting a file),
838- // show the loading page. Otherwise show genuine 404.
839- var isRepoPath = segments.length >= 1 && !segments[0].includes('.');
840- var repoName = segments[0] || '';
841-
842- if (isRepoPath && repoName) {
843- document.getElementById('loading').classList.remove('hidden');
844- document.getElementById('loading-repo').textContent = repoName;
845- document.title = 'Generating ' + repoName + ' — Supermodel Architecture Docs';
846-
847- // Animate steps over time to show progress
848- var steps = document.querySelectorAll('.step');
849- var stepTimings = [0, 8000, 30000, 60000]; // approximate real timings
850-
851- function activateStep(index) {
852- steps.forEach(function(s, i) {
853- var icon = s.querySelector('.step-icon');
854- if (i < index) {
855- s.classList.add('done');
856- s.classList.remove('active');
857- icon.innerHTML = '<svg class="step-check" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6L9 17l-5-5"/></svg>';
858- } else if (i === index) {
859- s.classList.add('active');
860- s.classList.remove('done');
861- icon.innerHTML = '<div class="step-spinner"></div>';
862- } else {
863- s.classList.remove('active', 'done');
864- icon.innerHTML = '<div class="step-dot"></div>';
865- }
866- });
867- }
868-
869- // Start first step immediately
870- activateStep(0);
871- var currentStep = 0;
872-
873- // Advance steps on a timer
874- function advanceStep() {
875- if (currentStep < steps.length - 1) {
876- currentStep++;
877- activateStep(currentStep);
878- }
879- }
880- setTimeout(advanceStep, 8000); // ~8s: fork done, analyzing
881- setTimeout(advanceStep, 35000); // ~35s: graphs building
882- setTimeout(advanceStep, 70000); // ~70s: deploying
883-
884- // Poll for the real docs page
885- var pollInterval = 5000;
886- var maxPolls = 120; // 10 minutes max
887- var pollCount = 0;
888-
889- function pollForDocs() {
890- pollCount++;
891- if (pollCount > maxPolls) return;
892-
893- fetch(window.location.href, { cache: 'no-store', redirect: 'follow' })
894- .then(function(resp) {
895- if (resp.ok) {
896- return resp.text().then(function(html) {
897- // Make sure it's the real docs page, not this 404 page
898- if (html.indexOf('arch-docs') !== -1 && html.indexOf('loading-container') === -1) {
899- // Docs are ready — mark all steps done then reload
900- activateStep(steps.length);
901- setTimeout(function() { window.location.reload(); }, 800);
902- return;
903- }
904- setTimeout(pollForDocs, pollInterval);
905- });
906- } else {
907- setTimeout(pollForDocs, pollInterval);
908- }
909- })
910- .catch(function() {
911- setTimeout(pollForDocs, pollInterval);
912- });
913- }
914-
915- setTimeout(pollForDocs, pollInterval);
916- } else {
917- document.getElementById('not-found').classList.remove('hidden');
918- document.title = '404 — Supermodel Architecture Docs';
919- }
920- })();
921- </script>
922- </body>
923- </html>
924- `
0 commit comments