mirror of
https://github.com/Dvorinka/Containr.git
synced 2026-10-28 07:41:27 +00:00
feat(site): wire landing to deployed app demo
- All CTAs (nav, hero, install note, gallery, catalog, footer) link to https://containr-app.vercel.app - the app frontend deployed as a public demo (VITE_PUBLIC_DEMO build). - templates.html: per-template "Open in demo app" deep links via ?template=<id>; dead default API removed so the official snapshot renders instantly until an instance is configured with ?api=. - Hero canvas screenshot updated to the fullscreen canvas build. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
117b469fae
commit
e825eb0d7c
4 files changed
+45
-35
No files matched your search
+11
-9
@@ -34,7 +34,7 @@
|
||||
<a class="gh-link" href="https://github.com/Dvorinka/Containr" target="_blank" rel="noopener" aria-label="Containr on GitHub">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8Z"/></svg>
|
||||
</a>
|
||||
<a class="btn btn-primary" href="#install">Get started</a>
|
||||
<a class="btn btn-primary" href="https://containr-app.vercel.app/projects">Live demo</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -48,16 +48,16 @@
|
||||
<h1>Deploy containers on <em>your own cloud</em></h1>
|
||||
<p class="sub">Containr turns a Docker host into a full deployment platform. Git builds, managed databases, previews, failover.</p>
|
||||
<div class="hero-cta">
|
||||
<a class="btn btn-primary" href="#install">
|
||||
Get started
|
||||
<a class="btn btn-primary" href="https://containr-app.vercel.app/projects">
|
||||
Explore the live demo
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
|
||||
</a>
|
||||
<a class="btn btn-ghost" href="https://github.com/Dvorinka/Containr" target="_blank" rel="noopener">View on GitHub</a>
|
||||
<a class="btn btn-ghost" href="#install">Get started</a>
|
||||
</div>
|
||||
|
||||
<div class="shot-frame reveal">
|
||||
<div class="shot-bar"><span class="addr">localhost:3000/canvas</span></div>
|
||||
<img src="screenshots/canvas.png" alt="Containr project canvas with two connected services" fetchpriority="high">
|
||||
<div class="shot-bar"><span class="addr">containr-app.vercel.app/projects/demo-project-core</span></div>
|
||||
<img src="screenshots/canvas.png" alt="Containr fullscreen project canvas with connected services" fetchpriority="high">
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@@ -67,7 +67,7 @@
|
||||
<div class="install-inner reveal">
|
||||
<div class="install-copy">
|
||||
<h2>One command, running stack</h2>
|
||||
<p>Requires Docker and openssl. Installs into ./containr, never overwrites your .env.</p>
|
||||
<p>Requires Docker and openssl. Installs into ./containr, never overwrites your .env. <a href="https://containr-app.vercel.app/projects" style="color: var(--accent);">Or explore the hosted demo first →</a></p>
|
||||
</div>
|
||||
<div class="cmd">
|
||||
<code id="install-cmd">curl -fsSL https://raw.githubusercontent.com/Dvorinka/Containr/main/install.sh | bash</code>
|
||||
@@ -154,6 +154,7 @@
|
||||
</div>
|
||||
<img id="gallery-img" src="screenshots/dashboard.png" alt="Containr dashboard" loading="lazy">
|
||||
<p class="cap" id="gallery-cap">Projects dashboard with host CPU, memory, and disk telemetry.</p>
|
||||
<p class="cap"><a href="https://containr-app.vercel.app/projects/demo-project-core" style="color: var(--accent);">Try the canvas live →</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -162,7 +163,7 @@
|
||||
<div class="wrap">
|
||||
<div class="sec-head reveal">
|
||||
<h2>A catalog worth browsing</h2>
|
||||
<p>Thirty official templates plus community presets. <a href="templates.html" style="color: var(--accent);">Browse the full catalog</a> or publish your own.</p>
|
||||
<p>Thirty official templates plus community presets. <a href="templates.html" style="color: var(--accent);">Browse the full catalog</a>, <a href="https://containr-app.vercel.app/templates" style="color: var(--accent);">open it in the app</a>, or publish your own.</p>
|
||||
</div>
|
||||
<div class="marquee reveal" aria-label="Template catalog">
|
||||
<div class="marquee-track" id="marquee-track">
|
||||
@@ -231,7 +232,7 @@
|
||||
Get started
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
|
||||
</a>
|
||||
<a class="btn btn-ghost" href="https://github.com/Dvorinka/Containr" target="_blank" rel="noopener">Star on GitHub</a>
|
||||
<a class="btn btn-ghost" href="https://containr-app.vercel.app/projects">Live demo</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -240,6 +241,7 @@
|
||||
<div class="wrap foot">
|
||||
<span class="l"><img src="containr.svg" alt="">Containr - MIT License</span>
|
||||
<nav>
|
||||
<a href="https://containr-app.vercel.app/projects">Live demo</a>
|
||||
<a href="https://github.com/Dvorinka/Containr" target="_blank" rel="noopener">GitHub</a>
|
||||
<a href="https://github.com/Dvorinka/Containr/tree/main/docs" target="_blank" rel="noopener">Docs</a>
|
||||
<a href="https://github.com/Dvorinka/Containr/blob/main/CONTRIBUTING.md" target="_blank" rel="noopener">Contribute</a>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 145 KiB |
+29
-21
@@ -317,7 +317,7 @@
|
||||
<a class="gh-link" href="https://github.com/Dvorinka/Containr" target="_blank" rel="noopener" aria-label="Containr on GitHub">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8Z"/></svg>
|
||||
</a>
|
||||
<a class="btn btn-primary" href="index.html#install">Get started</a>
|
||||
<a class="btn btn-primary" href="https://containr-app.vercel.app/projects">Live demo</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -370,6 +370,7 @@
|
||||
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="12" height="12" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
|
||||
Copy template JSON
|
||||
</button>
|
||||
<a class="btn btn-ghost" id="m-open" href="https://containr-app.vercel.app/templates" target="_blank" rel="noopener">Open in demo app</a>
|
||||
<a class="btn btn-ghost" href="https://github.com/Dvorinka/Containr/tree/main/docs/guides" target="_blank" rel="noopener">Deploy guide</a>
|
||||
</div>
|
||||
<p class="hint">In your instance: <code>Templates → New template → Upload .json</code> (or paste the copied JSON). Deploy it to any project from there.</p>
|
||||
@@ -380,6 +381,7 @@
|
||||
<div class="wrap foot">
|
||||
<span class="l"><img src="containr.svg" alt="">Containr - MIT License</span>
|
||||
<nav>
|
||||
<a href="https://containr-app.vercel.app/projects">Live demo</a>
|
||||
<a href="https://github.com/Dvorinka/Containr" target="_blank" rel="noopener">GitHub</a>
|
||||
<a href="https://github.com/Dvorinka/Containr/tree/main/docs" target="_blank" rel="noopener">Docs</a>
|
||||
<a href="https://github.com/Dvorinka/Containr/blob/main/CONTRIBUTING.md" target="_blank" rel="noopener">Contribute</a>
|
||||
@@ -389,14 +391,15 @@
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
// The catalog comes from a live Containr instance when one is reachable.
|
||||
// Default is the project's public API; override once with ?api=https://host
|
||||
// (persisted in localStorage) or fall back to the bundled snapshot.
|
||||
const DEFAULT_API = 'https://containr-api.up.railway.app';
|
||||
// The catalog comes from a live Containr instance when one is configured.
|
||||
// Point it at an instance once with ?api=https://host (persisted in
|
||||
// localStorage); with no instance configured the bundled official
|
||||
// snapshot renders immediately.
|
||||
const APP_BASE = 'https://containr-app.vercel.app';
|
||||
const params = new URLSearchParams(location.search);
|
||||
const paramApi = params.get('api');
|
||||
if (paramApi) localStorage.setItem('containr-api', paramApi.replace(/\/$/, ''));
|
||||
const API_BASE = (localStorage.getItem('containr-api') || DEFAULT_API).replace(/\/$/, '');
|
||||
const API_BASE = (localStorage.getItem('containr-api') || '').replace(/\/$/, '');
|
||||
|
||||
const grid = document.getElementById('grid');
|
||||
const catsEl = document.getElementById('cats');
|
||||
@@ -412,22 +415,26 @@
|
||||
const esc = (s) => String(s ?? '').replace(/[&<>"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]));
|
||||
|
||||
async function loadTemplates() {
|
||||
const ctrl = new AbortController();
|
||||
const timer = setTimeout(() => ctrl.abort(), 4000);
|
||||
try {
|
||||
const res = await fetch(API_BASE + '/api/v1/templates', { signal: ctrl.signal });
|
||||
if (!res.ok) throw new Error('api ' + res.status);
|
||||
const data = await res.json();
|
||||
const list = Array.isArray(data.templates) ? data.templates : [];
|
||||
if (!list.length) throw new Error('empty catalog');
|
||||
setTemplates(list, 'live: ' + API_BASE.replace(/^https?:\/\//, ''), true);
|
||||
} catch {
|
||||
const res = await fetch('templates.json');
|
||||
const data = await res.json();
|
||||
setTemplates(data.templates || [], 'offline snapshot - official catalog', false);
|
||||
} finally {
|
||||
clearTimeout(timer);
|
||||
if (API_BASE) {
|
||||
const ctrl = new AbortController();
|
||||
const timer = setTimeout(() => ctrl.abort(), 4000);
|
||||
try {
|
||||
const res = await fetch(API_BASE + '/api/v1/templates', { signal: ctrl.signal });
|
||||
if (!res.ok) throw new Error('api ' + res.status);
|
||||
const data = await res.json();
|
||||
const list = Array.isArray(data.templates) ? data.templates : [];
|
||||
if (!list.length) throw new Error('empty catalog');
|
||||
setTemplates(list, 'live: ' + API_BASE.replace(/^https?:\/\//, ''), true);
|
||||
return;
|
||||
} catch {
|
||||
// fall through to the bundled snapshot
|
||||
} finally {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
}
|
||||
const res = await fetch('templates.json');
|
||||
const data = await res.json();
|
||||
setTemplates(data.templates || [], 'official snapshot - connect an instance with ?api=', false);
|
||||
}
|
||||
|
||||
function setTemplates(list, label, live) {
|
||||
@@ -534,6 +541,7 @@
|
||||
document.getElementById('m-badges').innerHTML =
|
||||
badge(t) + `<span class="badge" style="background:var(--surface-muted);color:var(--text-tertiary)">${esc(t.category || 'custom')}</span>`;
|
||||
document.getElementById('m-desc').textContent = t.description || 'No description.';
|
||||
document.getElementById('m-open').href = `${APP_BASE}/templates?template=${encodeURIComponent(t.id)}`;
|
||||
|
||||
const c = cfg(t);
|
||||
const meta = [];
|
||||
|
||||
+5
-5
@@ -6,7 +6,7 @@
|
||||
"description": "Generic Node.js application with automatic dependency detection",
|
||||
"category": "web",
|
||||
"logo": "https://cdn.simpleicons.org/node.js",
|
||||
"config": "{\"type\":\"web\",\"runtime\":\"node\",\"build_command\":\"npm install \u0026\u0026 npm run build\",\"start_command\":\"npm start\",\"port\":3000,\"health_check\":\"/health\"}",
|
||||
"config": "{\"type\":\"web\",\"runtime\":\"node\",\"build_command\":\"npm install && npm run build\",\"start_command\":\"npm start\",\"port\":3000,\"health_check\":\"/health\"}",
|
||||
"variables": "[{\"key\":\"NODE_ENV\",\"label\":\"Node Environment\",\"default\":\"production\",\"required\":false,\"secret\":false},{\"key\":\"NPM_TOKEN\",\"label\":\"NPM Token\",\"default\":\"\",\"required\":false,\"secret\":true}]",
|
||||
"is_official": true,
|
||||
"is_public": false,
|
||||
@@ -19,7 +19,7 @@
|
||||
"description": "React single-page application with Vite",
|
||||
"category": "frontend",
|
||||
"logo": "https://cdn.simpleicons.org/react",
|
||||
"config": "{\"type\":\"web\",\"runtime\":\"node\",\"build_command\":\"npm install \u0026\u0026 npm run build\",\"start_command\":\"npx serve -s dist\",\"port\":3000}",
|
||||
"config": "{\"type\":\"web\",\"runtime\":\"node\",\"build_command\":\"npm install && npm run build\",\"start_command\":\"npx serve -s dist\",\"port\":3000}",
|
||||
"variables": "[{\"key\":\"VITE_API_URL\",\"label\":\"API URL\",\"default\":\"\",\"required\":true,\"secret\":false}]",
|
||||
"is_official": true,
|
||||
"is_public": false,
|
||||
@@ -148,7 +148,7 @@
|
||||
"name": "Background Worker",
|
||||
"description": "Background job processing service",
|
||||
"category": "worker",
|
||||
"logo": "https://cdn.simpleicons.org/terminal",
|
||||
"logo": "",
|
||||
"config": "{\"type\":\"worker\",\"runtime\":\"node\",\"build_command\":\"npm install\",\"start_command\":\"npm run worker\"}",
|
||||
"variables": "[{\"key\":\"WORKER_CONCURRENCY\",\"label\":\"Concurrency\",\"default\":\"4\",\"required\":false,\"secret\":false}]",
|
||||
"is_official": true,
|
||||
@@ -161,7 +161,7 @@
|
||||
"name": "Cron Job",
|
||||
"description": "Scheduled task runner",
|
||||
"category": "cron",
|
||||
"logo": "https://cdn.simpleicons.org/clock",
|
||||
"logo": "",
|
||||
"config": "{\"type\":\"cron\",\"runtime\":\"node\",\"build_command\":\"npm install\",\"start_command\":\"npm run cron\"}",
|
||||
"variables": "[{\"key\":\"CRON_SCHEDULE\",\"label\":\"Schedule\",\"default\":\"0 * * * *\",\"required\":true,\"secret\":false}]",
|
||||
"is_official": true,
|
||||
@@ -226,7 +226,7 @@
|
||||
"name": "Uptime Kuma",
|
||||
"description": "Self-hosted monitoring tool for services and websites",
|
||||
"category": "app",
|
||||
"logo": "https://cdn.simpleicons.org/uptimerobot",
|
||||
"logo": "https://cdn.simpleicons.org/uptimekuma",
|
||||
"config": "{\"type\":\"web\",\"runtime\":\"louislam/uptime-kuma:1\",\"port\":3001,\"health_check\":\"/\"}",
|
||||
"variables": "[]",
|
||||
"is_official": true,
|
||||
|
||||
Reference in new issue
Block a user