Skip to content

Commit c696932

Browse files
committed
redesign landing page to match Better Auth style
1 parent 3763b2d commit c696932

9 files changed

Lines changed: 458 additions & 108 deletions

File tree

docs/app/app.vue

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,31 @@
11
<script setup lang="ts">
2+
import type { ContentNavigationItem, PageCollections } from '@nuxt/content'
3+
4+
const { locale, isEnabled } = useDocusI18n()
5+
const collectionName = computed(() => isEnabled.value ? `docs_${locale.value}` : 'docs')
6+
7+
const { data: navigation } = await useAsyncData(() => `navigation_${collectionName.value}`, () => queryCollectionNavigation(collectionName.value as keyof PageCollections), {
8+
transform: (data: ContentNavigationItem[]) => {
9+
const rootResult = data.find(item => item.path === '/docs')?.children || data || []
10+
return rootResult.find(item => item.path === `/${locale.value}`)?.children || rootResult
11+
},
12+
watch: [locale],
13+
})
14+
const { data: files } = useLazyAsyncData(`search_${collectionName.value}`, () => queryCollectionSearchSections(collectionName.value as keyof PageCollections), { server: false })
15+
16+
provide('navigation', navigation)
217
</script>
318

419
<template>
20+
<NuxtLoadingIndicator color="var(--ui-primary)" />
521
<UBanner icon="i-lucide-construction" title="This library is in early development. Expect breaking changes." color="warning" />
22+
<AppHeader />
623
<NuxtLayout>
724
<NuxtPage />
825
</NuxtLayout>
26+
<AppFooter />
27+
28+
<ClientOnly>
29+
<LazyUContentSearch :files="files" :navigation="navigation" />
30+
</ClientOnly>
931
</template>

docs/app/assets/css/main.css

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,78 @@ pre, code {
2121
font-family: var(--font-mono), ui-monospace, monospace;
2222
}
2323

