Tools — page template

Use PortalLayout, never StarlightPage

Every tool page in this folder MUST use PortalLayout. See /CLAUDE.md (“Portal pages vs. Starlight”) for the full rule and the reasoning.

Template

Copy this when starting a new tool page (e.g. /tools/my-tool.astro):

---
import PortalLayout from "../../layouts/PortalLayout.astro";
import MyTool from "../../components/tools/MyTool";
import { getUserAskTier } from "../../lib/access";
import { normalizeTierSlug } from "../../lib/tiers";

const auth = Astro.locals.auth?.();
if (!auth?.userId) {
  return Astro.redirect("/sign-in?redirect_url=/tools/my-tool");
}
const tier = await getUserAskTier(auth);
const normalizedTier = normalizeTierSlug(tier);
if (!["principal", "team"].includes(normalizedTier)) {
  return Astro.redirect("/pricing?upgrade=principal");
}

const user = await Astro.locals.currentUser?.();
const firstName =
  user?.firstName ??
  user?.emailAddresses?.[0]?.emailAddress?.split("@")[0] ??
  null;
---

<PortalLayout
  title="My Tool"
  isSignedIn={true}
  normalizedTier={normalizedTier}
  firstName={firstName ?? undefined}
>
  <div class="tool-shell">
    <div class="tool-header">
      <a class="tool-back" href="/tools">← Tools</a>
      {/* No body <h1>: the page title is rendered in the top bar via the
          PortalLayout `title` prop, so a heading here is a redundant 2nd h1. */}
      <p class="tool-desc">Short description of what this tool does.</p>
    </div>

    <MyTool client:load />
  </div>
</PortalLayout>

<style>
  .tool-shell {
    max-width: 80rem;
    padding: 0.5rem 0 3rem;
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
  }
  .tool-header { display: flex; flex-direction: column; gap: 0.5rem; }
  .tool-back {
    font-family: var(--lp-font-mono);
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--lp-steel);
    text-decoration: none;
    width: max-content;
  }
  .tool-back:hover { color: var(--lp-text); }
  .tool-desc {
    margin: 0;
    font-size: 0.9rem;
    color: var(--lp-steel);
    line-height: 1.5;
    max-width: 56rem;
  }
</style>

Don’t forget the tools hub card

Add a corresponding entry to src/pages/tools.astro under the appropriate category group so the tool is discoverable.

Styling

Tool React components should use the portal CSS tokens (var(--lp-text), var(--lp-steel), var(--lp-border), var(--lp-indigo), etc.) so they feel native to the portal.