feat: deploy nxtgauge.com coming-soon page
The static page (coming-soon/) has existed in this repo since 167ea12
but was never actually wired up - its own README says as much ('Add
this repo to your Kustomize setup and create a Deployment + Service +
Ingress'). No ingress for the bare nxtgauge.com/www.nxtgauge.com
domain existed at all (only subdomains: api/admin/test111/llm/ci/logs).
Deploys the page as a stock nginx:1.27-alpine container (no custom
image/CI build needed - the whole site is ~183KB of static HTML/PNG/
SVG) with the content mounted via two ConfigMaps (configmap-html for
index.html + nginx.conf, configmap-assets for the logo/trademark
files - split because ConfigMap keys can't contain '/', so the
assets/ subdirectory needed its own map). 2 replicas, standard
readiness/liveness probes, ingress for both nxtgauge.com and
www.nxtgauge.com terminating TLS via the existing letsencrypt-prod
ClusterIssuer.
Confirmed DNS for both hostnames already resolves through the same
Cloudflare-proxied IPs as the working test111.nxtgauge.com subdomain -
no DNS changes needed, this starts serving as soon as Flux applies it.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
3da2937c8e
commit
93d0254b2d
8 changed files with 498 additions and 0 deletions
58
apps/nxtgauge-coming-soon/base/configmap-assets.yaml
Normal file
58
apps/nxtgauge-coming-soon/base/configmap-assets.yaml
Normal file
File diff suppressed because one or more lines are too long
311
apps/nxtgauge-coming-soon/base/configmap-html.yaml
Normal file
311
apps/nxtgauge-coming-soon/base/configmap-html.yaml
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
apiVersion: v1
|
||||
data:
|
||||
index.html: |
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Nxtgauge — Coming Soon</title>
|
||||
<meta name="description" content="Nxtgauge is launching soon — India's marketplace for jobs and professional services, powered by AI." />
|
||||
<meta property="og:title" content="Nxtgauge — Coming Soon" />
|
||||
<meta property="og:description" content="India's marketplace for jobs and professional services. Launching soon." />
|
||||
<link rel="icon" href="/assets/nxtgauge-logo.png" type="image/png" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Exo+2:wght@400;600;700;800;900&display=swap" rel="stylesheet" />
|
||||
|
||||
<style>
|
||||
/* ── Brand tokens (from nxtgauge app.css) ─────────────────── */
|
||||
:root {
|
||||
--orange: #fd6116;
|
||||
--orange-dark: #e45a14;
|
||||
--navy: #050026;
|
||||
--font: "Exo 2", "Segoe UI", system-ui, -apple-system, sans-serif;
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
html, body { height: 100%; }
|
||||
|
||||
body {
|
||||
font-family: var(--font);
|
||||
background: var(--navy);
|
||||
color: #fff;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 100dvh;
|
||||
overflow: hidden;
|
||||
padding: 32px 24px 100px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* ── Background layers ───────────────────────────────────────── */
|
||||
.bg {
|
||||
position: fixed; inset: 0; pointer-events: none; z-index: 0;
|
||||
}
|
||||
.bg-base {
|
||||
position: absolute; inset: 0;
|
||||
background: radial-gradient(ellipse 80% 60% at 50% 0%, #17003e 0%, var(--navy) 70%);
|
||||
}
|
||||
.bg-mesh {
|
||||
position: absolute; inset: 0;
|
||||
background:
|
||||
radial-gradient(ellipse 65% 55% at 50% 30%, rgba(253,97,22,0.22) 0%, transparent 65%),
|
||||
radial-gradient(ellipse 45% 40% at 10% 80%, rgba(50,30,120,0.18) 0%, transparent 60%),
|
||||
radial-gradient(ellipse 45% 40% at 90% 75%, rgba(253,97,22,0.09) 0%, transparent 60%);
|
||||
}
|
||||
.bg-grid {
|
||||
position: absolute; inset: 0;
|
||||
background-image:
|
||||
linear-gradient(rgba(255,255,255,0.025) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgba(255,255,255,0.025) 1px, transparent 1px);
|
||||
background-size: 48px 48px;
|
||||
}
|
||||
.orb {
|
||||
position: absolute; border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(253,97,22,0.14) 0%, transparent 70%);
|
||||
animation: orbFloat linear infinite;
|
||||
}
|
||||
.orb-1 { width: 600px; height: 600px; top: -220px; left: -180px; animation-duration: 20s; }
|
||||
.orb-2 { width: 380px; height: 380px; bottom: -100px; right: -60px; animation-duration: 15s; animation-delay: -7s; }
|
||||
@keyframes orbFloat {
|
||||
0% { transform: translateY(0) scale(1); }
|
||||
50% { transform: translateY(-28px) scale(1.04); }
|
||||
100% { transform: translateY(0) scale(1); }
|
||||
}
|
||||
|
||||
/* ── Content ─────────────────────────────────────────────────── */
|
||||
.content {
|
||||
position: relative; z-index: 1;
|
||||
display: flex; flex-direction: column;
|
||||
align-items: center; text-align: center;
|
||||
max-width: 580px; width: 100%;
|
||||
}
|
||||
|
||||
.brand-logo {
|
||||
height: 50px; width: auto;
|
||||
margin-bottom: 52px;
|
||||
filter: brightness(0) invert(1);
|
||||
}
|
||||
|
||||
/* Badge */
|
||||
.badge {
|
||||
display: inline-flex; align-items: center; gap: 9px;
|
||||
font-size: 11px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
|
||||
color: var(--orange);
|
||||
border: 1px solid rgba(253,97,22,0.38);
|
||||
padding: 7px 18px; border-radius: 999px;
|
||||
background: rgba(253,97,22,0.08);
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.badge-dot {
|
||||
width: 6px; height: 6px; border-radius: 50%;
|
||||
background: var(--orange);
|
||||
box-shadow: 0 0 7px var(--orange);
|
||||
animation: blink 2.2s ease-in-out infinite;
|
||||
}
|
||||
@keyframes blink { 0%,100%{opacity:1} 50%{opacity:0.28} }
|
||||
|
||||
/* Headline */
|
||||
h1 {
|
||||
font-size: clamp(44px, 10vw, 86px);
|
||||
font-weight: 900;
|
||||
letter-spacing: -0.04em;
|
||||
line-height: 0.95;
|
||||
color: #fff;
|
||||
margin-bottom: 26px;
|
||||
}
|
||||
h1 .accent {
|
||||
display: block;
|
||||
background: linear-gradient(105deg, var(--orange) 0%, #ff9c65 55%, #ffcba0 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
/* Tagline */
|
||||
.tagline {
|
||||
font-size: clamp(14px, 2vw, 17px);
|
||||
color: rgba(255,255,255,0.48);
|
||||
line-height: 1.68;
|
||||
max-width: 420px;
|
||||
margin-bottom: 52px;
|
||||
}
|
||||
|
||||
/* Email form */
|
||||
.form {
|
||||
display: flex;
|
||||
width: 100%; max-width: 420px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.form input {
|
||||
flex: 1; height: 50px; padding: 0 18px;
|
||||
border: 1.5px solid rgba(255,255,255,0.12); border-right: none;
|
||||
border-radius: 10px 0 0 10px;
|
||||
background: rgba(255,255,255,0.05);
|
||||
color: #fff; font-family: var(--font); font-size: 14px;
|
||||
outline: none; transition: border-color 0.2s;
|
||||
}
|
||||
.form input::placeholder { color: rgba(255,255,255,0.24); }
|
||||
.form input:focus { border-color: rgba(253,97,22,0.5); }
|
||||
.form button {
|
||||
height: 50px; padding: 0 22px;
|
||||
border: none; border-radius: 0 10px 10px 0;
|
||||
background: var(--orange); color: var(--navy);
|
||||
font-family: var(--font); font-size: 14px; font-weight: 700;
|
||||
cursor: pointer; white-space: nowrap;
|
||||
transition: background 0.15s;
|
||||
}
|
||||
.form button:hover { background: var(--orange-dark); }
|
||||
.form button:active { transform: scale(0.98); }
|
||||
|
||||
.form-note {
|
||||
font-size: 11px;
|
||||
color: rgba(255,255,255,0.22);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.form-success {
|
||||
display: none;
|
||||
font-size: 14px; font-weight: 600; color: #4ade80;
|
||||
animation: fadeIn 0.4s ease;
|
||||
}
|
||||
@keyframes fadeIn { from{opacity:0;transform:translateY(6px)} to{opacity:1;transform:translateY(0)} }
|
||||
|
||||
/* ── Footer ──────────────────────────────────────────────────── */
|
||||
.footer {
|
||||
position: fixed; bottom: 0; left: 0; right: 0;
|
||||
z-index: 1;
|
||||
display: flex; flex-direction: column; align-items: center;
|
||||
gap: 6px; padding: 14px 0 18px;
|
||||
background: linear-gradient(to top, rgba(5,0,38,0.9) 0%, transparent 100%);
|
||||
}
|
||||
.footer-copy {
|
||||
font-size: 11px; color: rgba(255,255,255,0.2); letter-spacing: 0.04em;
|
||||
}
|
||||
.footer-powered {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
}
|
||||
.footer-powered-label {
|
||||
font-size: 11px; font-weight: 700; letter-spacing: 0.08em;
|
||||
text-transform: uppercase; color: rgba(255,255,255,0.55);
|
||||
}
|
||||
.footer-powered-logo {
|
||||
height: 26px; width: auto;
|
||||
filter: brightness(0) invert(1);
|
||||
opacity: 0.85;
|
||||
transition: opacity 0.15s;
|
||||
}
|
||||
.footer-powered-logo:hover { opacity: 1; }
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.form { flex-direction: column; }
|
||||
.form input {
|
||||
border-right: 1.5px solid rgba(255,255,255,0.12);
|
||||
border-bottom: none;
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
.form button { border-radius: 0 0 10px 10px; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Background -->
|
||||
<div class="bg" aria-hidden="true">
|
||||
<div class="bg-base"></div>
|
||||
<div class="bg-mesh"></div>
|
||||
<div class="bg-grid"></div>
|
||||
<div class="orb orb-1"></div>
|
||||
<div class="orb orb-2"></div>
|
||||
</div>
|
||||
|
||||
<!-- Content -->
|
||||
<main class="content">
|
||||
<img class="brand-logo" src="/assets/nxtgauge-logo.png" alt="Nxtgauge" />
|
||||
|
||||
<div class="badge">
|
||||
<div class="badge-dot"></div>
|
||||
Coming Soon
|
||||
</div>
|
||||
|
||||
<h1>
|
||||
Something Big<br>
|
||||
<span class="accent">Is Coming.</span>
|
||||
</h1>
|
||||
|
||||
<p class="tagline">
|
||||
India's marketplace for jobs and professional services —
|
||||
verified professionals, AI-powered tools, fair for everyone.
|
||||
</p>
|
||||
|
||||
<form class="form" id="notifyForm" onsubmit="handleSubmit(event)">
|
||||
<input type="email" id="emailInput" placeholder="Enter your email" required autocomplete="email" />
|
||||
<button type="submit">Notify Me</button>
|
||||
</form>
|
||||
<p class="form-note" id="formNote">No spam. We'll only email when we launch.</p>
|
||||
<p class="form-success" id="successMsg">✓ You're on the list! We'll reach out when we go live.</p>
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="footer">
|
||||
<div class="footer-copy">© 2026 Nxtgauge. All rights reserved.</div>
|
||||
<div class="footer-powered">
|
||||
<span class="footer-powered-label">Powered by</span>
|
||||
<img class="footer-powered-logo" src="/assets/traceworks-trademark-white.svg" alt="Traceworks" />
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
function handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
const email = document.getElementById('emailInput').value.trim();
|
||||
if (!email) return;
|
||||
|
||||
document.getElementById('notifyForm').style.display = 'none';
|
||||
document.getElementById('formNote').style.display = 'none';
|
||||
document.getElementById('successMsg').style.display = 'block';
|
||||
|
||||
// Wire to your backend — example:
|
||||
// fetch('/api/waitlist', {
|
||||
// method: 'POST',
|
||||
// headers: { 'Content-Type': 'application/json' },
|
||||
// body: JSON.stringify({ email })
|
||||
// });
|
||||
|
||||
console.log('Waitlist signup:', email);
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
nginx.conf: |
|
||||
server {
|
||||
listen 80;
|
||||
server_name nxtgauge.com www.nxtgauge.com;
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
# Serve static assets with caching
|
||||
location /assets/ {
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
# All requests serve the single page
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# Redirect www to non-www
|
||||
if ($host = www.nxtgauge.com) {
|
||||
return 301 https://nxtgauge.com$request_uri;
|
||||
}
|
||||
}
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: nxtgauge-coming-soon-html
|
||||
namespace: nxtgauge
|
||||
63
apps/nxtgauge-coming-soon/base/deployment.yaml
Normal file
63
apps/nxtgauge-coming-soon/base/deployment.yaml
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nxtgauge-coming-soon
|
||||
namespace: nxtgauge
|
||||
labels:
|
||||
app: nxtgauge-coming-soon
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nxtgauge-coming-soon
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nxtgauge-coming-soon
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.27-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
volumeMounts:
|
||||
- name: html
|
||||
mountPath: /usr/share/nginx/html/index.html
|
||||
subPath: index.html
|
||||
- name: html
|
||||
mountPath: /etc/nginx/conf.d/default.conf
|
||||
subPath: nginx.conf
|
||||
- name: assets
|
||||
mountPath: /usr/share/nginx/html/assets
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 80
|
||||
initialDelaySeconds: 3
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 80
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 20
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
memory: 16Mi
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 64Mi
|
||||
volumes:
|
||||
- name: html
|
||||
configMap:
|
||||
name: nxtgauge-coming-soon-html
|
||||
- name: assets
|
||||
configMap:
|
||||
name: nxtgauge-coming-soon-assets
|
||||
36
apps/nxtgauge-coming-soon/base/ingress.yaml
Normal file
36
apps/nxtgauge-coming-soon/base/ingress.yaml
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: nxtgauge-coming-soon
|
||||
namespace: nxtgauge
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
tls:
|
||||
- hosts:
|
||||
- nxtgauge.com
|
||||
- www.nxtgauge.com
|
||||
secretName: nxtgauge-com-tls
|
||||
rules:
|
||||
- host: nxtgauge.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nxtgauge-coming-soon
|
||||
port:
|
||||
number: 80
|
||||
- host: www.nxtgauge.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: nxtgauge-coming-soon
|
||||
port:
|
||||
number: 80
|
||||
8
apps/nxtgauge-coming-soon/base/kustomization.yaml
Normal file
8
apps/nxtgauge-coming-soon/base/kustomization.yaml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- configmap-html.yaml
|
||||
- configmap-assets.yaml
|
||||
- deployment.yaml
|
||||
- service.yaml
|
||||
- ingress.yaml
|
||||
16
apps/nxtgauge-coming-soon/base/service.yaml
Normal file
16
apps/nxtgauge-coming-soon/base/service.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nxtgauge-coming-soon
|
||||
namespace: nxtgauge
|
||||
labels:
|
||||
app: nxtgauge-coming-soon
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: nxtgauge-coming-soon
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
namespace: nxtgauge
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ../../base
|
||||
|
|
@ -5,6 +5,7 @@ resources:
|
|||
- ../../apps/nxtgauge-backend-rust/overlays/prod
|
||||
- ../../apps/nxtgauge-frontend-solid/overlays/prod
|
||||
- ../../apps/nxtgauge-admin-solid/overlays/prod
|
||||
- ../../apps/nxtgauge-coming-soon/overlays/prod
|
||||
- ../../apps/nxtgauge-ai-assistant/overlays/prod
|
||||
- ../../apps/github-actions-runners/base
|
||||
- ../../apps/ollama/base
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue