mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-04 21:04:37 +08:00
Head tags
This commit is contained in:
parent
f1dec75d1e
commit
df2130d36a
@ -26,6 +26,8 @@ const config = {
|
||||
onBrokenLinks: "throw",
|
||||
onBrokenMarkdownLinks: "warn",
|
||||
|
||||
headTags: JSON.parse((console.log(process.env.STACK_HEAD_TAGS), process.env.STACK_HEAD_TAGS) || "[]"),
|
||||
|
||||
// Even if you don't use internationalization, you can use this field to set
|
||||
// useful metadata like html lang. For example, if your site is Chinese, you
|
||||
// may want to replace "en" with "zh-Hans".
|
||||
|
||||
@ -20,4 +20,7 @@ DIRECT_DATABASE_CONNECTION_STRING=# enter your direct (unpooled or session mode)
|
||||
|
||||
STACK_ACCESS_TOKEN_EXPIRATION_TIME=# enter the expiration time for the access token here
|
||||
|
||||
NEXT_PUBLIC_DOC_URL=http://localhost:8104
|
||||
NEXT_PUBLIC_STACK_HEAD_TAGS=[{ "tagName": "script", "attributes": {}, "innerHTML": "// insert head tags here" }]
|
||||
|
||||
NEXT_PUBLIC_DOC_URL=https://docs.stackframe.co
|
||||
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/analytics": "^1.2.2",
|
||||
"@emotion/react": "^11.11.3",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@mdx-js/loader": "^3",
|
||||
|
||||
@ -2,10 +2,13 @@ import type { Metadata } from 'next';
|
||||
import {GeistSans} from 'geist/font/sans';
|
||||
import {GeistMono} from "geist/font/mono";
|
||||
import { SnackbarProvider } from '@/hooks/use-snackbar';
|
||||
import { Analytics } from "@vercel/analytics/react";
|
||||
|
||||
import './globals.css';
|
||||
import ThemeProvider from '@/theme';
|
||||
import { StyleLink } from '@/components/style-link';
|
||||
import { getEnvVariable } from '@stackframe/stack-shared/dist/utils/env';
|
||||
import React from 'react';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
@ -15,17 +18,34 @@ export const metadata: Metadata = {
|
||||
description: 'Some frontend with auth built by N2D4',
|
||||
};
|
||||
|
||||
type TagConfigJson = {
|
||||
tagName: string,
|
||||
attributes: { [key: string]: string },
|
||||
innerHTML: string,
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode,
|
||||
}) {
|
||||
const headTags: TagConfigJson[] = JSON.parse(getEnvVariable('NEXT_PUBLIC_STACK_HEAD_TAGS'));
|
||||
|
||||
return (
|
||||
<html lang="en" className={`${GeistSans.variable} ${GeistMono.variable}`}>
|
||||
<head>
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||
<StyleLink href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded&display=block" />
|
||||
<StyleLink defer href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.css" integrity="sha384-OH8qNTHoMMVNVcKdKewlipV4SErXqccxxlg6HC9Cwjr5oZu2AdBej1TndeCirael" crossOrigin="anonymous" />
|
||||
|
||||
{headTags.map((tag, index) => {
|
||||
const { tagName, attributes, innerHTML } = tag;
|
||||
return React.createElement(tagName, {
|
||||
key: index,
|
||||
dangerouslySetInnerHTML: { __html: innerHTML ?? "" },
|
||||
...attributes,
|
||||
});
|
||||
})}
|
||||
</head>
|
||||
<body
|
||||
style={{
|
||||
@ -38,6 +58,7 @@ export default function RootLayout({
|
||||
fontFamily: '"Brush Script MT", "Zapfino", "Comic Sans MS", cursive',
|
||||
}}
|
||||
>
|
||||
<Analytics />
|
||||
<ThemeProvider>
|
||||
<SnackbarProvider>
|
||||
{children}
|
||||
|
||||
@ -1,8 +1,17 @@
|
||||
import { throwErr } from "./errors";
|
||||
import { deindent } from "./strings";
|
||||
|
||||
/**
|
||||
* Returns the environment variable with the given name, throwing an error if it's undefined or the empty string.
|
||||
*/
|
||||
export function getEnvVariable(name: string): string {
|
||||
if (typeof window !== 'undefined') {
|
||||
throw new Error(deindent`
|
||||
Can't use getEnvVariable on the client because Next.js transpiles expressions of the kind process.env.XYZ at build-time on the client.
|
||||
|
||||
Use process.env.XYZ directly instead.
|
||||
`);
|
||||
}
|
||||
|
||||
return (process.env[name] ?? throwErr(`Missing environment variable: ${name}`)) || throwErr(`Empty environment variable: ${name}`);
|
||||
}
|
||||
|
||||
@ -340,6 +340,9 @@ importers:
|
||||
'@types/mdx':
|
||||
specifier: ^2
|
||||
version: 2.0.11
|
||||
'@vercel/analytics':
|
||||
specifier: ^1.2.2
|
||||
version: 1.2.2(next@14.1.0)(react@18.2.0)
|
||||
bcrypt:
|
||||
specifier: ^5.1.1
|
||||
version: 5.1.1
|
||||
@ -6202,6 +6205,22 @@ packages:
|
||||
/@ungap/structured-clone@1.2.0:
|
||||
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
|
||||
|
||||
/@vercel/analytics@1.2.2(next@14.1.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-X0rctVWkQV1e5Y300ehVNqpOfSOufo7ieA5PIdna8yX/U7Vjz0GFsGf4qvAhxV02uQ2CVt7GYcrFfddXXK2Y4A==}
|
||||
peerDependencies:
|
||||
next: '>= 13'
|
||||
react: ^18 || ^19
|
||||
peerDependenciesMeta:
|
||||
next:
|
||||
optional: true
|
||||
react:
|
||||
optional: true
|
||||
dependencies:
|
||||
next: 14.1.0(react-dom@18.2.0)(react@18.2.0)
|
||||
react: 18.2.0
|
||||
server-only: 0.0.1
|
||||
dev: false
|
||||
|
||||
/@vitest/expect@1.2.2:
|
||||
resolution: {integrity: sha512-3jpcdPAD7LwHUUiT2pZTj2U82I2Tcgg2oVPvKxhn6mDI2On6tfvPQTjAI4628GUGDZrCm4Zna9iQHm5cEexOAg==}
|
||||
dependencies:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user