Merge branch 'cl/romantic-mendel-5a2c25' into cl/hexclave-pr3
BIN
.github/assets/hexclave-rebrand-modal.png
vendored
Normal file
|
After Width: | Height: | Size: 114 KiB |
26
apps/dashboard/public/hexclave-icon.svg
Normal file
@ -0,0 +1,26 @@
|
||||
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="neon-grad" x1="4" y1="4" x2="44" y2="44" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0%" stop-color="#00FFFF" />
|
||||
<stop offset="50%" stop-color="#3B82F6" />
|
||||
<stop offset="100%" stop-color="#8B5CF6" />
|
||||
</linearGradient>
|
||||
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
|
||||
<feGaussianBlur stdDeviation="1.5" result="blur1" />
|
||||
<feGaussianBlur stdDeviation="3.5" result="blur2" />
|
||||
<feMerge>
|
||||
<feMergeNode in="blur2" />
|
||||
<feMergeNode in="blur1" />
|
||||
<feMergeNode in="SourceGraphic" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
<g id="benzene-mark">
|
||||
<path d="M 24 4 L 41.32 14 L 41.32 34 L 24 44 L 6.68 34 L 6.68 14 Z" fill="none" stroke="url(#neon-grad)" stroke-width="3" stroke-linejoin="miter" />
|
||||
<path d="M 11 16.87 L 14 15.13 L 14 32.87 L 11 31.13 Z" fill="url(#neon-grad)" />
|
||||
<path d="M 11 16.87 L 14 15.13 L 14 32.87 L 11 31.13 Z" fill="url(#neon-grad)" transform="rotate(120 24 24)" />
|
||||
<path d="M 11 16.87 L 14 15.13 L 14 32.87 L 11 31.13 Z" fill="url(#neon-grad)" transform="rotate(240 24 24)" />
|
||||
</g>
|
||||
</defs>
|
||||
<use href="#benzene-mark" filter="url(#glow)" opacity="0.75" />
|
||||
<use href="#benzene-mark" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@ -1,3 +1,26 @@
|
||||
<svg width="131" height="156" viewBox="0 0 131 156" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M124.042 28.6459L69.7327 1.75616C66.9416 0.374284 63.666 0.372197 60.8735 1.75051L0.335449 31.6281V87.6369L65.3045 119.91L117.154 93.675V112.414L65.3045 138.44L0.335449 106.584V119.655C0.335449 122.359 1.87599 124.827 4.30545 126.015L61.8765 154.161C64.6911 155.538 67.9883 155.515 70.7832 154.099L130.065 124.074V79.7105C130.065 74.8003 124.934 71.5769 120.51 73.7077L79.0476 93.675V75.9771L130.065 50.1589V38.3485C130.065 34.2325 127.731 30.4724 124.042 28.6459Z" fill="white"/>
|
||||
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg" aria-label="Hexclave">
|
||||
<defs>
|
||||
<linearGradient id="neon-grad" x1="4" y1="4" x2="44" y2="44" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0%" stop-color="#00FFFF" />
|
||||
<stop offset="50%" stop-color="#3B82F6" />
|
||||
<stop offset="100%" stop-color="#8B5CF6" />
|
||||
</linearGradient>
|
||||
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
|
||||
<feGaussianBlur stdDeviation="1.5" result="blur1" />
|
||||
<feGaussianBlur stdDeviation="3.5" result="blur2" />
|
||||
<feMerge>
|
||||
<feMergeNode in="blur2" />
|
||||
<feMergeNode in="blur1" />
|
||||
<feMergeNode in="SourceGraphic" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
<g id="benzene-mark">
|
||||
<path d="M 24 4 L 41.32 14 L 41.32 34 L 24 44 L 6.68 34 L 6.68 14 Z" fill="none" stroke="url(#neon-grad)" stroke-width="3" stroke-linejoin="miter" />
|
||||
<path d="M 11 16.87 L 14 15.13 L 14 32.87 L 11 31.13 Z" fill="url(#neon-grad)" />
|
||||
<path d="M 11 16.87 L 14 15.13 L 14 32.87 L 11 31.13 Z" fill="url(#neon-grad)" transform="rotate(120 24 24)" />
|
||||
<path d="M 11 16.87 L 14 15.13 L 14 32.87 L 11 31.13 Z" fill="url(#neon-grad)" transform="rotate(240 24 24)" />
|
||||
</g>
|
||||
</defs>
|
||||
<use href="#benzene-mark" filter="url(#glow)" opacity="0.75" />
|
||||
<use href="#benzene-mark" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 597 B After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 1.5 KiB |
@ -1,3 +1,26 @@
|
||||
<svg width="131" height="156" viewBox="0 0 131 156" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M124.447 28.6459L70.1382 1.75616C67.3472 0.374284 64.0715 0.372197 61.279 1.75051L0.740967 31.6281V87.6369L65.7101 119.91L117.56 93.675V112.414L65.7101 138.44L0.740967 106.584V119.655C0.740967 122.359 2.28151 124.827 4.71097 126.015L62.282 154.161C65.0966 155.538 68.3938 155.515 71.1888 154.099L130.47 124.074V79.7105C130.47 74.8003 125.34 71.5769 120.915 73.7077L79.4531 93.675V75.9771L130.47 50.1589V38.3485C130.47 34.2325 128.137 30.4724 124.447 28.6459Z" fill="black"/>
|
||||
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg" aria-label="Hexclave">
|
||||
<defs>
|
||||
<linearGradient id="neon-grad" x1="4" y1="4" x2="44" y2="44" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0%" stop-color="#00FFFF" />
|
||||
<stop offset="50%" stop-color="#3B82F6" />
|
||||
<stop offset="100%" stop-color="#8B5CF6" />
|
||||
</linearGradient>
|
||||
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
|
||||
<feGaussianBlur stdDeviation="1.5" result="blur1" />
|
||||
<feGaussianBlur stdDeviation="3.5" result="blur2" />
|
||||
<feMerge>
|
||||
<feMergeNode in="blur2" />
|
||||
<feMergeNode in="blur1" />
|
||||
<feMergeNode in="SourceGraphic" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
<g id="benzene-mark">
|
||||
<path d="M 24 4 L 41.32 14 L 41.32 34 L 24 44 L 6.68 34 L 6.68 14 Z" fill="none" stroke="url(#neon-grad)" stroke-width="3" stroke-linejoin="miter" />
|
||||
<path d="M 11 16.87 L 14 15.13 L 14 32.87 L 11 31.13 Z" fill="url(#neon-grad)" />
|
||||
<path d="M 11 16.87 L 14 15.13 L 14 32.87 L 11 31.13 Z" fill="url(#neon-grad)" transform="rotate(120 24 24)" />
|
||||
<path d="M 11 16.87 L 14 15.13 L 14 32.87 L 11 31.13 Z" fill="url(#neon-grad)" transform="rotate(240 24 24)" />
|
||||
</g>
|
||||
</defs>
|
||||
<use href="#benzene-mark" filter="url(#glow)" opacity="0.75" />
|
||||
<use href="#benzene-mark" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 591 B After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 148 KiB |
@ -3,6 +3,7 @@
|
||||
import Loading from "@/app/loading";
|
||||
import { CursorBlastEffect } from "@hexclave/dashboard-ui-components";
|
||||
import { ConfigUpdateDialogProvider } from "@/lib/config-update";
|
||||
import { HexclaveRebrandModal } from "@/components/hexclave-rebrand-modal";
|
||||
import { getPublicEnvVar } from '@/lib/env';
|
||||
import { useStackApp, useUser } from "@hexclave/next";
|
||||
import { LOCAL_EMULATOR_ADMIN_EMAIL, LOCAL_EMULATOR_ADMIN_PASSWORD } from "@hexclave/shared/dist/local-emulator";
|
||||
@ -60,6 +61,7 @@ export default function LayoutClient({ children }: { children: React.ReactNode }
|
||||
return (
|
||||
<ConfigUpdateDialogProvider>
|
||||
<CursorBlastEffect />
|
||||
<HexclaveRebrandModal />
|
||||
{children}
|
||||
</ConfigUpdateDialogProvider>
|
||||
);
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 10 KiB |
207
apps/dashboard/src/components/hexclave-rebrand-modal.tsx
Normal file
@ -0,0 +1,207 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { getPublicEnvVar } from "@/lib/env";
|
||||
import { useUser } from "@stackframe/stack";
|
||||
import Image from "next/image";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
// Per-user dismissal flag. Keyed by user.id so a shared browser (e.g. a
|
||||
// machine where two teammates each log into their own accounts) tracks the
|
||||
// dismissal separately for each account — otherwise one teammate dismissing
|
||||
// would silently hide the announcement from the other.
|
||||
const STORAGE_KEY_PREFIX = "hexclave-rebrand-modal-dismissed:";
|
||||
const MIGRATION_DOCS_URL = "https://docs.hexclave.com/migration";
|
||||
|
||||
// Users who signed up before this instant predate the Stack Auth → Hexclave
|
||||
// rebrand and are the only ones who benefit from the announcement. Anyone
|
||||
// signing up after this already lands on a Hexclave-branded experience and
|
||||
// has no "Stack Auth" mental model to update — no point telling them.
|
||||
const REBRAND_CUTOFF = new Date("2026-05-27T00:00:00.000Z");
|
||||
|
||||
/**
|
||||
* One-time informational modal announcing the Stack Auth → Hexclave rebrand.
|
||||
*
|
||||
* Skipped entirely in preview / local-emulator / remote-development environments
|
||||
* — those auto-create throwaway users or seed a fixture admin, so the rebrand
|
||||
* notice would be friction for developers and meaningless for preview visitors
|
||||
* who never used "Stack Auth" in the first place.
|
||||
*
|
||||
* For real customers: only renders for a logged-in user who signed up before
|
||||
* {@link REBRAND_CUTOFF}. On any dismissal (confirm button, close button,
|
||||
* overlay click, or Escape) writes `${STORAGE_KEY_PREFIX}${user.id}` to
|
||||
* localStorage so the modal never re-appears for that account on that browser.
|
||||
*/
|
||||
export function HexclaveRebrandModal() {
|
||||
// Skip in dev/preview environments — same flags the protected layout already
|
||||
// gates on. Read at top so we can short-circuit before any hook runs the
|
||||
// useEffect or computes the user-based gate.
|
||||
const isDevEnvironment =
|
||||
getPublicEnvVar("NEXT_PUBLIC_STACK_IS_LOCAL_EMULATOR") === "true"
|
||||
|| getPublicEnvVar("NEXT_PUBLIC_STACK_IS_REMOTE_DEVELOPMENT_ENVIRONMENT") === "true"
|
||||
|| getPublicEnvVar("NEXT_PUBLIC_STACK_IS_PREVIEW") === "true";
|
||||
|
||||
// `or: "return-null"` keeps this from triggering the sign-in redirect when
|
||||
// it's rendered above the auth boundary — we simply opt out for guests.
|
||||
const user = useUser({ or: "return-null" });
|
||||
const isPreRebrandUser =
|
||||
!isDevEnvironment && user != null && user.signedUpAt < REBRAND_CUTOFF;
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
// Per-user storage key. `null` when there's no user; the gates below
|
||||
// ensure we never try to read/write it in that case.
|
||||
const storageKey = user ? `${STORAGE_KEY_PREFIX}${user.id}` : null;
|
||||
|
||||
// Read localStorage after hydration to avoid SSR mismatch — render closed
|
||||
// on the server and only open if we know this user hasn't dismissed it.
|
||||
useEffect(() => {
|
||||
if (!isPreRebrandUser || !storageKey) return;
|
||||
try {
|
||||
const dismissed = localStorage.getItem(storageKey);
|
||||
if (dismissed !== "true") {
|
||||
setOpen(true);
|
||||
}
|
||||
} catch {
|
||||
// localStorage can throw in private-mode / sandboxed iframes; treat
|
||||
// unavailable storage as "already dismissed" so we don't spam users
|
||||
// who can't persist the dismissal anyway.
|
||||
}
|
||||
}, [isPreRebrandUser, storageKey]);
|
||||
|
||||
const dismiss = () => {
|
||||
if (storageKey) {
|
||||
try {
|
||||
localStorage.setItem(storageKey, "true");
|
||||
} catch {
|
||||
// see above — best-effort write
|
||||
}
|
||||
}
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
if (!isPreRebrandUser) return null;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={open}
|
||||
onOpenChange={(next) => {
|
||||
if (!next) dismiss();
|
||||
}}
|
||||
>
|
||||
<DialogContent className="max-w-md">
|
||||
<DialogHeader>
|
||||
<RebrandIllustration />
|
||||
<DialogTitle className="text-center text-xl pt-2">
|
||||
Stack Auth is now Hexclave
|
||||
</DialogTitle>
|
||||
<DialogDescription className="text-center">
|
||||
We're rebranding! Same product, same team, new home at{" "}
|
||||
<a
|
||||
href="https://app.hexclave.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="font-medium underline underline-offset-2 hover:text-foreground"
|
||||
>
|
||||
app.hexclave.com
|
||||
</a>
|
||||
. To update your project, rename all{" "}
|
||||
<code className="font-mono text-xs">@stackframe/*</code> imports to{" "}
|
||||
<code className="font-mono text-xs">@hexclave/*</code> — the only
|
||||
exception is{" "}
|
||||
<code className="font-mono text-xs">@stackframe/stack</code>, which
|
||||
becomes <code className="font-mono text-xs">@hexclave/next</code>.
|
||||
See the{" "}
|
||||
<a
|
||||
href={MIGRATION_DOCS_URL}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="underline underline-offset-2 hover:text-foreground"
|
||||
>
|
||||
migration guide
|
||||
</a>{" "}
|
||||
for full details.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter className="sm:justify-center pt-6">
|
||||
<Button onClick={dismiss} className="min-w-32">
|
||||
Got it
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stack Auth mark (faded) → arrow → Hexclave benzene mark. Both logos are
|
||||
* served from `/public` so they match the canonical brand assets.
|
||||
*/
|
||||
function RebrandIllustration() {
|
||||
return (
|
||||
<div
|
||||
className="flex justify-center items-center gap-4 pb-2"
|
||||
aria-hidden="true"
|
||||
>
|
||||
{/* Stack Auth: served light & dark variants depending on theme */}
|
||||
<Image
|
||||
src="/logo.svg"
|
||||
alt=""
|
||||
width={48}
|
||||
height={48}
|
||||
aria-hidden
|
||||
className="h-12 w-auto opacity-50 block dark:hidden"
|
||||
/>
|
||||
<Image
|
||||
src="/logo-bright.svg"
|
||||
alt=""
|
||||
width={48}
|
||||
height={48}
|
||||
aria-hidden
|
||||
className="h-12 w-auto opacity-60 hidden dark:block"
|
||||
/>
|
||||
|
||||
{/* Arrow — bridge between the two marks */}
|
||||
<svg
|
||||
width="40"
|
||||
height="14"
|
||||
viewBox="0 0 40 14"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="text-muted-foreground"
|
||||
>
|
||||
<path
|
||||
d="M2 7 L34 7"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
<path
|
||||
d="M28 1 L34 7 L28 13"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
fill="none"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
{/* Hexclave benzene mark — gradient + glow filter, theme-agnostic */}
|
||||
<Image
|
||||
src="/hexclave-icon.svg"
|
||||
alt=""
|
||||
width={56}
|
||||
height={56}
|
||||
aria-hidden
|
||||
className="h-14 w-14"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
Before Width: | Height: | Size: 318 B After Width: | Height: | Size: 10 KiB |
@ -154,7 +154,7 @@
|
||||
{
|
||||
"group": "Tutorials",
|
||||
"pages": [
|
||||
"guides/other/tutorials/build-a-saas-with-stack-auth",
|
||||
"guides/other/tutorials/build-a-saas-with-hexclave",
|
||||
"guides/other/tutorials/build-a-team-based-app",
|
||||
"guides/other/tutorials/ship-production-ready-auth"
|
||||
]
|
||||
|
||||
@ -5,7 +5,7 @@ description: Model B2B tenants as teams, wire team selection and deep links, enf
|
||||
|
||||
This tutorial walks through a **multi-tenant** product where a **team** is the customer boundary (workspace, organization, account). You get membership-scoped team access, permission checks, team selection UX, and invitations.
|
||||
|
||||
If you have not installed Stack yet (handler routes, `HexclaveProvider`, environment variables), start with [Build a SaaS with Hexclave](/guides/other/tutorials/build-a-saas-with-stack-auth), then continue here.
|
||||
If you have not installed Stack yet (handler routes, `HexclaveProvider`, environment variables), start with [Build a SaaS with Hexclave](/guides/other/tutorials/build-a-saas-with-hexclave), then continue here.
|
||||
|
||||
## What you will have at the end
|
||||
|
||||
@ -17,7 +17,7 @@ If you have not installed Stack yet (handler routes, `HexclaveProvider`, environ
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Hexclave installed as in [Build a SaaS with Hexclave](/guides/other/tutorials/build-a-saas-with-stack-auth) (Next.js App Router examples below assume `stackServerApp` in `stack/server.ts` and `@hexclave/next` in the app).
|
||||
- Hexclave installed as in [Build a SaaS with Hexclave](/guides/other/tutorials/build-a-saas-with-hexclave) (Next.js App Router examples below assume `stackServerApp` in `stack/server.ts` and `@hexclave/next` in the app).
|
||||
- A project in the [dashboard](https://app.hexclave.com/projects) where you can edit **Teams** and **Team permissions**.
|
||||
|
||||
<Note>
|
||||
@ -356,7 +356,7 @@ Teams support `clientMetadata`, `serverMetadata`, and `clientReadOnlyMetadata` o
|
||||
|
||||
| Topic | Guide |
|
||||
|--------|--------|
|
||||
| Auth bootstrap and route protection | [Build a SaaS with Hexclave](/guides/other/tutorials/build-a-saas-with-stack-auth) |
|
||||
| Auth bootstrap and route protection | [Build a SaaS with Hexclave](/guides/other/tutorials/build-a-saas-with-hexclave) |
|
||||
| Teams API reference | [Teams](/guides/apps/teams/overview) |
|
||||
| `SelectedTeamSwitcher` and URL strategies | [Team selection](/guides/apps/teams/team-selection) |
|
||||
| Permission modeling and nesting | [RBAC](/guides/apps/rbac/overview) |
|
||||
|
||||
@ -5,7 +5,7 @@ description: Lock down page and API access, handle secrets and environments, the
|
||||
|
||||
Going live is not only “turning on production mode.” This guide focuses on **what must be true** so only signed-in users reach protected surfaces, **secrets stay server-only**, and Stack’s dev-friendly defaults are replaced with **your** domains, OAuth apps, and email.
|
||||
|
||||
If you are still wiring Stack into your app, complete [Build a SaaS with Hexclave](/guides/other/tutorials/build-a-saas-with-stack-auth) first. For team RBAC before launch, see [Build a team-based app](/guides/other/tutorials/build-a-team-based-app).
|
||||
If you are still wiring Stack into your app, complete [Build a SaaS with Hexclave](/guides/other/tutorials/build-a-saas-with-hexclave) first. For team RBAC before launch, see [Build a team-based app](/guides/other/tutorials/build-a-team-based-app).
|
||||
|
||||
## What you will have at the end
|
||||
|
||||
@ -153,7 +153,7 @@ If you consume Stack webhooks, **verify every payload** (for example with Svix a
|
||||
|
||||
| Topic | Guide |
|
||||
|--------|--------|
|
||||
| First integration | [Build a SaaS with Hexclave](/guides/other/tutorials/build-a-saas-with-stack-auth) |
|
||||
| First integration | [Build a SaaS with Hexclave](/guides/other/tutorials/build-a-saas-with-hexclave) |
|
||||
| Page protection details | [User fundamentals](/guides/getting-started/user-fundamentals) |
|
||||
| Domains, OAuth, email, prod mode | [Launch checklist](/guides/apps/launch-checklist/overview) |
|
||||
| `HexclaveServerApp` and keys | [Stack App](/guides/going-further/stack-app) |
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 1.3 KiB |
@ -7,8 +7,8 @@ import { stackServerApp } from "src/stack";
|
||||
import './global.css';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Stack Demo',
|
||||
description: 'Example of using Stack as your authentication system.',
|
||||
title: 'Hexclave Demo',
|
||||
description: 'Example of using Hexclave as your authentication system.',
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
|
||||
@ -17,7 +17,6 @@ export default function Header() {
|
||||
alt="Hexclave Logo"
|
||||
width={64}
|
||||
height={64}
|
||||
className="dark:invert"
|
||||
/>
|
||||
Demo
|
||||
</Link>
|
||||
|
||||
@ -8,8 +8,8 @@ import './global.css';
|
||||
const inter = Inter({ subsets: ['latin'] });
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Stack Demo',
|
||||
description: 'Example of using Stack as your authentication system.',
|
||||
title: 'Hexclave Docs Example',
|
||||
description: 'Example of using Hexclave as your authentication system.',
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
|
||||
@ -7,7 +7,7 @@ const inter = Inter({ subsets: ["latin"] });
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Hexclave Middleware Demo",
|
||||
description: "A demo of Stack's middleware capabilities.",
|
||||
description: "A demo of Hexclave's middleware capabilities.",
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
|
||||
@ -8,7 +8,7 @@ export function Header() {
|
||||
<div className="mx-auto flex h-14 max-w-5xl items-center justify-between gap-4">
|
||||
<nav className="flex items-center gap-4">
|
||||
<Link to="/" className="font-semibold tracking-tight">
|
||||
Stack TanStack Demo
|
||||
Hexclave TanStack Demo
|
||||
</Link>
|
||||
<Link to="/ssr" className="text-sm text-zinc-600 hover:text-zinc-950 hover:transition-none dark:text-zinc-300 dark:hover:text-white">
|
||||
SSR
|
||||
|
||||