a homebrewed DnD campaign based in the Honkai: Star Rail universe
hsr honkaistarrail dnd
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

use PageMeta component everywhere

+90 -73
+3
app/.env.example
··· 1 + # Site 2 + PUBLIC_SITE_DESCRIPTION= 3 + 1 4 # Resend 2 5 RESEND_KEY= 3 6 CONTACT_ADDRESS=
+3 -12
app/src/lib/PageMeta.svelte app/src/lib/page-meta/PageMeta.svelte
··· 1 1 <script lang="ts"> 2 - import { pageTitle } from './utils' 2 + import { PUBLIC_SITE_DESCRIPTION } from '$env/static/public' 3 + import { pageTitle, type PageMeta } from '$lib/utils' 3 4 import { page } from '$app/state' 4 5 5 - type PageMetaProps = { 6 - title?: string, 7 - description: string, 8 - url?: string, 9 - robots?: { 10 - nofollow?: boolean, 11 - noindex?: boolean, 12 - noimageindex?: boolean, 13 - }, 14 - } 15 - let { title, description, robots }: PageMetaProps = $props() 6 + let { title, description = PUBLIC_SITE_DESCRIPTION, robots }: PageMeta = $props() 16 7 let htmlTitle = $derived(pageTitle(title)) 17 8 let htmlUrl = $derived(page.url.toString()) 18 9 let htmlRobots = $derived.by(() => {
+1
app/src/lib/page-meta/index.ts
··· 1 + export { default as PageMeta } from './PageMeta.svelte'
+16 -1
app/src/lib/utils.ts
··· 1 1 import { clsx, type ClassValue } from 'clsx' 2 2 import { twMerge } from 'tailwind-merge' 3 3 4 + export type PageMeta = { 5 + title?: string 6 + description?: string 7 + url?: string 8 + robots?: { 9 + nofollow?: boolean 10 + noindex?: boolean 11 + noimageindex?: boolean 12 + } 13 + } 14 + 15 + export function definePageMeta(options: PageMeta): PageMeta { 16 + return options 17 + } 18 + 4 19 /** 5 20 * Generates a consistent, human-readable page title 6 21 * intended for within a `<title>` element. 7 22 */ 8 - export const pageTitle = (title?: string) => { 23 + export function pageTitle(title?: string): string { 9 24 const prefix = 'The Drifting Starlight' 10 25 const separator = '\u2022' 11 26
+4 -4
app/src/routes/(app)/abilities/+page.server.ts
··· 1 1 import type { AbilityCardProps } from '$patterns/ability-card/AbilityCard.svelte' 2 - import { pageTitle } from '$lib/utils' 2 + import { definePageMeta } from '$lib/utils' 3 3 import type { PageServerLoad } from './$types' 4 4 5 5 const abilities: AbilityCardProps[] = [ ··· 52 52 53 53 export const load: PageServerLoad = async () => { 54 54 return { 55 - meta: { 56 - pageTitle: pageTitle('Combat'), 57 - }, 55 + meta: definePageMeta({ 56 + title: 'Combat', 57 + }), 58 58 abilities: abilities, 59 59 } 60 60 }
+3 -2
app/src/routes/(app)/abilities/+page.svelte
··· 1 1 <script lang="ts"> 2 + import { PageMeta } from '$lib/page-meta' 2 3 import { AbilityCard } from '$patterns/ability-card' 3 4 import { Checkbox } from '$ui/checkbox' 4 5 import { PageLayout } from '$ui/site' 5 6 import type { PageProps } from './$types' 6 7 7 8 let { data }: PageProps = $props() 8 - const { meta: { pageTitle }, abilities } = $derived(data) 9 + const { meta, abilities } = $derived(data) 9 10 10 11 let offensive = $state<string[]>([]) 11 12 let defensive = $state<string[]>([]) ··· 19 20 </script> 20 21 21 22 <svelte:head> 22 - <title>{pageTitle}</title> 23 + <PageMeta {...meta} /> 23 24 </svelte:head> 24 25 25 26 <PageLayout
+4 -4
app/src/routes/(app)/campaigns/new/+page.server.ts
··· 1 - import { pageTitle } from '$lib/utils' 1 + import { definePageMeta } from '$lib/utils' 2 2 import type { PageServerLoad } from './$types' 3 3 4 4 export const load: PageServerLoad = async () => { 5 5 return { 6 - meta: { 7 - pageTitle: pageTitle('Create a new campaign'), 8 - }, 6 + meta: definePageMeta({ 7 + title: 'Create a new campaign', 8 + }), 9 9 } 10 10 }
+3 -2
app/src/routes/(app)/campaigns/new/+page.svelte
··· 1 1 <script lang="ts"> 2 + import { PageMeta } from '$lib/page-meta' 2 3 import { Button } from '$ui/button' 3 4 import { Field } from '$ui/field' 4 5 import { Heading, HeadingGroup, SubHeading } from '$ui/heading' ··· 7 8 import type { PageProps } from './$types' 8 9 9 10 let { data }: PageProps = $props() 10 - const { meta: { pageTitle } } = $derived(data) 11 + const { meta } = $derived(data) 11 12 </script> 12 13 13 14 <svelte:head> 14 - <title>{pageTitle}</title> 15 + <PageMeta {...meta} /> 15 16 </svelte:head> 16 17 17 18 <PageLayout display="flex" direction="col" class="gap-8 mx-auto" items="stretch">
+4 -4
app/src/routes/(app)/classes/new/+page.server.ts
··· 1 - import { pageTitle } from '$lib/utils' 1 + import { definePageMeta } from '$lib/utils' 2 2 import { AbilityAbbrArray, getAbilityDesc, getAbilityName } from '@starlight/types/dnd' 3 3 import type { PageServerLoad } from './$types' 4 4 5 5 export const load: PageServerLoad = async () => { 6 6 return { 7 - meta: { 8 - pageTitle: pageTitle('Register a new class'), 9 - }, 7 + meta: definePageMeta({ 8 + title: 'Register a new class', 9 + }), 10 10 abilities: AbilityAbbrArray.map((ability) => ({ 11 11 title: getAbilityName(ability), 12 12 desc: getAbilityDesc(ability),
+3 -2
app/src/routes/(app)/classes/new/+page.svelte
··· 1 1 <script lang="ts"> 2 + import { PageMeta } from '$lib/page-meta'; 2 3 import { Checkbox } from '$ui/checkbox' 3 4 import { Field } from '$ui/field' 4 5 import { HeadingGroup, Heading, SubHeading } from '$ui/heading' ··· 8 9 import type { PageProps } from './$types' 9 10 10 11 let { data }: PageProps = $props() 11 - const { meta: { pageTitle }, abilities } = $derived(data) 12 + const { meta, abilities } = $derived(data) 12 13 </script> 13 14 14 15 <svelte:head> 15 - <title>{pageTitle}</title> 16 + <PageMeta {...meta } /> 16 17 </svelte:head> 17 18 18 19 <PageLayout display="flex" direction="col" class="gap-8" items="stretch">
+4 -4
app/src/routes/(app)/species/new/+page.server.ts
··· 1 - import { pageTitle } from '$lib/utils' 1 + import { definePageMeta } from '$lib/utils' 2 2 import { getAbilityName, getAbilityDesc, AbilityAbbrArray } from '@starlight/types/dnd' 3 3 import type { PageServerLoad } from './$types' 4 4 5 5 export const load: PageServerLoad = async () => { 6 6 return { 7 - meta: { 8 - pageTitle: pageTitle('Register a new species'), 9 - }, 7 + meta: definePageMeta({ 8 + title: 'Register a new species', 9 + }), 10 10 abilities: AbilityAbbrArray.map((ability) => ({ 11 11 title: getAbilityName(ability), 12 12 desc: getAbilityDesc(ability),
+4 -4
app/src/routes/(app)/species/new/+page.svelte
··· 1 1 <script lang="ts"> 2 - import type { WithChildren } from 'bits-ui' 2 + import { PageMeta } from '$lib/page-meta' 3 3 import { Button } from '$ui/button' 4 4 import { Checkbox } from '$ui/checkbox' 5 5 import { Field } from '$ui/field' ··· 9 9 import { TextInput, TextAreaInput } from '$ui/text-input' 10 10 import type { PageProps } from './$types' 11 11 12 - type SpeciesNewProps = WithChildren<PageProps> 12 + type SpeciesNewProps = PageProps 13 13 let { data }: SpeciesNewProps = $props() 14 - const { meta: { pageTitle }, abilities } = $derived(data) 14 + const { meta, abilities } = $derived(data) 15 15 16 16 const movementSpeed = $state({ 17 17 walk: 30, ··· 23 23 </script> 24 24 25 25 <svelte:head> 26 - <title>{pageTitle}</title> 26 + <PageMeta {...meta} /> 27 27 </svelte:head> 28 28 29 29 <PageLayout display="flex" direction="col" class="gap-8 mx-auto" items="stretch">
+4 -4
app/src/routes/(auth)/reset-password/+page.server.ts
··· 1 - import { pageTitle } from '$lib/utils' 1 + import { definePageMeta } from '$lib/utils' 2 2 import { auth } from '$server/auth' 3 3 import { zChangePassword, zResetPassword } from '$server/schemas/auth' 4 4 import { fail } from '@sveltejs/kit' ··· 8 8 9 9 export const load: PageServerLoad = async () => { 10 10 return { 11 + meta: definePageMeta({ 12 + title: 'Reset your password', 13 + }), 11 14 form: await superValidate(zod4(zResetPassword)), 12 - meta: { 13 - pageTitle: pageTitle('Reset your password'), 14 - }, 15 15 } 16 16 } 17 17
+4 -4
app/src/routes/(auth)/reset-password/+page.svelte
··· 1 1 <script lang="ts"> 2 - import type { WithChildren } from 'bits-ui' 3 2 import { untrack } from 'svelte' 4 3 import { superForm } from 'sveltekit-superforms' 4 + import { PageMeta } from '$lib/page-meta' 5 5 import { Button, LinkButton } from '$ui/button' 6 6 import { Field } from '$ui/field' 7 7 import { FormHeader } from '$ui/form' ··· 9 9 import type { PageProps } from './$types' 10 10 import { AuthPageLayout } from '../components' 11 11 12 - type ResetPasswordProps = WithChildren<PageProps> 12 + type ResetPasswordProps = PageProps 13 13 let { data }: ResetPasswordProps = $props() 14 14 15 - const { meta: { pageTitle } } = $derived(data) 15 + const { meta } = $derived(data) 16 16 const { form, errors, constraints, enhance } = superForm(untrack(() => data.form)) 17 17 </script> 18 18 19 19 <svelte:head> 20 - <title>{pageTitle}</title> 20 + <PageMeta { ...meta } /> 21 21 </svelte:head> 22 22 23 23 <AuthPageLayout>
+4 -4
app/src/routes/(auth)/signin/+page.server.ts
··· 1 - import { pageTitle } from '$lib/utils' 1 + import { definePageMeta } from '$lib/utils' 2 2 import { auth } from '$server/auth' 3 3 import { db } from '$server/db' 4 4 import { AuthRepository } from '$server/db/repos/auth' ··· 11 11 export const load: PageServerLoad = async () => { 12 12 return { 13 13 form: await superValidate(zod4(zSignIn)), 14 - meta: { 15 - pageTitle: pageTitle('Sign in'), 16 - }, 14 + meta: definePageMeta({ 15 + title: 'Sign in', 16 + }), 17 17 } 18 18 } 19 19
+5 -5
app/src/routes/(auth)/signin/+page.svelte
··· 1 1 <script lang="ts"> 2 2 import LogInIcon from '@lucide/svelte/icons/log-in' 3 - import type { WithChildren } from 'bits-ui' 4 3 import { untrack } from 'svelte' 5 4 import { superForm } from 'sveltekit-superforms' 6 5 import { goto } from '$app/navigation' 7 6 import { resolve } from '$app/paths' 7 + import { PageMeta } from '$lib/page-meta' 8 8 import { Button } from '$ui/button' 9 9 import { Callout } from '$ui/callout' 10 10 import { Field } from '$ui/field' 11 11 import { Link } from '$ui/link' 12 12 import { TextInput, PasswordInput } from '$ui/text-input' 13 + import { AuthHeader, AuthFooter, AuthPageLayout } from '../components' 13 14 import type { PageProps } from './$types' 14 - import { AuthHeader, AuthFooter, AuthPageLayout } from '../components' 15 15 16 - type SignInProps = WithChildren<PageProps> 16 + type SignInProps = PageProps 17 17 let { data }: SignInProps = $props() 18 18 19 - const { meta: { pageTitle } } = $derived(data) 19 + const { meta } = $derived(data) 20 20 const { form, errors, constraints, message, enhance } = superForm(untrack(() => data.form), { 21 21 applyAction: false, 22 22 onResult: ({ result }) => { ··· 29 29 </script> 30 30 31 31 <svelte:head> 32 - <title>{pageTitle}</title> 32 + <PageMeta { ...meta } /> 33 33 </svelte:head> 34 34 35 35 <AuthPageLayout>
+4 -4
app/src/routes/(auth)/signup/+page.server.ts
··· 1 - import { pageTitle } from '$lib/utils' 1 + import { definePageMeta } from '$lib/utils' 2 2 import { auth } from '$server/auth' 3 3 import { zSignUp } from '$server/schemas/auth' 4 4 import { fail, redirect } from '@sveltejs/kit' ··· 9 9 export const load: PageServerLoad = async () => { 10 10 return { 11 11 form: await superValidate(zod4(zSignUp)), 12 - meta: { 13 - pageTitle: pageTitle('Sign up'), 14 - }, 12 + meta: definePageMeta({ 13 + title: 'Sign up', 14 + }), 15 15 } 16 16 } 17 17
+5 -5
app/src/routes/(auth)/signup/+page.svelte
··· 1 1 <script lang="ts"> 2 2 import UserPlusIcon from '@lucide/svelte/icons/user-plus' 3 - import type { WithChildren } from 'bits-ui' 4 3 import { untrack } from 'svelte' 5 4 import { superForm } from 'sveltekit-superforms' 6 - import type { PageProps } from './$types' 7 5 import { goto } from '$app/navigation' 8 6 import { resolve } from '$app/paths' 7 + import { PageMeta } from '$lib/page-meta' 9 8 import { Button } from '$ui/button' 10 9 import { Callout } from '$ui/callout' 11 10 import { Field } from '$ui/field' 12 11 import { Link } from '$ui/link' 13 12 import { TextInput, PasswordInput } from '$ui/text-input' 14 13 import { AuthHeader, AuthFooter, AuthPageLayout } from '../components' 14 + import type { PageProps } from './$types' 15 15 16 - type SignUpProps = WithChildren<PageProps> 16 + type SignUpProps = PageProps 17 17 let { data }: SignUpProps = $props() 18 18 19 - const { meta: { pageTitle } } = $derived(data) 19 + const { meta } = $derived(data) 20 20 const { form, errors, constraints, message, enhance } = superForm(untrack(() => data.form), { 21 21 applyAction: false, 22 22 onResult: ({ result }) => { ··· 32 32 </script> 33 33 34 34 <svelte:head> 35 - <title>{pageTitle}</title> 35 + <PageMeta { ...meta } /> 36 36 </svelte:head> 37 37 38 38 <AuthPageLayout>
-2
app/src/routes/+layout.svelte
··· 2 2 import LogInIcon from '@lucide/svelte/icons/log-in' 3 3 import UserPlusIcon from '@lucide/svelte/icons/user-plus' 4 4 import { Tooltip, type WithChildren } from 'bits-ui' 5 - import { pageTitle } from '$lib/utils' 6 5 import { LinkButton } from '$ui/button' 7 6 import { Header } from '$ui/site' 8 7 import type { LayoutProps } from './$types' ··· 21 20 </script> 22 21 23 22 <svelte:head> 24 - <title>{pageTitle()}</title> 25 23 <meta name="theme-color" content="#00FF08" media="(prefers-color-scheme: light)"> 26 24 <meta name="theme-color" content="#151512" media="(prefers-color-scheme: dark)"> 27 25 </svelte:head>
+5
app/src/routes/+page.svelte
··· 8 8 import FeatIcon from '$icons/FeatIcon.svelte' 9 9 import OriginIcon from '$icons/OriginIcon.svelte' 10 10 import SpeciesIcon from '$icons/SpeciesIcon.svelte' 11 + import { PageMeta } from '$lib/page-meta' 11 12 import { PageLayout } from '$ui/site' 12 13 import HomepageCard from './HomepageCard.svelte' 13 14 ··· 23 24 { text: 'Factions', entries: 17, icon: FactionIcon }, 24 25 ] 25 26 </script> 27 + 28 + <svelte:head> 29 + <PageMeta /> 30 + </svelte:head> 26 31 27 32 <PageLayout direction="col" items="stretch" class="gap-12"> 28 33 <div class="flex flex-col gap-2 mt-12">
+4 -4
app/src/routes/users/[username]/+page.server.ts
··· 1 - import { pageTitle } from '$lib/utils' 1 + import { definePageMeta } from '$lib/utils' 2 2 import { auth } from '$server/auth' 3 3 import { db } from '$server/db' 4 4 import { AuthRepository } from '$server/db/repos/auth' ··· 9 9 const userQuery = await authRepo.getUserByUsername(params.username) 10 10 return { 11 11 user: userQuery, 12 - meta: { 13 - pageTitle: pageTitle(params.username), 14 - }, 12 + meta: definePageMeta({ 13 + title: params.username, 14 + }), 15 15 } 16 16 }
+3 -2
app/src/routes/users/[username]/+page.svelte
··· 1 1 <script lang="ts"> 2 2 import { BookPlusIcon, UserPlusIcon } from '@lucide/svelte' 3 + import { PageMeta } from '$lib/page-meta' 3 4 import { LinkButton } from '$ui/button' 4 5 import { Heading } from '$ui/heading' 5 6 import { PageLayout } from '$ui/site' ··· 10 11 11 12 type UserProfileProps = PageProps 12 13 let { data, params }: UserProfileProps = $props() 13 - const { user, meta: { pageTitle } } = $derived(data) 14 + const { user, meta } = $derived(data) 14 15 </script> 15 16 16 17 <svelte:head> 17 - <title>{pageTitle}</title> 18 + <PageMeta { ...meta } /> 18 19 </svelte:head> 19 20 20 21 <PageLayout display="flex" direction="col">