CoolFace
Apppublic

simata/huggingmes

sourceHugging Facemitupdated 4mo agoView on Hugging Face
1likes
env-builder.html854 linesDownload Raw Back to root
1<!DOCTYPE html>2<html lang="en">3<head>4<meta charset="UTF-8">5<meta name="viewport" content="width=device-width, initial-scale=1.0">6<title>HuggingMes · ENV Builder</title>7<link rel="preconnect" href="https://fonts.googleapis.com">8<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>9<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=Syne:wght@400;500;600;700;800&display=swap" rel="stylesheet">10 11<style>12*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }13 14:root {15  --bg:        #0b0c0f;16  --bg2:       #111318;17  --bg3:       #181c23;18  --bg4:       #1e2330;19  --border:    #252b38;20  --border2:   #2e3648;21  --amber:     #f5a623;22  --amber2:    #ffbe55;23  --amber-dim: rgba(245,166,35,.12);24  --amber-glow:rgba(245,166,35,.22);25  --green:     #3dd68c;26  --red:       #f05f5f;27  --blue:      #5b8af5;28  --text:      #e4e8f0;29  --text2:     #8d97ad;30  --text3:     #535f76;31  --mono:      'JetBrains Mono', monospace;32  --sans:      'Syne', sans-serif;33  --r:         8px;34  --r2:        12px;35  --sidebar-w: 220px;36  --panel-w:   340px;37}38 39html { scroll-behavior: smooth; height: 100%; }40 41body {42  font-family: var(--sans);43  background: var(--bg);44  color: var(--text);45  height: 100vh;46  overflow: hidden;47  display: flex;48  flex-direction: column;49}50 51.topbar {52  position: sticky;53  top: 0;54  z-index: 100;55  height: 52px;56  background: rgba(11,12,15,.9);57  backdrop-filter: blur(14px);58  border-bottom: 1px solid var(--border);59  display: flex;60  align-items: center;61  padding: 0 20px;62  gap: 16px;63  flex-shrink: 0;64}65 66.topbar-logo {67  display: flex;68  align-items: center;69  gap: 10px;70  flex-shrink: 0;71}72 73.topbar-logo .logo-emoji { font-size: 24px; line-height: 1; }74 75.topbar-wordmark {76  font-weight: 800;77  font-size: 14px;78  letter-spacing: -.2px;79  color: var(--text);80  white-space: nowrap;81}82 83.topbar-wordmark em {84  color: var(--amber);85  font-style: normal;86}87 88.topbar-divider {89  width: 1px;90  height: 22px;91  background: var(--border2);92}93 94.topbar-title {95  font-size: 12px;96  font-weight: 600;97  color: var(--text2);98  letter-spacing: .5px;99  text-transform: uppercase;100}101 102.topbar-spacer { flex: 1; }103 104.topbar-pill {105  font-family: var(--mono);106  font-size: 10px;107  color: var(--amber);108  background: var(--amber-dim);109  border: 1px solid var(--amber-glow);110  border-radius: 20px;111  padding: 3px 10px;112  letter-spacing: .5px;113}114 115.layout {116  display: flex;117  flex: 1;118  min-height: 0;119  height: calc(100vh - 52px);120}121 122.sidebar-wrap {123  width: var(--sidebar-w);124  flex-shrink: 0;125  border-right: 1px solid var(--border);126  background: var(--bg2);127  display: flex;128  flex-direction: column;129  overflow: hidden;130}131 132.sidebar-scroll {133  flex: 1;134  overflow-y: auto;135  padding: 14px 10px;136}137 138.sidebar-scroll::-webkit-scrollbar { width: 4px; }139.sidebar-scroll::-webkit-scrollbar-track { background: transparent; }140.sidebar-scroll::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 4px; }141 142.sb-label {143  font-size: 9px;144  font-weight: 700;145  text-transform: uppercase;146  letter-spacing: 1.2px;147  color: var(--text3);148  padding: 0 8px 10px;149}150 151.nav-btn {152  width: 100%;153  display: flex;154  align-items: center;155  gap: 8px;156  padding: 8px 10px;157  border: none;158  background: transparent;159  cursor: pointer;160  border-radius: var(--r);161  text-align: left;162  color: var(--text2);163  font-family: var(--sans);164  font-size: 12.5px;165  font-weight: 500;166  transition: background .15s, color .15s;167  margin-bottom: 2px;168}169 170.nav-btn:hover { background: var(--bg3); color: var(--text); }171.nav-btn.active {172  background: var(--amber-dim);173  color: var(--amber);174  border: 1px solid var(--amber-glow);175}176 177.nav-icon { font-size: 13px; flex-shrink: 0; }178.nav-label { flex: 1; }179.nav-count {180  font-family: var(--mono);181  font-size: 10px;182  font-weight: 600;183  color: var(--text3);184  background: var(--bg3);185  border-radius: 10px;186  padding: 1px 6px;187  min-width: 20px;188  text-align: center;189  transition: background .2s, color .2s;190}191.nav-btn.active .nav-count {192  background: var(--amber-glow);193  color: var(--amber2);194}195 196.main {197  flex: 1;198  display: flex;199  flex-direction: column;200  min-width: 0;201  overflow: hidden;202}203 204.toolbar {205  display: flex;206  align-items: center;207  gap: 10px;208  padding: 12px 20px;209  border-bottom: 1px solid var(--border);210  background: var(--bg2);211  flex-shrink: 0;212  flex-wrap: wrap;213}214 215.search-wrap {216  position: relative;217  flex: 1;218  min-width: 160px;219  max-width: 340px;220}221 222.search-icon {223  position: absolute;224  left: 10px;225  top: 50%;226  transform: translateY(-50%);227  color: var(--text3);228  pointer-events: none;229  font-size: 12px;230}231 232#search {233  width: 100%;234  background: var(--bg3);235  border: 1px solid var(--border2);236  border-radius: var(--r);237  padding: 7px 10px 7px 30px;238  font-family: var(--mono);239  font-size: 12px;240  color: var(--text);241  outline: none;242  transition: border-color .15s;243}244 245#search:focus { border-color: var(--amber); }246#search::placeholder { color: var(--text3); }247 248.tb-sep {249  width: 1px;250  height: 24px;251  background: var(--border2);252}253 254.btn {255  display: inline-flex;256  align-items: center;257  gap: 5px;258  padding: 6px 13px;259  border-radius: var(--r);260  border: 1px solid var(--border2);261  background: var(--bg3);262  color: var(--text2);263  font-family: var(--sans);264  font-size: 11.5px;265  font-weight: 600;266  cursor: pointer;267  transition: all .15s;268  white-space: nowrap;269}270 271.btn:hover { background: var(--bg4); color: var(--text); border-color: var(--border2); }272 273.btn-amber {274  background: var(--amber);275  color: #0b0c0f;276  border-color: var(--amber);277}278.btn-amber:hover { background: var(--amber2); border-color: var(--amber2); }279 280.btn-ghost {281  background: transparent;282  border-color: transparent;283  color: var(--text3);284}285.btn-ghost:hover { background: var(--bg3); color: var(--text2); border-color: var(--border2); }286 287.content-wrap {288  flex: 1;289  display: flex;290  min-height: 0;291  overflow: hidden;292}293 294.sections-scroll {295  flex: 1;296  overflow-y: auto;297  padding: 16px 20px 80px;298  min-width: 0;299}300 301.sections-scroll::-webkit-scrollbar { width: 5px; }302.sections-scroll::-webkit-scrollbar-track { background: transparent; }303.sections-scroll::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 4px; }304 305.sec { margin-bottom: 28px; }306.sec.sec-hidden { display: none !important; }307 308.sec-header {309  display: flex;310  align-items: center;311  gap: 8px;312  margin-bottom: 12px;313}314 315.sec-icon { font-size: 14px; }316.sec-title {317  font-size: 11px;318  font-weight: 700;319  text-transform: uppercase;320  letter-spacing: 1.2px;321  color: var(--text3);322}323 324.sec-line {325  flex: 1;326  height: 1px;327  background: var(--border);328}329 330.cards {331  display: grid;332  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));333  gap: 10px;334}335 336.env-card {337  background: var(--bg2);338  border: 1px solid var(--border);339  border-radius: var(--r2);340  padding: 12px;341  transition: border-color .2s, background .2s;342}343 344.env-card:hover { border-color: var(--border2); }345.env-card.hidden { display: none; }346 347.env-card.selected {348  border-color: var(--amber-glow);349  background: linear-gradient(135deg, var(--bg2) 80%, rgba(245,166,35,.04));350}351 352.card-top {353  display: flex;354  align-items: flex-start;355  gap: 9px;356  margin-bottom: 9px;357}358 359.card-check {360  width: 15px;361  height: 15px;362  accent-color: var(--amber);363  flex-shrink: 0;364  margin-top: 2px;365  cursor: pointer;366}367 368.card-info { flex: 1; min-width: 0; }369 370.card-key {371  font-family: var(--mono);372  font-size: 11.5px;373  font-weight: 600;374  color: var(--text);375  letter-spacing: .3px;376  white-space: nowrap;377  overflow: hidden;378  text-overflow: ellipsis;379}380 381.card-lbl {382  font-size: 11px;383  color: var(--text3);384  margin-top: 2px;385  line-height: 1.35;386}387 388.badge {389  flex-shrink: 0;390  font-family: var(--mono);391  font-size: 9px;392  font-weight: 700;393  text-transform: uppercase;394  letter-spacing: .6px;395  padding: 2px 7px;396  border-radius: 20px;397}398 399/* Tag badge styles */400.badge-critical  { background: rgba(240,80,80,.14);  color: #f05f5f; border: 1px solid rgba(240,80,80,.3); }401.badge-credential{ background: rgba(220,140,60,.13); color: #e09040; border: 1px solid rgba(220,140,60,.28); }402.badge-feature   { background: rgba(70,140,250,.12); color: #5a9eff; border: 1px solid rgba(70,140,250,.25); }403.badge-optional  { background: rgba(61,214,140,.10); color: #3dd68c; border: 1px solid rgba(61,214,140,.22); }404.badge-advanced  { background: rgba(160,100,230,.12);color: #b07ae0; border: 1px solid rgba(160,100,230,.25); }405.badge-build     { background: rgba(240,185,60,.12); color: #e0b030; border: 1px solid rgba(240,185,60,.28); }406 407/* Card left-border accents */408.env-card:has(.badge-critical)  { border-left: 3px solid rgba(240,80,80,.4); }409.env-card:has(.badge-critical):hover { border-left-color: rgba(240,80,80,.7); }410.env-card:has(.badge-critical).selected { border-left-color: #f05f5f; }411.env-card:has(.badge-credential){ border-left: 3px solid rgba(220,140,60,.3); }412 413/* Section count badge */414.sec-count {415  font-family: var(--mono);416  font-size: 10px;417  color: var(--text3);418  background: var(--bg3);419  border: 1px solid var(--border);420  border-radius: 10px;421  padding: 1px 7px;422}423 424/* Tag legend */425.tag-legend {426  margin-bottom: 14px;427  background: var(--bg2);428  border: 1px solid var(--border);429  border-radius: var(--r);430  overflow: hidden;431}432.legend-summary {433  display: flex;434  align-items: center;435  gap: 10px;436  padding: 7px 12px;437  cursor: pointer;438  list-style: none;439  user-select: none;440  outline: none;441}442.legend-summary::-webkit-details-marker { display: none; }443.legend-chips { display: flex; gap: 5px; flex-wrap: wrap; flex: 1; }444.legend-hint { font-size: 10px; color: var(--text3); white-space: nowrap; flex-shrink: 0; }445.tag-legend[open] .legend-hint { opacity: 0; }446.legend-body {447  padding: 8px 12px 10px;448  border-top: 1px solid var(--border);449  display: flex;450  flex-direction: column;451  gap: 6px;452}453.legend-row { display: flex; align-items: center; gap: 10px; font-size: 11px; color: var(--text2); }454.legend-row .badge { flex-shrink: 0; width: 74px; text-align: center; }455.legend-tip { font-size: 9.5px; color: var(--text3); margin-top: 4px; padding-top: 6px; border-top: 1px solid var(--border); }456.toolbar-hint { color: var(--text3); font-size: 12px; margin-right: 6px; white-space: nowrap; }457 458.card-input { position: relative; }459 460.card-input input[type="text"],461.card-input input[type="password"],462.card-input input[type="number"],463.card-input textarea,464.card-input select {465  width: 100%;466  background: var(--bg3);467  border: 1px solid var(--border);468  border-radius: var(--r);469  padding: 7px 10px;470  font-family: var(--mono);471  font-size: 11.5px;472  color: var(--text);473  outline: none;474  transition: border-color .15s;475  resize: vertical;476}477 478.card-input input[type="text"]:focus,479.card-input input[type="password"]:focus,480.card-input input[type="number"]:focus,481.card-input textarea:focus,482.card-input select:focus {483  border-color: var(--amber);484}485 486.card-input textarea { min-height: 64px; }487.card-input select {488  cursor: pointer;489  appearance: none;490  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%238d97ad' d='M6 8L1 3h10z'/%3E%3C/svg%3E");491  background-repeat: no-repeat;492  background-position: right 10px center;493  padding-right: 28px;494}495 496.card-input optgroup { color: var(--text2); font-weight: 600; }497.card-input option { color: var(--text); background: var(--bg3); }498 499.toggle-shell { display: flex; align-items: center; gap: 8px; }500.tog {501  padding: 5px 14px;502  border-radius: 20px;503  border: 1px solid var(--border2);504  background: var(--bg3);505  color: var(--text3);506  font-family: var(--mono);507  font-size: 11px;508  font-weight: 700;509  cursor: pointer;510  transition: all .18s;511  letter-spacing: .5px;512}513.tog.on {514  background: rgba(61,214,140,.15);515  border-color: rgba(61,214,140,.4);516  color: var(--green);517}518 519.picker-shell { display: flex; flex-direction: column; gap: 6px; }520.picker-row { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }521 522.picker-select {523  flex: 1;524  min-width: 0;525  padding: 6px 28px 6px 8px !important;526  font-size: 11px !important;527}528 529.mini-btn {530  padding: 5px 9px;531  border-radius: var(--r);532  border: 1px solid var(--border2);533  background: var(--bg3);534  color: var(--text2);535  font-family: var(--mono);536  font-size: 10px;537  font-weight: 600;538  cursor: pointer;539  transition: all .15s;540  white-space: nowrap;541}542.mini-btn:hover { background: var(--bg4); color: var(--text); }543 544.right-panel {545  width: var(--panel-w);546  flex-shrink: 0;547  border-left: 1px solid var(--border);548  background: var(--bg2);549  display: flex;550  flex-direction: column;551  overflow: hidden;552}553 554.panel-scroll {555  flex: 1;556  overflow-y: auto;557  padding: 16px;558  display: flex;559  flex-direction: column;560  gap: 16px;561}562 563.panel-scroll::-webkit-scrollbar { width: 4px; }564.panel-scroll::-webkit-scrollbar-track { background: transparent; }565.panel-scroll::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 4px; }566 567.pblock {568  background: var(--bg3);569  border: 1px solid var(--border);570  border-radius: var(--r2);571  overflow: hidden;572}573 574.pblock-head {575  display: flex;576  align-items: center;577  justify-content: space-between;578  padding: 10px 14px;579  border-bottom: 1px solid var(--border);580}581 582.pblock-title {583  font-size: 10.5px;584  font-weight: 700;585  text-transform: uppercase;586  letter-spacing: 1px;587  color: var(--text3);588  display: flex;589  align-items: center;590  gap: 6px;591}592 593.pblock-body { padding: 12px 14px; display: flex; flex-direction: column; gap: 8px; }594 595.pblock-body textarea,596.pblock-body input[type="text"] {597  width: 100%;598  background: var(--bg);599  border: 1px solid var(--border);600  border-radius: var(--r);601  padding: 8px 10px;602  font-family: var(--mono);603  font-size: 10.5px;604  color: var(--text2);605  outline: none;606  resize: vertical;607  transition: border-color .15s;608}609 610.pblock-body textarea:focus,611.pblock-body input[type="text"]:focus {612  border-color: var(--amber);613  color: var(--text);614}615 616#importText { min-height: 80px; }617#bundleOut { min-height: 60px; color: var(--amber2); }618#envLineOut { font-size: 10px; }619 620.row-btns { display: flex; gap: 6px; flex-wrap: wrap; }621 622#summary {623  font-size: 11.5px;624  color: var(--text2);625  line-height: 1.6;626}627 628#summary strong {629  font-size: 15px;630  color: var(--amber);631  font-family: var(--mono);632}633 634.sum-keys {635  margin-top: 8px;636  display: flex;637  flex-wrap: wrap;638  gap: 4px;639}640 641.sum-key {642  font-family: var(--mono);643  font-size: 9.5px;644  color: var(--text2);645  background: var(--bg4);646  border: 1px solid var(--border2);647  border-radius: 4px;648  padding: 2px 6px;649}650 651#customSec { margin-top: 8px; }652 653.custom-row {654  display: flex;655  gap: 8px;656  align-items: center;657  margin-bottom: 8px;658}659 660.custom-row input {661  flex: 1;662  background: var(--bg3);663  border: 1px solid var(--border);664  border-radius: var(--r);665  padding: 7px 10px;666  font-family: var(--mono);667  font-size: 11px;668  color: var(--text);669  outline: none;670  transition: border-color .15s;671  min-width: 0;672}673 674.custom-row input:focus { border-color: var(--amber); }675.custom-row input:first-child { flex: 0 0 40%; }676 677#toast {678  position: fixed;679  bottom: 24px;680  left: 50%;681  transform: translateX(-50%) translateY(20px);682  background: var(--bg4);683  border: 1px solid var(--border2);684  color: var(--amber);685  font-family: var(--mono);686  font-size: 12px;687  font-weight: 600;688  padding: 9px 20px;689  border-radius: 30px;690  z-index: 9999;691  opacity: 0;692  transition: opacity .2s, transform .2s;693  pointer-events: none;694  box-shadow: 0 8px 32px rgba(0,0,0,.5);695}696 697#toast.show {698  opacity: 1;699  transform: translateX(-50%) translateY(0);700}701 702::-webkit-scrollbar { width: 6px; height: 6px; }703::-webkit-scrollbar-track { background: transparent; }704::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 4px; }705 706@media (max-width: 900px) {707  :root { --panel-w: 280px; --sidebar-w: 180px; }708}709 710@media (max-width: 700px) {711  .right-panel { display: none; }712  :root { --sidebar-w: 160px; }713}714 715@media (max-width: 520px) {716  .sidebar-wrap { display: none; }717  .topbar-divider, .topbar-title { display: none; }718}719</style>720</head>721 722<body>723 724<header class="topbar">725  <div class="topbar-logo">726    <span class="logo-emoji">🪽</span>727    <span class="topbar-wordmark">Hugging<em>Mes</em></span>728  </div>729  <div class="topbar-divider"></div>730  <span class="topbar-title">ENV Builder</span>731  <div class="topbar-spacer"></div>732  <span class="topbar-pill">v2025</span>733</header>734 735<div class="layout">736 737  <aside class="sidebar-wrap">738    <div class="sidebar-scroll">739      <div id="sidebar"></div>740    </div>741  </aside>742 743  <main class="main">744 745    <div class="toolbar">746      <span class="toolbar-hint">Tip: Start with <strong>⚡ Required</strong>, then fill keys and click <strong># Generate Bundle</strong>.</span>747      <div class="search-wrap">748        <span class="search-icon">⌕</span>749        <input id="search" type="text" placeholder="Search variables…" autocomplete="off" spellcheck="false">750      </div>751 752      <div class="tb-sep"></div>753 754      <button id="selectRequired" class="btn">⚡ Required</button>755      <button id="selectCommon" class="btn">★ Common</button>756      <button id="selectVisible" class="btn">☑ Visible</button>757      <button id="clearAll" class="btn btn-ghost">✕ Clear</button>758    </div>759 760    <div class="content-wrap">761 762      <div class="sections-scroll">763 764        <details class="tag-legend">765          <summary class="legend-summary">766            <div class="legend-chips">767              <span class="badge badge-critical">critical</span>768              <span class="badge badge-credential">credential</span>769              <span class="badge badge-feature">feature</span>770              <span class="badge badge-optional">optional</span>771              <span class="badge badge-advanced">advanced</span>772              <span class="badge badge-build">build</span>773            </div>774            <span class="legend-hint">▸ Tag legend</span>775          </summary>776          <div class="legend-body">777            <div class="legend-row"><span class="badge badge-critical">critical</span> Required for the space to function at all</div>778            <div class="legend-row"><span class="badge badge-credential">credential</span> API keys, tokens, secrets — keep private</div>779            <div class="legend-row"><span class="badge badge-feature">feature</span> Unlocks an optional feature or integration</div>780            <div class="legend-row"><span class="badge badge-optional">optional</span> Useful but not required; has a default</div>781            <div class="legend-row"><span class="badge badge-advanced">advanced</span> Fine-tuning for specific deployments</div>782            <div class="legend-row"><span class="badge badge-build">build</span> Affects Docker build, not runtime</div>783            <div class="legend-tip">Use <strong>⚡ Required</strong> to auto-select all critical fields, then fill in credential keys.</div>784          </div>785        </details>786 787        <div id="sections"></div>788 789        <div id="customSec" class="sec" data-section="Custom Env">790          <div class="sec-header">791            <span class="sec-icon">🔧</span>792            <span class="sec-title">Custom Env</span>793            <div class="sec-line"></div>794          </div>795          <div id="customRows"></div>796          <button id="addCustom" class="btn" style="margin-top:6px;">+ Add variable</button>797        </div>798      </div>799 800      <aside class="right-panel">801        <div class="panel-scroll">802 803          <div class="pblock">804            <div class="pblock-head">805              <span class="pblock-title">📊 Summary</span>806            </div>807            <div class="pblock-body">808              <div id="summary">No variables selected yet.</div>809            </div>810          </div>811 812          <div class="pblock">813            <div class="pblock-head">814              <span class="pblock-title">📦 Bundle Output</span>815            </div>816            <div class="pblock-body">817              <textarea id="bundleOut" placeholder="Select variables and click # Generate Bundle…" readonly spellcheck="false"></textarea>818              <input type="text" id="envLineOut" placeholder="HUGGINGMES_ENV_BUNDLE=…" readonly spellcheck="false">819              <div class="row-btns">820                <button id="generateBundle" class="btn btn-amber" style="width:100%;"># Generate Bundle</button>821              </div>822              <div class="row-btns">823                <button id="copyBundle" class="btn btn-amber">⎘ Bundle</button>824                <button id="copyEnvLine" class="btn">⎘ Env Line</button>825                <button id="copyJson" class="btn">⎘ JSON</button>826                <button id="applyBundle" class="btn btn-ghost">↺ Apply</button>827              </div>828            </div>829          </div>830 831          <div class="pblock">832            <div class="pblock-head">833              <span class="pblock-title">📥 Import</span>834            </div>835            <div class="pblock-body">836              <textarea id="importText" placeholder="Paste .env, JSON, or HUGGINGMES_ENV_BUNDLE=… here" spellcheck="false"></textarea>837              <button id="applyImport" class="btn btn-amber" style="width:100%;">↓ Import & Apply</button>838            </div>839          </div>840 841        </div>842      </aside>843 844    </div>845  </main>846</div>847 848<div id="toast">Copied ✓</div>849 850<script src="env-builder.js"></script>851 852</body>853</html>854