Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions site/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,18 @@ const site = process.env.SITE_URL ?? "http://localhost:4321";
const base = process.env.BASE_PATH ?? "/";
const outDir = base === "/" ? "./dist" : `./dist${base.replace(/\/$/, "")}`;

// The stable community link: the site and the README point at <site>/slack/,
// so a new Slack invite changes only this line.
const slackInvite = "https://join.slack.com/t/engramscommunity/shared_invite/zt-4bwkz6mfb-BAH7s00BtvA5FAMXZvgmUA";

export default defineConfig({
site,
base,
outDir,
trailingSlash: "always",
output: "static",
// A static host has no server redirects, so Astro writes a page that redirects at once.
redirects: { "/slack": slackInvite },
integrations: [
starlight({
title: "engrams",
Expand Down
7 changes: 7 additions & 0 deletions site/src/landing/copy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,13 @@ export const extensible = {
],
};

export const community = {
badge: "Sec. 6",
label: "Community",
title: "Join the community",
lede: "Join our Slack to chat directly with the engineers building engrams, get support on your software factory, and see what other teams are running in production.",
cta: { label: "Join the Slack" },
};

export const start = {
eyebrow: "Start with one task",
Expand Down
32 changes: 32 additions & 0 deletions site/src/layouts/Marketing.astro
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ const ogImage = new URL(`${base}/og.png`, Astro.site);
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script is:inline>
try {
if (localStorage.getItem("slack-banner-closed")) document.documentElement.classList.add("banner-closed");
} catch {}
</script>
<GoogleTagManager part="head" />
<title>{title}</title>
<meta name="description" content={description} />
Expand All @@ -54,6 +59,21 @@ const ogImage = new URL(`${base}/og.png`, Astro.site);
</head>
<body>
<GoogleTagManager part="body" />
<!-- The Slack banner scrolls away with the page. A visitor who closes it
does not see it again (the head script hides it before first paint). -->
<div class="banner" data-banner>
<div class="wrap">
<a href={`${base}/slack/`}>
<span class="tag">Community</span>
<span class="long">Join the engrams Slack: talk with the engineers who build it</span>
<span class="short">Join the engrams Slack</span>
<span aria-hidden="true">→</span>
</a>
<button class="close" type="button" aria-label="Close the Slack banner" data-banner-close>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18" /></svg>
</button>
</div>
</div>
<div class:list={["cover", "masthead", { landing }]}>
<div class="layer grid"></div>
<div class="layer scan"></div>
Expand Down Expand Up @@ -106,6 +126,7 @@ const ogImage = new URL(`${base}/og.png`, Astro.site);
<a href={`${base}/compare/`}>Compare</a>
<a href={`${base}/docs/`}>Docs</a>
<a href="https://github.com/cortexapps/engrams">GitHub</a>
<a href={`${base}/slack/`}>Join our Slack community</a>
</nav>
</div>
<div class="stripe"><span class="lime"></span><span class="amber"></span><span class="sage"></span><span></span></div>
Expand All @@ -115,10 +136,21 @@ const ogImage = new URL(`${base}/og.png`, Astro.site);
</html>

<script>
document.querySelector("[data-banner-close]")?.addEventListener("click", () => {
document.documentElement.classList.add("banner-closed");
try {
localStorage.setItem("slack-banner-closed", "1");
} catch {}
});

const toggle = document.querySelector<HTMLButtonElement>("[data-menu-toggle]");
const panel = document.getElementById("site-menu");
if (toggle && panel) {
const masthead = document.querySelector<HTMLElement>(".masthead");
const set = (open: boolean) => {
// The banner above the masthead can push it down, so the panel starts
// where the masthead ends now.
if (open && masthead) panel.style.top = `${masthead.getBoundingClientRect().bottom}px`;
toggle.setAttribute("aria-expanded", String(open));
panel.hidden = !open;
document.documentElement.classList.toggle("menu-open", open);
Expand Down
18 changes: 17 additions & 1 deletion site/src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import Marketing from "../layouts/Marketing.astro";
import TraceMark from "../components/TraceMark.astro";
import pelican from "../assets/screenshots/session-pelican.png";
import { hero, modules, slack, automations, how, session, extensible, start } from "../landing/copy";
import { hero, modules, slack, automations, how, session, extensible, community, start } from "../landing/copy";
import { nodes, edges, frame } from "../landing/demo";

const base = import.meta.env.BASE_URL.replace(/\/$/, "");
Expand Down Expand Up @@ -240,6 +240,22 @@ const code = (s: string) => s.replace(/`([^`]+)`/g, "<code>$1</code>");
</div>
</section>

<!-- SEC. 6 — COMMUNITY -->
<section class="sec">
<div class="wrap">
<div class="sec-head"><span class="sec-badge">{community.badge}</span><span>{community.label}</span><span class="sec-rule"></span></div>
<div class="sec-intro">
<h2 class="display">{community.title}</h2>
<div>
<p class="lede">{community.lede}</p>
<div class="actions">
<a class="btn outline" href={`${base}/slack/`}>{community.cta.label} <span>→</span></a>
</div>
</div>
</div>
</div>
</section>

<!-- START -->
<section class="cover start">
<div class="layer carbon bg-carbon-fade"></div>
Expand Down
81 changes: 79 additions & 2 deletions site/src/styles/marketing.css
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,70 @@ code {
background: var(--primary);
}

/* ---- Slack banner (above the masthead; scrolls away) ---- */
:root {
--banner-h: 40px;
}
html.banner-closed {
--banner-h: 0px;
}
html.banner-closed .banner {
display: none;
}
.banner {
box-sizing: border-box;
height: var(--banner-h);
/* A dark gap keeps the orange bar apart from the orange in the stripe below. */
border-bottom: 4px solid var(--panel-deep);
background: var(--amber);
color: var(--primary-foreground);
font-family: var(--font-mono);
font-size: 12px;
letter-spacing: 0.12em;
text-transform: uppercase;
}
.banner .wrap {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.banner a {
display: flex;
align-items: center;
gap: 14px;
white-space: nowrap;
}
.banner a:hover .long,
.banner a:hover .short {
text-decoration: underline;
text-underline-offset: 3px;
}
.banner .tag {
border: 1px solid currentColor;
padding: 1px 8px;
font-size: 10px;
}
.banner .short {
display: none;
}
.banner .close {
position: absolute;
right: 60px;
display: grid;
place-items: center;
width: 32px;
height: 32px;
border: 0;
background: transparent;
color: inherit;
cursor: pointer;
}
.banner .close svg {
width: 18px;
height: 18px;
}

/* ---- header ---- */
:root {
--masthead-h: 81px;
Expand Down Expand Up @@ -411,7 +475,7 @@ html.menu-open {
/* The cover fills the first screen under the masthead, so the floor grid
always meets the bottom of the window, whatever the hero's own height. */
.cover-hero {
min-height: calc(100svh - var(--masthead-h));
min-height: calc(100svh - var(--masthead-h) - var(--banner-h));
}
.hero {
display: grid;
Expand Down Expand Up @@ -1200,7 +1264,8 @@ html.menu-open {
}
.site-footer nav {
display: flex;
gap: 24px;
flex-wrap: wrap;
gap: 12px 24px;
}
.site-footer .stripe {
margin-top: 24px;
Expand Down Expand Up @@ -1558,6 +1623,18 @@ html.menu-open {
:root {
--masthead-h: 69px;
}
.banner .long {
display: none;
}
.banner .short {
display: inline;
}
.banner .tag {
display: none;
}
.banner .close {
right: 8px;
}
.site-header {
height: 64px;
}
Expand Down
Loading