forgedock 1.0.16 → 1.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -3
- package/bin/cross-publish.mjs +344 -0
- package/bin/forgedock.mjs +2205 -541
- package/bin/github-app-manifest.json.license +2 -0
- package/bin/hooks/session-start.mjs +4 -5
- package/bin/registry.mjs +20 -0
- package/bin/tui.mjs +172 -96
- package/commands/adopt.md +433 -0
- package/commands/analytics.md +2 -0
- package/commands/audit-agents.md +2 -0
- package/commands/audit.md +2 -0
- package/commands/autopilot.md +77 -0
- package/commands/changelog.md +354 -0
- package/commands/cleanup.md +2 -0
- package/commands/compat-audit.md +330 -0
- package/commands/deploy-info.md +6 -5
- package/commands/design-bench.md +176 -0
- package/commands/design-render-critique-loop.md +103 -0
- package/commands/design.md +259 -0
- package/commands/diagnose.md +483 -0
- package/commands/explain.md +349 -0
- package/commands/forge-stats.md +2 -0
- package/commands/forgedock-init.md +2 -0
- package/commands/geo-audit.md +2 -0
- package/commands/incident-response.md +2 -0
- package/commands/issue.md +9 -3
- package/commands/milestone.md +2 -0
- package/commands/optimize.md +411 -0
- package/commands/orchestrate.md +239 -0
- package/commands/pipeline-health.md +60 -1
- package/commands/qa-sweep.md +39 -2
- package/commands/quality-gate.md +67 -0
- package/commands/replay.md +263 -0
- package/commands/resume.md +264 -0
- package/commands/review-pr-agents.md +5 -1
- package/commands/review-pr-staging.md +160 -2
- package/commands/review-pr.md +85 -3
- package/commands/rollback.md +2 -0
- package/commands/scope.md +280 -0
- package/commands/security-audit.md +2 -0
- package/commands/status.md +262 -0
- package/commands/sync-ecosystem.md +2 -0
- package/commands/test-gate.md +929 -0
- package/commands/validate.md +2 -0
- package/commands/work-on/build/architect.md +128 -18
- package/commands/work-on/build/context.md +130 -17
- package/commands/work-on/build/implement.md +7 -3
- package/commands/work-on/build/validate.md +2 -0
- package/commands/work-on/build.md +32 -7
- package/commands/work-on/close.md +85 -0
- package/commands/work-on/decompose.md +2 -0
- package/commands/work-on/investigate.md +30 -3
- package/commands/work-on/review.md +13 -1
- package/commands/work-on-monolithic.md +2 -0
- package/commands/work-on.md +676 -38
- package/docs/BRAND.md +51 -0
- package/docs/CI.md +177 -0
- package/docs/CONFIG.md +94 -0
- package/docs/FORGE-PROTOCOL.md +324 -0
- package/docs/articles/b-vs-c-baseline.md +210 -0
- package/docs/articles/full-abc-benchmark.md +205 -0
- package/docs/articles/per-repo-adaptive-scripts-token-savings.md +174 -0
- package/docs/articles/selective-spec-loading-token-savings.md +140 -0
- package/docs/claude-breakpoints.json +47 -0
- package/docs/design/abc-benchmark.md +195 -0
- package/docs/design/design-architect-rationale.md +123 -0
- package/docs/design/design-memory.md +61 -0
- package/docs/design/design-spec-schema.md +248 -0
- package/docs/design/design-system-lint.md +150 -0
- package/docs/design/divergent-generation.md +106 -0
- package/docs/design/effects-appropriateness.md +133 -0
- package/docs/design/fixtures/briefs/README.md +47 -0
- package/docs/design/fixtures/briefs/cadence.md +39 -0
- package/docs/design/fixtures/briefs/plume.md +39 -0
- package/docs/design/fixtures/briefs/slipstream.md +39 -0
- package/docs/design/fixtures/briefs/tender.md +39 -0
- package/docs/design/fixtures/briefs/voltage.md +39 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/cadence/arm-b/run-1.html +364 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/cadence/arm-b/run-2.html +420 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/cadence/arm-b/run-3.html +506 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/plume/arm-b/run-1.html +611 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/plume/arm-b/run-2.html +594 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/plume/arm-b/run-3.html +817 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/runs.json +175 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/scorecard.json +138 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/slipstream/arm-b/run-1.html +373 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/slipstream/arm-b/run-2.html +398 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/slipstream/arm-b/run-3.html +595 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/tender/arm-b/run-1.html +531 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/tender/arm-b/run-2.html +565 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/tender/arm-b/run-3.html +674 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/voltage/arm-b/run-1.html +388 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/voltage/arm-b/run-2.html +463 -0
- package/docs/design/fixtures/runs/b-vs-c-baseline/voltage/arm-b/run-3.html +568 -0
- package/docs/design/fixtures/runs/full-abc/cadence/arm-a/run-1.html +562 -0
- package/docs/design/fixtures/runs/full-abc/cadence/arm-a/run-2.html +618 -0
- package/docs/design/fixtures/runs/full-abc/cadence/arm-a/run-3.html +618 -0
- package/docs/design/fixtures/runs/full-abc/cadence/arm-b/run-1.html +364 -0
- package/docs/design/fixtures/runs/full-abc/cadence/arm-b/run-2.html +420 -0
- package/docs/design/fixtures/runs/full-abc/cadence/arm-b/run-3.html +506 -0
- package/docs/design/fixtures/runs/full-abc/plume/arm-a/run-1.html +527 -0
- package/docs/design/fixtures/runs/full-abc/plume/arm-a/run-2.html +445 -0
- package/docs/design/fixtures/runs/full-abc/plume/arm-a/run-3.html +483 -0
- package/docs/design/fixtures/runs/full-abc/plume/arm-b/run-1.html +611 -0
- package/docs/design/fixtures/runs/full-abc/plume/arm-b/run-2.html +594 -0
- package/docs/design/fixtures/runs/full-abc/plume/arm-b/run-3.html +817 -0
- package/docs/design/fixtures/runs/full-abc/runs.json +190 -0
- package/docs/design/fixtures/runs/full-abc/scorecard.json +144 -0
- package/docs/design/fixtures/runs/full-abc/slipstream/arm-a/run-1.html +496 -0
- package/docs/design/fixtures/runs/full-abc/slipstream/arm-a/run-2.html +447 -0
- package/docs/design/fixtures/runs/full-abc/slipstream/arm-a/run-3.html +564 -0
- package/docs/design/fixtures/runs/full-abc/slipstream/arm-b/run-1.html +373 -0
- package/docs/design/fixtures/runs/full-abc/slipstream/arm-b/run-2.html +398 -0
- package/docs/design/fixtures/runs/full-abc/slipstream/arm-b/run-3.html +595 -0
- package/docs/design/fixtures/runs/full-abc/tender/arm-a/run-1.html +622 -0
- package/docs/design/fixtures/runs/full-abc/tender/arm-a/run-2.html +475 -0
- package/docs/design/fixtures/runs/full-abc/tender/arm-a/run-3.html +660 -0
- package/docs/design/fixtures/runs/full-abc/tender/arm-b/run-1.html +531 -0
- package/docs/design/fixtures/runs/full-abc/tender/arm-b/run-2.html +565 -0
- package/docs/design/fixtures/runs/full-abc/tender/arm-b/run-3.html +674 -0
- package/docs/design/fixtures/runs/full-abc/voltage/arm-a/run-1.html +525 -0
- package/docs/design/fixtures/runs/full-abc/voltage/arm-a/run-2.html +446 -0
- package/docs/design/fixtures/runs/full-abc/voltage/arm-a/run-3.html +463 -0
- package/docs/design/fixtures/runs/full-abc/voltage/arm-b/run-1.html +388 -0
- package/docs/design/fixtures/runs/full-abc/voltage/arm-b/run-2.html +463 -0
- package/docs/design/fixtures/runs/full-abc/voltage/arm-b/run-3.html +568 -0
- package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-a/run-1.html +1068 -0
- package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-a/run-2.html +1423 -0
- package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-a/run-3.html +1245 -0
- package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-b/run-1.html +305 -0
- package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-b/run-2.html +327 -0
- package/docs/design/fixtures/runs/full-abc-opus/cadence/arm-b/run-3.html +428 -0
- package/docs/design/fixtures/runs/full-abc-opus/plume/arm-a/run-1.html +1270 -0
- package/docs/design/fixtures/runs/full-abc-opus/plume/arm-a/run-2.html +1172 -0
- package/docs/design/fixtures/runs/full-abc-opus/plume/arm-a/run-3.html +1532 -0
- package/docs/design/fixtures/runs/full-abc-opus/plume/arm-b/run-1.html +315 -0
- package/docs/design/fixtures/runs/full-abc-opus/plume/arm-b/run-2.html +342 -0
- package/docs/design/fixtures/runs/full-abc-opus/plume/arm-b/run-3.html +353 -0
- package/docs/design/fixtures/runs/full-abc-opus/runs.json +190 -0
- package/docs/design/fixtures/runs/full-abc-opus/scorecard.json +144 -0
- package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-a/run-1.html +345 -0
- package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-a/run-2.html +396 -0
- package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-a/run-3.html +502 -0
- package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-b/run-1.html +408 -0
- package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-b/run-2.html +446 -0
- package/docs/design/fixtures/runs/full-abc-opus/slipstream/arm-b/run-3.html +496 -0
- package/docs/design/fixtures/runs/full-abc-opus/tender/arm-a/run-1.html +813 -0
- package/docs/design/fixtures/runs/full-abc-opus/tender/arm-a/run-2.html +711 -0
- package/docs/design/fixtures/runs/full-abc-opus/tender/arm-a/run-3.html +721 -0
- package/docs/design/fixtures/runs/full-abc-opus/tender/arm-b/run-1.html +280 -0
- package/docs/design/fixtures/runs/full-abc-opus/tender/arm-b/run-2.html +291 -0
- package/docs/design/fixtures/runs/full-abc-opus/tender/arm-b/run-3.html +366 -0
- package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-a/run-1.html +1010 -0
- package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-a/run-2.html +836 -0
- package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-a/run-3.html +930 -0
- package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-b/run-1.html +407 -0
- package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-b/run-2.html +396 -0
- package/docs/design/fixtures/runs/full-abc-opus/voltage/arm-b/run-3.html +529 -0
- package/docs/design/foundations/brutalist.css +294 -0
- package/docs/design/foundations/editorial.css +300 -0
- package/docs/design/foundations/minimal-luxury.css +295 -0
- package/docs/design/foundations/technical.css +293 -0
- package/docs/design/foundations/warm-photo.css +299 -0
- package/docs/design/reference-corpus.md +1726 -0
- package/docs/design/render-critique-loop.md +57 -0
- package/docs/site/getting-started.md +21 -0
- package/docs/spec-graph-schema.md +397 -0
- package/package.json +3 -3
- package/scripts/bench-scorecard.mjs +239 -0
- package/scripts/build-spec-graph.mjs +509 -0
- package/scripts/classify-lane.sh +138 -0
- package/scripts/design-system-lint.mjs +993 -0
- package/scripts/graph-query.sh +486 -0
- package/scripts/transition-label.sh +169 -0
- package/scripts/validate-pr-target.sh +30 -0
- package/scripts/validate-spec-graph.sh +423 -0
- package/templates/devdocs/README.md +72 -0
- package/templates/devdocs/agent/using-forgedock.md +3 -0
- package/templates/devdocs/agent/using-github.md +3 -0
- package/templates/devdocs/index.yaml +162 -0
- package/templates/devdocs/project/architecture.md +3 -0
- package/templates/devdocs/project/conventions.md +3 -0
- package/templates/devdocs/project/custom-instructions.md +3 -0
- package/templates/devdocs/project/glossary.md +3 -0
- package/templates/devdocs/project/stack.md +3 -0
- package/templates/devdocs/templates/commit-convention.md +3 -0
- package/templates/devdocs/templates/issue.md +3 -0
- package/templates/devdocs/templates/pull-request.md +3 -0
- package/templates/devdocs/templates/review-finding.md +3 -0
- package/templates/workflows/forgedock-review.yml +96 -0
|
@@ -0,0 +1,428 @@
|
|
|
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>Cadence — Email sending, solved</title>
|
|
7
|
+
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
8
|
+
<style>
|
|
9
|
+
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
10
|
+
body { font-family: 'Space Grotesk', sans-serif; color: #0c0c0c; background: #fff; -webkit-font-smoothing: antialiased; }
|
|
11
|
+
.wrap { max-width: 1200px; margin: 0 auto; padding: 0 48px; }
|
|
12
|
+
|
|
13
|
+
/* ---- NAV ---- */
|
|
14
|
+
.topbar { padding: 16px 0; }
|
|
15
|
+
.topbar .wrap { display: flex; align-items: center; justify-content: space-between; }
|
|
16
|
+
.brand { font-weight: 700; font-size: 21px; letter-spacing: -0.5px; }
|
|
17
|
+
.brand em { font-style: normal; color: #e55a2b; }
|
|
18
|
+
.topbar nav { display: flex; gap: 32px; align-items: center; }
|
|
19
|
+
.topbar nav a { font-size: 14px; color: #555; text-decoration: none; font-weight: 500; }
|
|
20
|
+
.topbar nav a:hover { color: #000; }
|
|
21
|
+
.pill-btn { background: #e55a2b; color: #fff; padding: 8px 22px; border-radius: 100px; font-weight: 600; font-size: 14px; text-decoration: none; }
|
|
22
|
+
.pill-btn:hover { background: #d14e22; }
|
|
23
|
+
|
|
24
|
+
/* ---- HERO: split diagonal ---- */
|
|
25
|
+
.hero { padding: 80px 0 0; overflow: hidden; }
|
|
26
|
+
.hero-inner { display: grid; grid-template-columns: 5fr 6fr; gap: 0; min-height: 520px; }
|
|
27
|
+
.hero-text { padding: 60px 48px 60px 0; display: flex; flex-direction: column; justify-content: center; }
|
|
28
|
+
.hero-text .overline { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 2px; color: #e55a2b; margin-bottom: 16px; }
|
|
29
|
+
.hero-text h1 { font-size: 50px; font-weight: 700; line-height: 1.1; letter-spacing: -2px; margin-bottom: 20px; }
|
|
30
|
+
.hero-text h1 .highlight { background: linear-gradient(120deg, #e55a2b 0%, #f59e0b 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
|
|
31
|
+
.hero-text p { font-size: 17px; color: #555; line-height: 1.7; margin-bottom: 32px; max-width: 440px; }
|
|
32
|
+
.hero-btns { display: flex; gap: 12px; }
|
|
33
|
+
.btn-orange { background: #e55a2b; color: #fff; padding: 14px 32px; border-radius: 10px; font-weight: 600; font-size: 15px; text-decoration: none; }
|
|
34
|
+
.btn-orange:hover { background: #d14e22; }
|
|
35
|
+
.btn-outline { border: 2px solid #ddd; color: #333; padding: 12px 32px; border-radius: 10px; font-weight: 600; font-size: 15px; text-decoration: none; }
|
|
36
|
+
.btn-outline:hover { border-color: #999; }
|
|
37
|
+
|
|
38
|
+
/* Hero right: stacked terminal */
|
|
39
|
+
.hero-code { background: #1e1e2e; border-radius: 16px 0 0 16px; padding: 40px 40px 40px 48px; display: flex; flex-direction: column; justify-content: center; position: relative; }
|
|
40
|
+
.hero-code::after { content: ''; position: absolute; right: -200px; top: 0; bottom: 0; width: 200px; background: #1e1e2e; }
|
|
41
|
+
.terminal-label { font-family: 'IBM Plex Mono', monospace; font-size: 11px; color: #666; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 12px; }
|
|
42
|
+
.terminal-block { background: #13131f; border-radius: 8px; padding: 20px; margin-bottom: 16px; font-family: 'IBM Plex Mono', monospace; font-size: 13px; line-height: 1.8; color: #cdd6f4; overflow-x: auto; }
|
|
43
|
+
.terminal-block:last-child { margin-bottom: 0; }
|
|
44
|
+
.t-kw { color: #cba6f7; }
|
|
45
|
+
.t-str { color: #a6e3a1; }
|
|
46
|
+
.t-fn { color: #89b4fa; }
|
|
47
|
+
.t-cm { color: #585b70; }
|
|
48
|
+
.t-op { color: #f38ba8; }
|
|
49
|
+
.t-num { color: #fab387; }
|
|
50
|
+
.t-var { color: #cdd6f4; }
|
|
51
|
+
|
|
52
|
+
/* ---- LOGOS / SOCIAL PROOF ---- */
|
|
53
|
+
.proof { padding: 56px 0; border-bottom: 1px solid #eee; }
|
|
54
|
+
.proof .wrap { text-align: center; }
|
|
55
|
+
.proof p { font-size: 13px; color: #aaa; text-transform: uppercase; letter-spacing: 1.5px; font-weight: 600; margin-bottom: 28px; }
|
|
56
|
+
.logo-row { display: flex; justify-content: center; gap: 56px; align-items: center; opacity: 0.35; }
|
|
57
|
+
.logo-row span { font-size: 22px; font-weight: 700; letter-spacing: -0.5px; }
|
|
58
|
+
|
|
59
|
+
/* ---- SPLIT FEATURES (alternating) ---- */
|
|
60
|
+
.split { padding: 100px 0; }
|
|
61
|
+
.split:nth-child(even) { background: #faf9f7; }
|
|
62
|
+
.split-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 80px; align-items: center; }
|
|
63
|
+
.split-grid.reverse { direction: rtl; }
|
|
64
|
+
.split-grid.reverse > * { direction: ltr; }
|
|
65
|
+
.split-text .tag { display: inline-block; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1.5px; padding: 4px 12px; border-radius: 4px; margin-bottom: 16px; }
|
|
66
|
+
.tag-orange { background: #fff3ec; color: #e55a2b; }
|
|
67
|
+
.tag-green { background: #ecfdf5; color: #059669; }
|
|
68
|
+
.tag-blue { background: #eff6ff; color: #2563eb; }
|
|
69
|
+
.tag-purple { background: #f5f3ff; color: #7c3aed; }
|
|
70
|
+
.split-text h2 { font-size: 34px; font-weight: 700; letter-spacing: -1px; margin-bottom: 14px; line-height: 1.2; }
|
|
71
|
+
.split-text p { font-size: 16px; color: #555; line-height: 1.7; margin-bottom: 16px; }
|
|
72
|
+
.split-text ul { list-style: none; margin-top: 8px; }
|
|
73
|
+
.split-text ul li { font-size: 15px; color: #444; padding: 6px 0 6px 22px; position: relative; }
|
|
74
|
+
.split-text ul li::before { content: ''; position: absolute; left: 0; top: 14px; width: 8px; height: 8px; border-radius: 2px; background: #e55a2b; }
|
|
75
|
+
|
|
76
|
+
/* Visual panels */
|
|
77
|
+
.visual-panel { border-radius: 12px; overflow: hidden; }
|
|
78
|
+
.api-response { background: #1e1e2e; border-radius: 12px; padding: 28px; font-family: 'IBM Plex Mono', monospace; font-size: 13px; line-height: 1.8; color: #cdd6f4; }
|
|
79
|
+
.dashboard-mock { background: #fff; border: 1px solid #e5e5e5; border-radius: 12px; padding: 0; overflow: hidden; }
|
|
80
|
+
.dash-header { background: #fafafa; border-bottom: 1px solid #eee; padding: 16px 24px; display: flex; align-items: center; gap: 12px; }
|
|
81
|
+
.dash-dot { width: 10px; height: 10px; border-radius: 50%; background: #ddd; }
|
|
82
|
+
.dash-title { font-size: 13px; font-weight: 600; color: #888; }
|
|
83
|
+
.dash-body { padding: 24px; }
|
|
84
|
+
.stat-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 20px; }
|
|
85
|
+
.stat-box { background: #faf9f7; border-radius: 8px; padding: 16px; }
|
|
86
|
+
.stat-box .val { font-size: 24px; font-weight: 700; }
|
|
87
|
+
.stat-box .lbl { font-size: 12px; color: #999; margin-top: 2px; }
|
|
88
|
+
.bar-chart { display: flex; gap: 6px; align-items: flex-end; height: 80px; }
|
|
89
|
+
.bar-chart .bar { flex: 1; border-radius: 3px 3px 0 0; }
|
|
90
|
+
.b-1 { height: 45%; background: #e55a2b; }
|
|
91
|
+
.b-2 { height: 62%; background: #e55a2b; }
|
|
92
|
+
.b-3 { height: 78%; background: #e55a2b; }
|
|
93
|
+
.b-4 { height: 55%; background: #e55a2b; }
|
|
94
|
+
.b-5 { height: 90%; background: #e55a2b; }
|
|
95
|
+
.b-6 { height: 72%; background: #e55a2b; }
|
|
96
|
+
.b-7 { height: 85%; background: #e55a2b; }
|
|
97
|
+
.b-8 { height: 60%; background: #f59e0b; }
|
|
98
|
+
|
|
99
|
+
.template-mock { background: #fff; border: 1px solid #e5e5e5; border-radius: 12px; overflow: hidden; }
|
|
100
|
+
.tmpl-toolbar { display: flex; gap: 8px; padding: 12px 16px; border-bottom: 1px solid #eee; background: #fafafa; }
|
|
101
|
+
.tmpl-btn { padding: 5px 14px; font-size: 12px; border-radius: 6px; border: 1px solid #ddd; background: #fff; color: #555; font-weight: 500; }
|
|
102
|
+
.tmpl-btn.active { background: #e55a2b; color: #fff; border-color: #e55a2b; }
|
|
103
|
+
.tmpl-body { padding: 24px; font-size: 14px; color: #333; }
|
|
104
|
+
.tmpl-body .subject-line { font-weight: 600; margin-bottom: 16px; padding-bottom: 12px; border-bottom: 1px solid #eee; }
|
|
105
|
+
.tmpl-body .body-text { color: #666; line-height: 1.8; }
|
|
106
|
+
.tmpl-body .var { background: #fff3ec; color: #e55a2b; padding: 1px 6px; border-radius: 3px; font-family: 'IBM Plex Mono', monospace; font-size: 12px; }
|
|
107
|
+
.tmpl-footer { padding: 12px 16px; border-top: 1px solid #eee; font-size: 12px; color: #aaa; }
|
|
108
|
+
|
|
109
|
+
/* ---- NUMBERS STRIP ---- */
|
|
110
|
+
.numbers { padding: 80px 0; background: #1e1e2e; color: #fff; }
|
|
111
|
+
.numbers .wrap { display: grid; grid-template-columns: repeat(4, 1fr); gap: 40px; text-align: center; }
|
|
112
|
+
.n-item .n-val { font-size: 40px; font-weight: 700; letter-spacing: -1px; }
|
|
113
|
+
.n-item .n-val span { color: #e55a2b; }
|
|
114
|
+
.n-item .n-label { font-size: 14px; color: #888; margin-top: 4px; }
|
|
115
|
+
|
|
116
|
+
/* ---- CTA ---- */
|
|
117
|
+
.bottom-cta { padding: 120px 0; text-align: center; background: #faf9f7; }
|
|
118
|
+
.bottom-cta h2 { font-size: 44px; font-weight: 700; letter-spacing: -1.5px; margin-bottom: 16px; }
|
|
119
|
+
.bottom-cta p { font-size: 17px; color: #666; max-width: 500px; margin: 0 auto 40px; line-height: 1.6; }
|
|
120
|
+
.cta-input-row { display: flex; justify-content: center; gap: 8px; max-width: 440px; margin: 0 auto; }
|
|
121
|
+
.cta-input { flex: 1; padding: 14px 20px; border: 2px solid #ddd; border-radius: 10px; font-size: 15px; font-family: 'Space Grotesk', sans-serif; outline: none; }
|
|
122
|
+
.cta-input:focus { border-color: #e55a2b; }
|
|
123
|
+
.cta-input::placeholder { color: #bbb; }
|
|
124
|
+
.cta-go { background: #e55a2b; color: #fff; border: none; padding: 14px 28px; border-radius: 10px; font-weight: 700; font-size: 15px; cursor: pointer; font-family: 'Space Grotesk', sans-serif; }
|
|
125
|
+
.cta-go:hover { background: #d14e22; }
|
|
126
|
+
.cta-fine { font-size: 13px; color: #999; margin-top: 14px; }
|
|
127
|
+
|
|
128
|
+
/* ---- FOOTER ---- */
|
|
129
|
+
footer { padding: 40px 0; border-top: 1px solid #eee; }
|
|
130
|
+
footer .wrap { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 40px; }
|
|
131
|
+
.foot-brand { font-weight: 700; font-size: 18px; margin-bottom: 8px; }
|
|
132
|
+
.foot-brand em { font-style: normal; color: #e55a2b; }
|
|
133
|
+
.foot-desc { font-size: 13px; color: #999; line-height: 1.6; }
|
|
134
|
+
.foot-col h4 { font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: #888; margin-bottom: 12px; }
|
|
135
|
+
.foot-col a { display: block; font-size: 14px; color: #555; text-decoration: none; padding: 4px 0; }
|
|
136
|
+
.foot-col a:hover { color: #000; }
|
|
137
|
+
</style>
|
|
138
|
+
</head>
|
|
139
|
+
<body>
|
|
140
|
+
|
|
141
|
+
<div class="topbar">
|
|
142
|
+
<div class="wrap">
|
|
143
|
+
<div class="brand">cadenc<em>e</em></div>
|
|
144
|
+
<nav>
|
|
145
|
+
<a href="#">Docs</a>
|
|
146
|
+
<a href="#">Pricing</a>
|
|
147
|
+
<a href="#">Templates</a>
|
|
148
|
+
<a href="#">Blog</a>
|
|
149
|
+
<a href="#">Login</a>
|
|
150
|
+
<a href="#" class="pill-btn">Start for free</a>
|
|
151
|
+
</nav>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
<!-- HERO -->
|
|
156
|
+
<section class="hero">
|
|
157
|
+
<div class="wrap">
|
|
158
|
+
<div class="hero-inner">
|
|
159
|
+
<div class="hero-text">
|
|
160
|
+
<div class="overline">Email API for developers</div>
|
|
161
|
+
<h1>Stop wrestling with email.<br><span class="highlight">Start sending it.</span></h1>
|
|
162
|
+
<p>Cadence gives you a REST API to send transactional and marketing email, a template editor for your content team, and deliverability infrastructure that keeps you out of the spam folder.</p>
|
|
163
|
+
<div class="hero-btns">
|
|
164
|
+
<a href="#" class="btn-orange">Get your API key</a>
|
|
165
|
+
<a href="#" class="btn-outline">See the docs</a>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
<div class="hero-code">
|
|
169
|
+
<div class="terminal-label">Send your first email</div>
|
|
170
|
+
<div class="terminal-block">
|
|
171
|
+
<span class="t-cm">// Install: npm install @cadence/node</span>
|
|
172
|
+
<br><br><span class="t-kw">import</span> { <span class="t-fn">Cadence</span> } <span class="t-kw">from</span> <span class="t-str">'@cadence/node'</span>;
|
|
173
|
+
<br><span class="t-kw">const</span> <span class="t-var">cadence</span> <span class="t-op">=</span> <span class="t-kw">new</span> <span class="t-fn">Cadence</span>(process.env.<span class="t-var">CADENCE_API_KEY</span>);
|
|
174
|
+
<br><br><span class="t-kw">const</span> { <span class="t-var">id</span> } <span class="t-op">=</span> <span class="t-kw">await</span> cadence.<span class="t-fn">send</span>({
|
|
175
|
+
<br> <span class="t-var">from</span>: <span class="t-str">'team@yourapp.com'</span>,
|
|
176
|
+
<br> <span class="t-var">to</span>: <span class="t-str">'jamie@example.com'</span>,
|
|
177
|
+
<br> <span class="t-var">subject</span>: <span class="t-str">'Your order has shipped'</span>,
|
|
178
|
+
<br> <span class="t-var">template</span>: <span class="t-str">'order-shipped'</span>,
|
|
179
|
+
<br> <span class="t-var">data</span>: {
|
|
180
|
+
<br> <span class="t-var">name</span>: <span class="t-str">'Jamie'</span>,
|
|
181
|
+
<br> <span class="t-var">tracking</span>: <span class="t-str">'1Z999AA10...'</span>
|
|
182
|
+
<br> }
|
|
183
|
+
<br>});
|
|
184
|
+
</div>
|
|
185
|
+
<div class="terminal-label">Response</div>
|
|
186
|
+
<div class="terminal-block">
|
|
187
|
+
{
|
|
188
|
+
<br> <span class="t-str">"id"</span>: <span class="t-str">"msg_8fK2xLm9..."</span>,
|
|
189
|
+
<br> <span class="t-str">"status"</span>: <span class="t-str">"queued"</span>,
|
|
190
|
+
<br> <span class="t-str">"estimated_delivery"</span>: <span class="t-str">"<1s"</span>
|
|
191
|
+
<br>}
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
</section>
|
|
197
|
+
|
|
198
|
+
<!-- Social proof -->
|
|
199
|
+
<section class="proof">
|
|
200
|
+
<div class="wrap">
|
|
201
|
+
<p>Trusted by engineering teams at</p>
|
|
202
|
+
<div class="logo-row">
|
|
203
|
+
<span>Vercel</span>
|
|
204
|
+
<span>Linear</span>
|
|
205
|
+
<span>Notion</span>
|
|
206
|
+
<span>Supabase</span>
|
|
207
|
+
<span>Planetscale</span>
|
|
208
|
+
</div>
|
|
209
|
+
</div>
|
|
210
|
+
</section>
|
|
211
|
+
|
|
212
|
+
<!-- Feature 1: Deliverability -->
|
|
213
|
+
<section class="split">
|
|
214
|
+
<div class="wrap">
|
|
215
|
+
<div class="split-grid">
|
|
216
|
+
<div class="split-text">
|
|
217
|
+
<div class="tag tag-green">Deliverability</div>
|
|
218
|
+
<h2>Your email lands in the inbox. We make sure of it.</h2>
|
|
219
|
+
<p>Deliverability is the hardest part of email and the most invisible. Cadence manages domain authentication, IP reputation, bounce processing, and suppression lists automatically.</p>
|
|
220
|
+
<ul>
|
|
221
|
+
<li>SPF, DKIM, and DMARC configured with one DNS change</li>
|
|
222
|
+
<li>Dedicated IP pools with automated warm-up</li>
|
|
223
|
+
<li>Real-time bounce and complaint suppression</li>
|
|
224
|
+
<li>Blocklist monitoring and proactive alerts</li>
|
|
225
|
+
<li>ISP postmaster integration for Gmail, Outlook, Yahoo</li>
|
|
226
|
+
</ul>
|
|
227
|
+
</div>
|
|
228
|
+
<div class="api-response">
|
|
229
|
+
<span class="t-cm">// GET /v1/domains/yourapp.com/health</span>
|
|
230
|
+
<br><br>{
|
|
231
|
+
<br> <span class="t-str">"domain"</span>: <span class="t-str">"yourapp.com"</span>,
|
|
232
|
+
<br> <span class="t-str">"authentication"</span>: {
|
|
233
|
+
<br> <span class="t-str">"spf"</span>: <span class="t-str">"pass"</span>,
|
|
234
|
+
<br> <span class="t-str">"dkim"</span>: <span class="t-str">"pass"</span>,
|
|
235
|
+
<br> <span class="t-str">"dmarc"</span>: <span class="t-str">"pass"</span>
|
|
236
|
+
<br> },
|
|
237
|
+
<br> <span class="t-str">"reputation"</span>: <span class="t-num">97</span>,
|
|
238
|
+
<br> <span class="t-str">"bounce_rate_30d"</span>: <span class="t-num">0.002</span>,
|
|
239
|
+
<br> <span class="t-str">"complaint_rate_30d"</span>: <span class="t-num">0.0001</span>,
|
|
240
|
+
<br> <span class="t-str">"blocklists"</span>: []
|
|
241
|
+
<br>}
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
245
|
+
</section>
|
|
246
|
+
|
|
247
|
+
<!-- Feature 2: Templates -->
|
|
248
|
+
<section class="split" style="background:#faf9f7;">
|
|
249
|
+
<div class="wrap">
|
|
250
|
+
<div class="split-grid reverse">
|
|
251
|
+
<div class="split-text">
|
|
252
|
+
<div class="tag tag-orange">Templates</div>
|
|
253
|
+
<h2>Engineers build templates. Content teams own them.</h2>
|
|
254
|
+
<p>Create email templates from React-style components or use the visual editor. Either way, your marketing and product people can edit subject lines, body copy, and scheduling without opening a code editor.</p>
|
|
255
|
+
<ul>
|
|
256
|
+
<li>Build from composable components (headers, CTAs, product cards)</li>
|
|
257
|
+
<li>Visual drag-and-drop editor for non-engineers</li>
|
|
258
|
+
<li>Variables, conditionals, and loops in templates</li>
|
|
259
|
+
<li>Version history with instant rollback</li>
|
|
260
|
+
<li>Preview with real recipient data before sending</li>
|
|
261
|
+
</ul>
|
|
262
|
+
</div>
|
|
263
|
+
<div class="template-mock">
|
|
264
|
+
<div class="tmpl-toolbar">
|
|
265
|
+
<div class="tmpl-btn active">Visual</div>
|
|
266
|
+
<div class="tmpl-btn">HTML</div>
|
|
267
|
+
<div class="tmpl-btn">Preview</div>
|
|
268
|
+
<div class="tmpl-btn">Data</div>
|
|
269
|
+
</div>
|
|
270
|
+
<div class="tmpl-body">
|
|
271
|
+
<div class="subject-line">Subject: Your order <span class="var">{{order_id}}</span> has shipped</div>
|
|
272
|
+
<div class="body-text">
|
|
273
|
+
Hi <span class="var">{{name}}</span>,<br><br>
|
|
274
|
+
Great news! Your order <span class="var">{{order_id}}</span> is on its way. You can track your package using the link below.<br><br>
|
|
275
|
+
<span style="display:inline-block; background:#e55a2b; color:#fff; padding:8px 20px; border-radius:6px; font-size:13px; font-weight:600;">Track my order</span><br><br>
|
|
276
|
+
Estimated delivery: <span class="var">{{delivery_date}}</span>
|
|
277
|
+
</div>
|
|
278
|
+
</div>
|
|
279
|
+
<div class="tmpl-footer">Template: order-shipped · v3 · Last edited by Maria L. · 1 day ago</div>
|
|
280
|
+
</div>
|
|
281
|
+
</div>
|
|
282
|
+
</div>
|
|
283
|
+
</section>
|
|
284
|
+
|
|
285
|
+
<!-- Feature 3: Analytics -->
|
|
286
|
+
<section class="split">
|
|
287
|
+
<div class="wrap">
|
|
288
|
+
<div class="split-grid">
|
|
289
|
+
<div class="split-text">
|
|
290
|
+
<div class="tag tag-blue">Analytics</div>
|
|
291
|
+
<h2>See what happens after you hit send</h2>
|
|
292
|
+
<p>Track deliveries, opens, clicks, bounces, and unsubscribes in real time. Drill down per message, per template, or per domain. Export everything to your data warehouse.</p>
|
|
293
|
+
<ul>
|
|
294
|
+
<li>Per-message event timeline (queued, sent, delivered, opened, clicked)</li>
|
|
295
|
+
<li>Aggregate dashboards by template, tag, or time range</li>
|
|
296
|
+
<li>Webhooks for every event, delivered in under 500ms</li>
|
|
297
|
+
<li>S3 export for long-term storage and analysis</li>
|
|
298
|
+
</ul>
|
|
299
|
+
</div>
|
|
300
|
+
<div class="dashboard-mock">
|
|
301
|
+
<div class="dash-header">
|
|
302
|
+
<div class="dash-dot"></div>
|
|
303
|
+
<div class="dash-dot"></div>
|
|
304
|
+
<div class="dash-dot"></div>
|
|
305
|
+
<div class="dash-title">Analytics — Last 7 days</div>
|
|
306
|
+
</div>
|
|
307
|
+
<div class="dash-body">
|
|
308
|
+
<div class="stat-row">
|
|
309
|
+
<div class="stat-box"><div class="val">142,391</div><div class="lbl">Delivered</div></div>
|
|
310
|
+
<div class="stat-box"><div class="val">68.2%</div><div class="lbl">Open rate</div></div>
|
|
311
|
+
<div class="stat-box"><div class="val">12.4%</div><div class="lbl">Click rate</div></div>
|
|
312
|
+
<div class="stat-box"><div class="val">0.3%</div><div class="lbl">Bounce rate</div></div>
|
|
313
|
+
</div>
|
|
314
|
+
<div class="bar-chart">
|
|
315
|
+
<div class="bar b-1"></div>
|
|
316
|
+
<div class="bar b-2"></div>
|
|
317
|
+
<div class="bar b-3"></div>
|
|
318
|
+
<div class="bar b-4"></div>
|
|
319
|
+
<div class="bar b-5"></div>
|
|
320
|
+
<div class="bar b-6"></div>
|
|
321
|
+
<div class="bar b-7"></div>
|
|
322
|
+
<div class="bar b-8"></div>
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
326
|
+
</div>
|
|
327
|
+
</div>
|
|
328
|
+
</section>
|
|
329
|
+
|
|
330
|
+
<!-- Feature 4: Testing -->
|
|
331
|
+
<section class="split" style="background:#faf9f7;">
|
|
332
|
+
<div class="wrap">
|
|
333
|
+
<div class="split-grid reverse">
|
|
334
|
+
<div class="split-text">
|
|
335
|
+
<div class="tag tag-purple">Testing</div>
|
|
336
|
+
<h2>Test every email before it reaches a real inbox</h2>
|
|
337
|
+
<p>Cadence's test mode captures outgoing email in a virtual inbox. Your integration tests can assert on email content, and your team can preview rendered templates with live data.</p>
|
|
338
|
+
<ul>
|
|
339
|
+
<li>Sandbox mode: all emails captured, none delivered</li>
|
|
340
|
+
<li>API to query captured emails in test suites</li>
|
|
341
|
+
<li>Visual preview with real template data</li>
|
|
342
|
+
<li>Separate test and production API keys</li>
|
|
343
|
+
</ul>
|
|
344
|
+
</div>
|
|
345
|
+
<div class="api-response">
|
|
346
|
+
<span class="t-cm">// Test mode: emails are captured, not sent</span>
|
|
347
|
+
<br><span class="t-kw">const</span> cadence <span class="t-op">=</span> <span class="t-kw">new</span> <span class="t-fn">Cadence</span>(<span class="t-str">'cd_test_...'</span>);
|
|
348
|
+
<br><br><span class="t-kw">await</span> cadence.<span class="t-fn">send</span>({
|
|
349
|
+
<br> <span class="t-var">to</span>: <span class="t-str">'test@example.com'</span>,
|
|
350
|
+
<br> <span class="t-var">template</span>: <span class="t-str">'welcome'</span>,
|
|
351
|
+
<br> <span class="t-var">data</span>: { <span class="t-var">name</span>: <span class="t-str">'Test User'</span> }
|
|
352
|
+
<br>});
|
|
353
|
+
<br><br><span class="t-cm">// Assert in your test suite</span>
|
|
354
|
+
<br><span class="t-kw">const</span> inbox <span class="t-op">=</span> <span class="t-kw">await</span> cadence.<span class="t-fn">testInbox</span>(<span class="t-str">'test@example.com'</span>);
|
|
355
|
+
<br>expect(inbox[<span class="t-num">0</span>].subject).<span class="t-fn">toContain</span>(<span class="t-str">'Welcome'</span>);
|
|
356
|
+
<br>expect(inbox[<span class="t-num">0</span>].html).<span class="t-fn">toContain</span>(<span class="t-str">'Test User'</span>);
|
|
357
|
+
</div>
|
|
358
|
+
</div>
|
|
359
|
+
</div>
|
|
360
|
+
</section>
|
|
361
|
+
|
|
362
|
+
<!-- Numbers -->
|
|
363
|
+
<section class="numbers">
|
|
364
|
+
<div class="wrap">
|
|
365
|
+
<div class="n-item">
|
|
366
|
+
<div class="n-val">2.1<span>B</span></div>
|
|
367
|
+
<div class="n-label">Emails delivered per month</div>
|
|
368
|
+
</div>
|
|
369
|
+
<div class="n-item">
|
|
370
|
+
<div class="n-val">99.98<span>%</span></div>
|
|
371
|
+
<div class="n-label">API uptime (90-day rolling)</div>
|
|
372
|
+
</div>
|
|
373
|
+
<div class="n-item">
|
|
374
|
+
<div class="n-val"><250<span>ms</span></div>
|
|
375
|
+
<div class="n-label">p95 API response time</div>
|
|
376
|
+
</div>
|
|
377
|
+
<div class="n-item">
|
|
378
|
+
<div class="n-val">7</div>
|
|
379
|
+
<div class="n-label">Official SDK languages</div>
|
|
380
|
+
</div>
|
|
381
|
+
</div>
|
|
382
|
+
</section>
|
|
383
|
+
|
|
384
|
+
<!-- CTA -->
|
|
385
|
+
<section class="bottom-cta">
|
|
386
|
+
<div class="wrap">
|
|
387
|
+
<h2>Ready to send?</h2>
|
|
388
|
+
<p>Create a free account and get your API key. 10,000 emails per month on the free tier. No credit card, no sales call.</p>
|
|
389
|
+
<div class="cta-input-row">
|
|
390
|
+
<input type="email" class="cta-input" placeholder="you@company.com">
|
|
391
|
+
<button class="cta-go">Get API key</button>
|
|
392
|
+
</div>
|
|
393
|
+
<div class="cta-fine">Free plan includes full API access, template editor, analytics, and test mode.</div>
|
|
394
|
+
</div>
|
|
395
|
+
</section>
|
|
396
|
+
|
|
397
|
+
<footer>
|
|
398
|
+
<div class="wrap">
|
|
399
|
+
<div>
|
|
400
|
+
<div class="foot-brand">cadenc<em>e</em></div>
|
|
401
|
+
<div class="foot-desc">Email infrastructure for developers<br>and the teams they work with.</div>
|
|
402
|
+
</div>
|
|
403
|
+
<div class="foot-col">
|
|
404
|
+
<h4>Product</h4>
|
|
405
|
+
<a href="#">API Reference</a>
|
|
406
|
+
<a href="#">SDKs</a>
|
|
407
|
+
<a href="#">Templates</a>
|
|
408
|
+
<a href="#">Pricing</a>
|
|
409
|
+
</div>
|
|
410
|
+
<div class="foot-col">
|
|
411
|
+
<h4>Resources</h4>
|
|
412
|
+
<a href="#">Documentation</a>
|
|
413
|
+
<a href="#">Changelog</a>
|
|
414
|
+
<a href="#">Status Page</a>
|
|
415
|
+
<a href="#">Blog</a>
|
|
416
|
+
</div>
|
|
417
|
+
<div class="foot-col">
|
|
418
|
+
<h4>Company</h4>
|
|
419
|
+
<a href="#">About</a>
|
|
420
|
+
<a href="#">Security</a>
|
|
421
|
+
<a href="#">Privacy</a>
|
|
422
|
+
<a href="#">Terms</a>
|
|
423
|
+
</div>
|
|
424
|
+
</div>
|
|
425
|
+
</footer>
|
|
426
|
+
|
|
427
|
+
</body>
|
|
428
|
+
</html>
|