24+
/* Grid background pattern */
2425
@utility bg-grid {
2526
background-image: linear-gradient(currentColor 1px, transparent 1px), linear-gradient(90deg, currentColor 1px, transparent 1px);
2627
background-size: 32px 32px;
2728
}
29+
30+
/* Brutalist button shadow */
31+
@utility shadow-brutalist {
32+
box-shadow: 1px 1px rgba(0,0,0), 2px 2px rgba(0,0,0), 3px 3px rgba(0,0,0), 4px 4px rgba(0,0,0), 5px 5px 0px 0px rgba(0,0,0);
33+
}
34+
35+
.dark .shadow-brutalist {
36+
box-shadow: 1px 1px rgba(255,255,255), 2px 2px rgba(255,255,255), 3px 3px rgba(255,255,255), 4px 4px rgba(255,255,255), 5px 5px 0px 0px rgba(255,255,255);
37+
}
38+
39+
/* Thin border utilities */
40+
@utility border-thin { border-width: 1.2px; }
41+
@utility border-l-thin { border-left-width: 1.2px; }
42+
@utility border-r-thin { border-right-width: 1.2px; }
43+
@utility border-t-thin { border-top-width: 1.2px; }
44+
@utility border-b-thin { border-bottom-width: 1.2px; }
45+
46+
/* Code preview styling */
47+
.code-preview {
48+
background: linear-gradient(to top right, var(--color-stone-100), var(--color-stone-200));
49+
}
50+
51+
.dark .code-preview {
52+
background: linear-gradient(to top right, rgba(28, 25, 23, 0.9), rgba(0, 0, 0, 0.9));
53+
}
54+
55+
/* Traffic lights for code preview */
56+
.traffic-lights circle {
57+
stroke: rgba(100, 116, 139, 0.3);
58+
}
59+
60+
/* Gradient background for npm command */
61+
.gradient-box {
62+
background: linear-gradient(145deg,
63+
rgba(251, 191, 36, 0.1) 0%,
64+
rgba(192, 132, 252, 0.1) 50%,
65+
rgba(34, 211, 238, 0.1) 100%
66+
);
67+
border: 1px solid rgba(255, 255, 255, 0.1);
68+
}
69+
70+
.dark .gradient-box {
71+
background: linear-gradient(145deg,
72+
rgba(251, 191, 36, 0.05) 0%,
73+
rgba(192, 132, 252, 0.05) 50%,
74+
rgba(34, 211, 238, 0.05) 100%
75+
);
76+
}
77+
78+
/* Hero code block styling */
79+
.hero-code pre {
80+
background: transparent !important;
81+
padding: 0.5rem 1rem;
82+
margin: 0;
83+
font-size: 0.75rem;
84+
}
85+
86+
@media (min-width: 640px) {
87+
.hero-code pre {
88+
font-size: 0.875rem;
89+
}
90+
}
91+
92+
.hero-code pre code {
93+
background: transparent !important;
94+
}
95+
96+
.hero-code .shiki {
97+
background: transparent !important;
98+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<script setup lang="ts">
2+
const route = useRoute()
3+
const appConfig = useAppConfig()
4+
const site = useSiteConfig()
5+
6+
const navLinks = [
7+
{ name: 'docs', path: '/getting-started/quickstart' },
8+
{ name: 'better-auth', path: 'https://www.better-auth.com', external: true },
9+
]
10+
11+
const isLanding = computed(() => route.path === '/')
12+
</script>
13+
14+
<template>
15+
<UHeader :ui="{ center: 'flex-1', root: 'border-b border-[var(--ui-border)]' }" to="/" :title="appConfig.header?.title || site.name">
16+
<template #title>
17+
<div class="flex items-center gap-3">
18+
<!-- Nuxt -->
19+
<div class="flex items-center gap-1.5">
20+
<svg width="48" height="32" viewBox="0 0 48 32" fill="none" class="h-4 w-auto" xmlns="http://www.w3.org/2000/svg">
21+
<path d="M26.88 32H44.64C45.2068 32.0001 45.7492 31.8009 46.24 31.52C46.7308 31.2391 47.2367 30.8865 47.52 30.4C47.8033 29.9135 48.0002 29.3615 48 28.7998C47.9998 28.2381 47.8037 27.6864 47.52 27.2001L35.52 6.56C35.2368 6.0736 34.8907 5.72084 34.4 5.44C33.9093 5.15916 33.2066 4.96 32.64 4.96C32.0734 4.96 31.5307 5.15916 31.04 5.44C30.5493 5.72084 30.2032 6.0736 29.92 6.56L26.88 11.84L20.8 1.59962C20.5165 1.11326 20.1708 0.600786 19.68 0.32C19.1892 0.0392139 18.6467 0 18.08 0C17.5133 0 16.9708 0.0392139 16.48 0.32C15.9892 0.600786 15.4835 1.11326 15.2 1.59962L0.32 27.2001C0.0363166 27.6864 0.000246899 28.2381 3.05588e-07 28.7998C-0.000246288 29.3615 0.0367437 29.9134 0.32 30.3999C0.603256 30.8864 1.10919 31.2391 1.6 31.52C2.09081 31.8009 2.63324 32.0001 3.2 32H14.4C18.8379 32 22.068 30.0092 24.32 26.24L29.76 16.8L32.64 11.84L41.44 26.88H29.76L26.88 32ZM14.24 26.88H6.4L18.08 6.72L24 16.8L20.0786 23.636C18.5831 26.0816 16.878 26.88 14.24 26.88Z" class="fill-black dark:fill-white" />
22+
</svg>
23+
<span class="font-semibold text-sm select-none">Nuxt</span>
24+
</div>
25+
<!-- X separator -->
26+
<span class="text-black/40 dark:text-white/40 text-sm select-none">×</span>
27+
<!-- Better Auth -->
28+
<div class="flex items-center gap-1.5">
29+
<svg width="60" height="45" viewBox="0 0 60 45" fill="none" class="h-4 w-auto" xmlns="http://www.w3.org/2000/svg">
30+
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 0H15V15H30V30H15V45H0V30V15V0ZM45 30V15H30V0H45H60V15V30V45H45H30V30H45Z" class="fill-black dark:fill-white" />
31+
</svg>
32+
<span class="font-semibold text-sm select-none">Better Auth</span>
33+
</div>
34+
</div>
35+
</template>
36+
37+
<template #center>
38+
<UNavigationMenu :items="[]" class="hidden lg:flex" />
39+
</template>
40+
41+
<template #right>
42+
<!-- Nav Links (desktop) -->
43+
<nav class="hidden md:flex items-center">
44+
<template v-for="link in navLinks" :key="link.name">
45+
<NuxtLink
46+
:to="link.path"
47+
:target="link.external ? '_blank' : undefined"
48+
class="px-4 py-2 text-sm text-muted hover:text-[var(--ui-text)] transition-colors border-l border-[var(--ui-border)]"
49+
>
50+
{{ link.name }}
51+
</NuxtLink>
52+
</template>
53+
<NuxtLink
54+
to="https://github.com/onmax/nuxt-better-auth"
55+
target="_blank"
56+
class="px-4 py-2 border-l border-[var(--ui-border)] text-muted hover:text-[var(--ui-text)] transition-colors"
57+
aria-label="GitHub"
58+
>
59+
<UIcon name="i-simple-icons-github" class="size-4" />
60+
</NuxtLink>
61+
</nav>
62+
63+
<UContentSearchButton class="lg:hidden" />
64+
65+
<ClientOnly>
66+
<UColorModeButton />
67+
<template #fallback>
68+
<div class="size-8 animate-pulse bg-[var(--ui-bg-elevated)] rounded-md" />
69+
</template>
70+
</ClientOnly>
71+
</template>
72+
73+
<template #toggle="{ open, toggle }">
74+
<UButton
75+
color="neutral"
76+
variant="ghost"
77+
:icon="open ? 'i-lucide-x' : 'i-lucide-menu'"
78+
class="lg:hidden"
79+
@click="toggle"
80+
/>
81+
</template>
82+
83+
<template #body>
84+
<UNavigationMenu :items="[]" orientation="vertical" class="w-full" />
85+
<nav class="flex flex-col border-t border-[var(--ui-border)] mt-4 pt-4">
86+
<NuxtLink
87+
v-for="link in navLinks"
88+
:key="link.name"
89+
:to="link.path"
90+
:target="link.external ? '_blank' : undefined"
91+
class="px-4 py-2 text-sm text-muted hover:text-[var(--ui-text)]"
92+
>
93+
{{ link.name }}
94+
</NuxtLink>
95+
</nav>
96+
</template>
97+
</UHeader>
98+
</template>
Lines changed: 59 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,66 @@
11
<script setup lang="ts">
22
// @ts-expect-error yaml is not typed
33
import features from './features.yml'
4+
5+
const items = features.items as { title: string, description: string, icon: string }[]
46
</script>
57

68
<template>
7-
<UPageSection
8-
:title="features.title"
9-
:description="features.description"
10-
:ui="{
11-
root: 'border-t border-default bg-gradient-to-b from-muted/30 to-default',
12-
title: 'text-2xl sm:text-3xl',
13-
features: 'lg:grid-cols-3 gap-8',
14-
}"
15-
>
16-
<template #features>
17-
<UPageFeature
18-
v-for="feature in features.items"
19-
:key="feature.title"
20-
v-bind="feature"
21-
orientation="vertical"
22-
:ui="{ icon: 'size-8', title: 'text-base', description: 'text-sm' }"
23-
/>
24-
</template>
25-
</UPageSection>
9+
<div class="md:w-10/12 mt-10 mx-auto relative md:border-l-0 md:border-b-0 border-thin border-stone-200 dark:border-stone-800 dark:bg-black/[0.95]">
10+
<div class="w-full md:mx-0">
11+
<!-- Features Grid -->
12+
<div class="grid grid-cols-1 relative md:grid-rows-2 md:grid-cols-3 border-b-thin border-stone-200 dark:border-stone-800">
13+
<!-- Plus decorators at grid intersections -->
14+
<div class="hidden md:grid top-1/2 left-0 -translate-y-1/2 w-full grid-cols-3 z-10 pointer-events-none select-none absolute">
15+
<UIcon name="i-lucide-plus" class="size-8 text-stone-300 translate-x-[16.5px] translate-y-[.5px] ml-auto dark:text-stone-600" />
16+
<UIcon name="i-lucide-plus" class="size-8 text-stone-300 ml-auto translate-x-[16.5px] translate-y-[.5px] dark:text-stone-600" />
17+
</div>
18+
19+
<!-- Feature items -->
20+
<div
21+
v-for="(feature, index) in items"
22+
:key="feature.title"
23+
class="justify-center md:border-l-thin border-stone-200 dark:border-stone-800 md:min-h-[240px] border-t-thin md:border-t-0 transform-gpu flex flex-col p-10 2xl:p-12"
24+
:class="{ 'md:border-t-thin': index >= 3 }"
25+
>
26+
<div class="flex items-center gap-2 my-1">
27+
<UIcon :name="feature.icon" class="size-4" />
28+
<p class="text-stone-600 dark:text-stone-400">{{ feature.title }}</p>
29+
</div>
30+
<div class="mt-2">
31+
<p class="mt-2 text-sm text-left text-muted">
32+
{{ feature.description }}
33+
<NuxtLink class="ml-2 underline" to="/getting-started/installation">
34+
Learn more
35+
</NuxtLink>
36+
</p>
37+
</div>
38+
</div>
39+
</div>
40+
41+
<!-- CTA Section -->
42+
<div class="relative col-span-3 md:border-l-thin border-stone-200 dark:border-stone-800 md:border-t-thin h-full py-20">
43+
<div class="w-full h-full p-16 pt-10 md:px-10 2xl:px-16">
44+
<div class="flex flex-col items-center justify-center w-full h-full gap-3">
45+
<div class="flex items-center gap-2">
46+
<UIcon name="i-lucide-globe" class="size-4" />
47+
<p class="text-stone-600 dark:text-stone-400">Nuxt + Better Auth</p>
48+
</div>
49+
<p class="max-w-md mx-auto mt-4 text-4xl font-normal tracking-tighter text-center md:text-4xl">
50+
<strong>Set up authentication in minutes, not hours!</strong>
51+
</p>
52+
<div class="flex mt-4 z-20 justify-center items-center gap-4">
53+
<UButton to="/getting-started/installation" size="lg">
54+
Get Started
55+
<UIcon name="i-lucide-arrow-right" class="size-4" />
56+
</UButton>
57+
<UButton to="https://www.better-auth.com/docs" target="_blank" color="neutral" variant="outline" size="lg">
58+
Better Auth Docs
59+
</UButton>
60+
</div>
61+
</div>
62+
</div>
63+
</div>
64+
</div>
65+
</div>
2666
</template>

0 commit comments

Comments
 (0)