Add Go CDN and playground server

Build Core and Handles into in-memory CDN modules, add the marketing site and tutorial docs, and provide a SQLite-backed WebGPU playground with TypeScript tooling and profiling.

Amp-Thread-ID: https://ampcode.com/threads/T-01a02485-5574-707c-bff4-5668d83bee8a
Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
Amp
2026-08-21 16:42:02 +00:00
co-authored by heaust
parent 53a53a8f3f
commit 7070799862
27 changed files with 3402 additions and 7 deletions
+163
View File
@@ -0,0 +1,163 @@
:root {
color: #17324c;
font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-synthesis: none;
}
* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { width: 100%; height: 100%; margin: 0; overflow: hidden; }
button, input { font: inherit; }
button { color: inherit; }
.playground-app { display: grid; width: 100%; height: 100%; height: 100dvh; grid-template-rows: 58px 41px minmax(0, 1fr); background: #f7fbfe; }
.playground-header { display: flex; min-width: 0; align-items: center; gap: 14px; padding: 0 16px 0 19px; border-bottom: 1px solid #d5e3ed; background: #fff; }
.playground-brand { display: inline-flex; align-items: center; gap: 9px; color: #102d49; text-decoration: none; }
.playground-brand strong { font-size: 18px; letter-spacing: -.04em; }
.brand-mark { position: relative; display: inline-block; width: 22px; height: 22px; }
.brand-mark i { position: absolute; width: 7px; border: 2px solid #218ddd; border-radius: 7px; transform: rotate(-28deg); }
.brand-mark i:nth-child(1) { left: 1px; top: 9px; height: 10px; }
.brand-mark i:nth-child(2) { left: 7px; top: 5px; height: 14px; }
.brand-mark i:nth-child(3) { left: 14px; top: 1px; height: 18px; }
.header-divider { width: 1px; height: 22px; margin-inline: 2px; background: #d8e3eb; }
.project-name { display: flex; min-width: 0; align-items: center; gap: 7px; }
.project-name input { width: min(250px, 24vw); padding: 5px 7px; color: #29445e; border: 1px solid transparent; border-radius: 5px; outline: 0; background: transparent; font-size: 13px; font-weight: 650; text-overflow: ellipsis; }
.project-name input:hover { background: #f5f9fc; }
.project-name input:focus { border-color: #a9d8f5; background: #f7fcff; box-shadow: 0 0 0 2px rgb(50 166 232 / 10%); }
#dirty-indicator, #tab-dirty { display: none; width: 6px; height: 6px; border-radius: 50%; background: #2a9ee6; }
#dirty-indicator.visible, #tab-dirty.visible { display: inline-block; }
#revision-label { padding: 4px 7px; color: #74879a; border: 1px solid #dae5ed; border-radius: 4px; background: #f8fafc; font: 600 9px/1 ui-monospace, monospace; }
.playground-nav { display: flex; flex: 1; justify-content: flex-end; gap: 21px; }
.playground-nav a { color: #687a8c; font-size: 11px; font-weight: 600; text-decoration: none; }
.playground-nav a:hover { color: #1889d2; }
.tool-button, .run-button { display: inline-flex; height: 32px; align-items: center; justify-content: center; gap: 7px; padding: 0 12px; border-radius: 6px; cursor: pointer; font-size: 11px; font-weight: 650; }
.tool-button { color: #486177; border: 1px solid #d4e1ea; background: #fff; }
.tool-button:hover { color: #177fc2; border-color: #add5ee; background: #f6fbfe; }
.run-button { min-width: 111px; color: white; border: 1px solid #1687ce; background: #1a8fda; box-shadow: 0 4px 12px rgb(26 143 218 / 18%); }
.run-button:hover { background: #117fc5; }
.run-button:disabled, .tool-button:disabled { cursor: wait; opacity: .58; }
.run-button kbd { padding-left: 7px; color: rgb(255 255 255 / 70%); border: 0; border-left: 1px solid rgb(255 255 255 / 24%); font: 8px/1 ui-monospace, monospace; }
.playground-tools { display: flex; min-width: 0; align-items: center; gap: 14px; padding: 0 10px; border-bottom: 1px solid #cfdce6; background: #f6f9fb; }
.tool-group { display: flex; align-items: center; gap: 2px; }
.tool-group button { display: inline-flex; height: 29px; align-items: center; gap: 6px; padding: 0 9px; color: #586d80; border: 1px solid transparent; border-radius: 5px; background: transparent; cursor: pointer; font-size: 10px; }
.tool-group button:hover, .tool-group button[aria-pressed="true"] { color: #187fc2; border-color: #d3e3ed; background: #fff; }
.braces { color: #2498df; font: 700 10px/1 ui-monospace, monospace; }
.tool-context { display: flex; min-width: 0; flex: 1; align-items: center; justify-content: center; gap: 7px; color: #748698; font-size: 9px; }
.language-dot { width: 6px; height: 6px; border-radius: 2px; background: #2d9de3; }
.context-divider { width: 1px; height: 12px; margin-inline: 4px; background: #cfdae3; }
#type-status { overflow: hidden; max-width: 250px; text-overflow: ellipsis; white-space: nowrap; }
.tool-group-right { margin-left: auto; }
.workbench { --editor-width: 50%; display: grid; min-width: 0; min-height: 0; grid-template-columns: minmax(330px, var(--editor-width)) 5px minmax(330px, 1fr); background: #0b1725; }
.editor-pane, .stage-pane { min-width: 0; min-height: 0; }
.editor-pane { display: grid; grid-template-rows: 37px minmax(0, 1fr) 24px; }
.pane-tabs, .stage-toolbar { display: flex; min-width: 0; align-items: stretch; border-bottom: 1px solid #1d3245; background: #112233; }
.pane-tab { display: flex; min-width: 145px; align-items: center; gap: 7px; padding: 0 14px; color: #9db1c2; border: 0; border-right: 1px solid #22384b; background: #0d1d2d; font-size: 10px; }
.pane-tab.active { color: #d4e2ed; border-top: 2px solid #2ba5ea; background: #0b1927; }
.ts-icon { display: grid; width: 18px; height: 16px; place-items: center; color: #fff; border-radius: 2px; background: #278dcd; font: 700 7px/1 ui-monospace, monospace; }
.editor { position: relative; min-height: 0; overflow: hidden; background: #0b1927; }
.editor-loading { display: grid; height: 100%; place-items: center; color: #668097; font: 10px/1 ui-monospace, monospace; }
.monaco-editor .margin { background-color: #0b1927 !important; }
.editor-status { display: flex; align-items: center; gap: 14px; padding: 0 10px; color: #6f8599; border-top: 1px solid #1b3042; background: #0c1d2c; font: 8px/1 ui-monospace, monospace; }
.status-spacer { flex: 1; }
#editor-diagnostics { display: flex; align-items: center; gap: 5px; }
#editor-diagnostics i { width: 5px; height: 5px; border-radius: 50%; background: #4aa975; }
#editor-diagnostics.has-errors { color: #e8a4a4; }
#editor-diagnostics.has-errors i { background: #e26f6f; }
.resize-handle { position: relative; z-index: 3; cursor: col-resize; background: #172a3b; }
.resize-handle::after { position: absolute; top: 50%; left: 1px; width: 3px; height: 40px; transform: translateY(-50%); border-radius: 3px; background: #355067; content: ""; opacity: .65; }
.resize-handle:hover, .resize-handle.dragging { background: #218ed2; }
.stage-pane { display: grid; grid-template-rows: 37px minmax(230px, 1fr) 190px; background: #091521; }
.stage-toolbar { justify-content: space-between; }
.stage-tabs button { height: 100%; padding: 0 14px; color: #8da3b6; border: 0; border-top: 2px solid transparent; background: transparent; font-size: 10px; }
.stage-tabs button.active { color: #d4e3ee; border-top-color: #35a9ed; background: #0d1d2c; }
.stage-meta { display: flex; min-width: 0; align-items: center; gap: 10px; padding-right: 12px; color: #6e869a; font: 8px/1 ui-monospace, monospace; }
#run-status { display: flex; align-items: center; gap: 6px; }
#run-status i { width: 6px; height: 6px; border-radius: 50%; background: #4cad79; box-shadow: 0 0 0 3px rgb(76 173 121 / 10%); }
#run-status.running i { background: #36a8e8; animation: status-pulse 1s infinite; }
#run-status.failed { color: #e49a9a; }
#run-status.failed i { background: #e36d6d; }
.stage-divider { width: 1px; height: 12px; background: #294052; }
.preview { position: relative; min-width: 0; min-height: 0; overflow: hidden; background: radial-gradient(circle at 50% 45%, #102b43, #06111d 72%); }
.preview::before { position: absolute; inset: 0; background-image: linear-gradient(rgb(82 143 182 / 5%) 1px, transparent 1px), linear-gradient(90deg, rgb(82 143 182 / 5%) 1px, transparent 1px); background-size: 32px 32px; content: ""; pointer-events: none; }
.preview canvas { position: relative; display: block; width: 100%; height: 100%; object-fit: contain; touch-action: none; }
.preview-message { position: absolute; top: 50%; left: 50%; display: grid; justify-items: center; gap: 7px; transform: translate(-50%, -50%); color: #93aabd; text-align: center; pointer-events: none; }
.preview-message[hidden] { display: none; }
.preview-message-icon { display: grid; width: 43px; height: 43px; margin-bottom: 7px; place-items: center; color: #54bdf6; border: 1px solid #25577a; border-radius: 12px; background: #0b2941; box-shadow: 0 0 30px rgb(46 171 238 / 12%); font-size: 16px; font-weight: 800; }
.preview-message strong { color: #b9cddd; font-size: 11px; }
.preview-message small { color: #627a8f; font-size: 9px; }
.inspector { min-height: 0; border-top: 1px solid #22384b; background: #0a1825; }
.inspector.collapsed { display: none; }
.stage-pane:has(.inspector.collapsed) { grid-template-rows: 37px minmax(230px, 1fr) 0; }
.inspector-tabs { display: flex; height: 31px; align-items: stretch; border-bottom: 1px solid #1c3041; background: #0e1e2c; }
.inspector-tabs button { padding: 0 13px; color: #71889b; border: 0; border-bottom: 1px solid transparent; background: transparent; cursor: pointer; font-size: 9px; }
.inspector-tabs button.active { color: #c0d2df; border-bottom-color: #32a8eb; }
.inspector-tabs button span { margin-left: 4px; padding: 1px 5px; border-radius: 5px; background: #1a3245; font-size: 7px; }
.inspector-tabs .clear-console { margin-left: auto; color: #61788b; }
.inspector-panel { display: none; height: calc(100% - 31px); overflow: auto; }
.inspector-panel.active { display: block; }
.console-empty, .profile-empty { display: flex; height: 100%; align-items: center; justify-content: center; gap: 10px; color: #718a9f; font: 9px/1 ui-monospace, monospace; }
.console-empty > span { color: #318fc7; font-size: 12px; }
.console-empty code { color: #90aabd; }
#console-lines { margin: 0; padding: 5px 0; color: #9cb1c1; list-style: none; font: 9px/1.6 ui-monospace, monospace; }
#console-lines li { display: flex; min-height: 22px; align-items: flex-start; gap: 9px; padding: 3px 10px; border-bottom: 1px solid rgb(36 57 73 / 45%); white-space: pre-wrap; word-break: break-word; }
#console-lines li::before { color: #399ed9; content: ""; }
#console-lines li.error { color: #e19a9a; }
#console-lines li.error::before { color: #dd6b6b; content: "×"; }
.profile-empty { font-family: inherit; }
.profile-empty .pulse-icon { display: grid; width: 30px; height: 30px; place-items: center; color: #48ace4; border: 1px solid #24516f; border-radius: 50%; background: #0e2940; }
.profile-empty > div { display: grid; gap: 4px; }
.profile-empty strong { color: #91a9ba; font-size: 10px; }
.profile-empty small { color: #526b7e; font-size: 8px; }
.profile-results { padding: 10px 12px; color: #8fa6b8; }
.profile-summary { display: grid; grid-template-columns: .7fr .8fr 1.5fr; gap: 8px; margin-bottom: 9px; }
.profile-summary > div { display: grid; gap: 3px; padding: 7px 9px; border: 1px solid #1e384b; border-radius: 5px; background: #0e2130; }
.profile-summary small { color: #587185; font-size: 7px; text-transform: uppercase; }
.profile-summary strong { overflow: hidden; color: #9fc7de; font: 8px/1.3 ui-monospace, monospace; text-overflow: ellipsis; white-space: nowrap; }
.profile-results table { width: 100%; border-collapse: collapse; font: 8px/1.4 ui-monospace, monospace; }
.profile-results th, .profile-results td { padding: 5px 7px; border-bottom: 1px solid #1b3041; text-align: left; }
.profile-results th { color: #506b80; font-weight: 600; }
.profile-results td:last-child, .profile-results th:last-child { color: #56b4e8; text-align: right; }
.snippets-dialog { width: min(580px, calc(100% - 30px)); padding: 0; color: #18354f; border: 1px solid #cadce8; border-radius: 14px; background: #fff; box-shadow: 0 30px 90px rgb(5 25 42 / 28%); }
.snippets-dialog::backdrop { background: rgb(6 23 38 / 48%); backdrop-filter: blur(3px); }
.dialog-heading { display: flex; align-items: flex-start; justify-content: space-between; padding: 25px 26px 17px; }
.dialog-heading span { color: #1b8ed8; font-size: 8px; font-weight: 800; letter-spacing: .13em; text-transform: uppercase; }
.dialog-heading h2 { margin: 5px 0 3px; font-size: 23px; letter-spacing: -.04em; }
.dialog-heading p { margin: 0; color: #798b9c; font-size: 10px; }
.dialog-heading > button { color: #7c8fa0; border: 0; background: transparent; cursor: pointer; font-size: 22px; }
.snippet-search { display: flex; height: 35px; align-items: center; gap: 8px; margin: 0 26px 14px; padding: 0 10px; color: #8a9aaa; border: 1px solid #d8e5ed; border-radius: 7px; background: #f9fbfd; }
.snippet-search input { min-width: 0; flex: 1; border: 0; outline: 0; background: transparent; font-size: 10px; }
.snippet-grid { display: grid; gap: 1px; padding: 0 16px 18px; }
.snippet-grid > button { display: grid; min-height: 66px; grid-template-columns: 40px 1fr auto; align-items: center; gap: 12px; padding: 8px 10px; text-align: left; border: 1px solid transparent; border-radius: 8px; background: transparent; cursor: pointer; }
.snippet-grid > button:hover { border-color: #cee5f4; background: #f3faff; }
.snippet-icon { display: grid; width: 36px; height: 36px; place-items: center; color: #168bd3; border: 1px solid #c6e4f6; border-radius: 9px; background: #edf9ff; font-size: 14px; }
.snippet-grid button > div { display: grid; grid-template-columns: auto 1fr; align-items: baseline; gap: 3px 8px; }
.snippet-grid strong { color: #294861; font-size: 11px; }
.snippet-grid small { grid-column: 1; color: #7b8e9f; font-size: 9px; }
.snippet-grid code { grid-column: 2; grid-row: 1 / 3; justify-self: end; padding: 4px 6px; color: #3b82ac; border: 1px solid #d8e8f1; border-radius: 4px; background: #f9fcfe; font: 8px/1 ui-monospace, monospace; }
.snippet-grid b { color: #329cdc; font-size: 16px; }
.toast { position: fixed; z-index: 100; right: 18px; bottom: 18px; max-width: 360px; padding: 11px 15px; transform: translateY(20px); color: #d8e9f4; border: 1px solid #2d5875; border-radius: 7px; background: #102d42; box-shadow: 0 12px 35px rgb(2 17 29 / 24%); font-size: 10px; opacity: 0; pointer-events: none; transition: opacity 180ms ease, transform 180ms ease; }
.toast.visible { transform: none; opacity: 1; }
@keyframes status-pulse { 50% { opacity: .35; } }
@media (max-width: 800px) {
.playground-header { gap: 8px; padding-inline: 10px; }
.header-divider, .playground-nav, #share-button, .project-name #revision-label { display: none; }
.project-name { min-width: 0; flex: 1; }
.project-name input { width: 100%; }
.tool-button { padding-inline: 8px; }
.run-button { min-width: auto; }
.run-button kbd { display: none; }
.tool-context { display: none; }
.tool-group-right { margin-left: auto; }
.workbench { display: grid; overflow: auto; grid-template-columns: 1fr; grid-template-rows: minmax(400px, 55vh) minmax(450px, 1fr); }
.resize-handle { display: none; }
.stage-pane { min-height: 500px; }
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; animation-iteration-count: 1 !important; }
}