- {!playground && (
+
+ {!playground && !frontpage && (
)}
-
+
diff --git a/site/decodal-site/src/pages/index.astro b/site/decodal-site/src/pages/index.astro
index c35adfa..3895e98 100644
--- a/site/decodal-site/src/pages/index.astro
+++ b/site/decodal-site/src/pages/index.astro
@@ -1,3 +1,64 @@
---
-return Astro.redirect('/docs/introduction/');
+import ManualLayout from '../layouts/ManualLayout.astro';
+
+const example = `Port = Int >= 1 & <= 65535 default 8080;
+
+Server = {
+ host = String default "localhost";
+ port = Port;
+};
+
+Production = Server & {
+ host = "example.com";
+};`;
---
+
+
+ Lazy configuration and schema language
+ Decodal keeps configuration, constraints, and defaults in one composable value.
+
+ Define structured data with constraints, compose it with patches, and materialize the result from Rust,
+ WebAssembly, or the browser playground.
+
+
+
+
+
+
+ What it is
+
+ Decodal is a small data language for configuration shapes that need validation, defaults,
+ lazy imports, and predictable composition.
+
+
+
+ Where it runs
+
+ Use the Rust crate for runtime embedding, the WASM package in browsers, CodeMirror/Lezer for the Web editor,
+ and Tree-sitter for general editor integration.
+
+
+
+ Start here
+
+ Open the playground to run examples in your browser, or read the components page to see how the runtime and
+ editor pieces fit together.
+
+ View components →
+
+
+
+
+
+
A compact example
+
+ Constraints and defaults are values. Compose them with concrete data and materialize when the host knows what
+ output shape it expects.
+
+
+ {example}
+
+
diff --git a/site/decodal-site/src/style.css b/site/decodal-site/src/style.css
index 451e8ba..5e365d3 100644
--- a/site/decodal-site/src/style.css
+++ b/site/decodal-site/src/style.css
@@ -458,6 +458,99 @@ button:disabled {
white-space: nowrap;
}
+.frontpage {
+ max-width: 1120px;
+ margin: 0 auto;
+}
+
+.hero {
+ padding: 5rem 0 4rem;
+}
+
+.eyebrow {
+ color: var(--muted);
+ font-size: 0.9rem;
+ font-weight: 700;
+ letter-spacing: 0.08em;
+ margin: 0 0 1rem;
+ text-transform: uppercase;
+}
+
+.hero h1 {
+ font-size: clamp(2.4rem, 6vw, 5rem);
+ line-height: 0.95;
+ letter-spacing: -0.06em;
+ margin: 0;
+ max-width: 950px;
+}
+
+.hero-copy {
+ color: var(--muted);
+ font-size: 1.2rem;
+ line-height: 1.7;
+ max-width: 760px;
+ margin: 1.5rem 0 0;
+}
+
+.hero-actions {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.9rem;
+ margin-top: 2rem;
+}
+
+.button {
+ border-radius: 999px;
+ font-weight: 700;
+ padding: 0.8rem 1.15rem;
+ text-decoration: none;
+}
+
+.button.primary {
+ background: var(--link);
+ color: #ffffff;
+}
+
+.button.secondary {
+ border: 1px solid var(--border);
+ color: var(--text);
+}
+
+.home-grid {
+ display: grid;
+ gap: 1rem;
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ margin-bottom: 1.5rem;
+}
+
+.home-card,
+.home-example {
+ background: var(--surface);
+ border: 1px solid var(--border);
+ border-radius: 18px;
+ padding: 1.4rem;
+}
+
+.home-card h2,
+.home-example h2 {
+ margin-top: 0;
+}
+
+.home-card p:last-child,
+.home-example p:last-child {
+ margin-bottom: 0;
+}
+
+.home-example {
+ display: grid;
+ gap: 1.5rem;
+ grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
+}
+
+.home-example pre {
+ margin: 0;
+}
+
@media (max-width: 900px) {
.layout {
grid-template-columns: 1fr;
@@ -467,7 +560,12 @@ button:disabled {
border-right: 0;
max-height: 260px;
}
- .playground-shell {
+ .playground-shell,
+ .home-grid,
+ .home-example {
grid-template-columns: 1fr;
}
+ .hero {
+ padding-top: 3rem;
+ }
}