Skip to content

Commit c6bdac6

Browse files
committed
docs: restore landing page
1 parent c28e5da commit c6bdac6

7 files changed

Lines changed: 1017 additions & 1054 deletions

File tree

docs/app/components/content/landing/LandingHero.vue

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
<script setup lang="ts">
2+
import type { MDCParserResult } from '@nuxtjs/mdc'
23
import { useElementSize } from '@vueuse/core'
34
import { motion, MotionConfig } from 'motion-v'
45
import { ScrollAreaRoot, ScrollAreaScrollbar, ScrollAreaThumb, ScrollAreaViewport } from 'reka-ui'
6+
import { parseMarkdown } from '@nuxtjs/mdc/runtime'
57
// @ts-expect-error yaml is not typed
68
import hero from './hero.yml'
79
@@ -26,6 +28,13 @@ function getLang(filename: string) {
2628
function getCodeBlock(tab: { name: string, code: string }) {
2729
return `\`\`\`${getLang(tab.name)}\n${tab.code.trim()}\n\`\`\``
2830
}
31+
32+
const codeBlocks = await Promise.all(
33+
tabs.map(tab => parseMarkdown(getCodeBlock(tab), {
34+
contentHeading: false,
35+
toc: false,
36+
}) as Promise<MDCParserResult>),
37+
)
2938
</script>
3039

3140
<template>
@@ -91,17 +100,17 @@ function getCodeBlock(tab: { name: string, code: string }) {
91100
</div>
92101

93102
<!-- CTA Buttons -->
94-
<div class="mt-4 flex w-fit flex-col gap-4 font-sans md:flex-row md:justify-center lg:justify-start items-center">
103+
<div class="mt-4 flex w-full max-w-sm items-center gap-3 font-sans min-[390px]:w-fit md:max-w-none md:gap-4 md:justify-center lg:justify-start">
95104
<NuxtLink
96105
to="/getting-started/installation"
97-
class="border-2 border-black bg-white px-4 py-1.5 text-sm uppercase text-black 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)] transition duration-200 md:px-8 hover:shadow-sm dark:border-stone-400 dark:hover:shadow-sm dark:shadow-[1px_1px_rgba(120,113,108),2px_2px_rgba(120,113,108),3px_3px_rgba(120,113,108),4px_4px_rgba(120,113,108),5px_5px_0px_0px_rgba(120,113,108)]"
106+
class="shrink-0 border-2 border-black bg-white px-4 py-1.5 text-sm uppercase text-black 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)] transition duration-200 hover:shadow-sm dark:border-stone-400 dark:hover:shadow-sm dark:shadow-[1px_1px_rgba(120,113,108),2px_2px_rgba(120,113,108),3px_3px_rgba(120,113,108),4px_4px_rgba(120,113,108),5px_5px_0px_0px_rgba(120,113,108)] md:px-8"
98107
>
99108
Get Started
100109
</NuxtLink>
101110
<NuxtLink
102111
to="https://github.com/onmax/nuxt-better-auth"
103112
target="_blank"
104-
class="group relative hidden p-px text-xs font-semibold leading-6 text-white no-underline md:inline-block"
113+
class="group relative inline-block min-w-0 p-px text-xs font-semibold leading-6 text-white no-underline"
105114
>
106115
<span class="absolute inset-0 overflow-hidden rounded-sm">
107116
<span class="absolute inset-0 rounded-sm bg-[image:radial-gradient(75%_100%_at_50%_0%,rgba(56,189,248,0.6)_0%,rgba(56,189,248,0)_75%)] opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
@@ -112,24 +121,15 @@ function getCodeBlock(tab: { name: string, code: string }) {
112121
</span>
113122
<span class="absolute bottom-0 left-[1.125rem] h-px w-[calc(100%-2.25rem)] bg-gradient-to-r from-emerald-400/0 via-stone-800/90 to-emerald-400/0 transition-opacity duration-500 group-hover:opacity-40" />
114123
</NuxtLink>
115-
<!-- Mobile GitHub button -->
116-
<NuxtLink
117-
to="https://github.com/onmax/nuxt-better-auth"
118-
target="_blank"
119-
class="flex items-center gap-2 rounded-none bg-zinc-950 px-4 py-2 text-xs font-semibold text-white ring-1 ring-white/10 md:hidden"
120-
>
121-
<UIcon name="i-simple-icons-github" class="size-4" />
122-
<span>GitHub</span>
123-
</NuxtLink>
124124
</div>
125125
</div>
126126
</div>
127127

128128
<!-- Right: Code preview -->
129129
<div class="relative md:block lg:static xl:pl-10">
130130
<div class="relative">
131-
<div class="from-sky-300 via-sky-300/70 to-blue-300 absolute inset-0 rounded-none bg-gradient-to-tr opacity-0 dark:opacity-5 blur-lg" />
132-
<div class="from-stone-300 via-stone-300/70 to-blue-300 absolute inset-0 rounded-none bg-gradient-to-tr opacity-0 dark:opacity-5" />
131+
<div class="pointer-events-none from-sky-300 via-sky-300/70 to-blue-300 absolute inset-0 rounded-none bg-gradient-to-tr opacity-0 dark:opacity-5 blur-lg" />
132+
<div class="pointer-events-none from-stone-300 via-stone-300/70 to-blue-300 absolute inset-0 rounded-none bg-gradient-to-tr opacity-0 dark:opacity-5" />
133133

134134
<!-- Code Preview Card -->
135135
<MotionConfig :transition="{ duration: 0.3, ease: 'easeInOut' }">
@@ -138,8 +138,8 @@ function getCodeBlock(tab: { name: string, code: string }) {
138138
class="code-preview relative overflow-hidden rounded-sm backdrop-blur-lg"
139139
>
140140
<div ref="contentRef">
141-
<div class="absolute -top-px left-0 right-0 h-px" />
142-
<div class="absolute -bottom-px left-11 right-20 h-px" />
141+
<div class="pointer-events-none absolute -top-px left-0 right-0 h-px" />
142+
<div class="pointer-events-none absolute -bottom-px left-11 right-20 h-px" />
143143
<div class="pl-4 pt-4">
144144
<!-- Traffic lights -->
145145
<svg aria-hidden="true" viewBox="0 0 42 10" fill="none" class="h-2.5 w-auto stroke-slate-500/30">
@@ -149,10 +149,11 @@ function getCodeBlock(tab: { name: string, code: string }) {
149149
</svg>
150150

151151
<!-- Tabs with layoutId animation -->
152-
<div class="mt-4 flex space-x-2 text-xs">
152+
<div class="relative z-10 mt-4 flex space-x-2 text-xs">
153153
<button
154154
v-for="(tab, index) in tabs"
155155
:key="tab.name"
156+
type="button"
156157
class="relative isolate flex h-6 cursor-pointer items-center justify-center rounded-full px-2.5 transition-colors"
157158
:class="currentTab === index ? 'text-stone-300' : 'text-slate-500'"
158159
@click="currentTab = index"
@@ -161,7 +162,7 @@ function getCodeBlock(tab: { name: string, code: string }) {
161162
<motion.div
162163
v-if="currentTab === index"
163164
layout-id="tab-code-preview"
164-
class="bg-stone-800 absolute inset-0 -z-10 rounded-full"
165+
class="pointer-events-none bg-stone-800 absolute inset-0 -z-10 rounded-full"
165166
/>
166167
</button>
167168
</div>
@@ -188,9 +189,8 @@ function getCodeBlock(tab: { name: string, code: string }) {
188189
</div>
189190
</div>
190191

191-
<!-- Code via MDC - all rendered during SSR -->
192192
<div class="hero-code">
193-
<MDC :value="getCodeBlock(tab)" tag="div" />
193+
<MDCRenderer :body="codeBlocks[index].body" />
194194
</div>
195195
</div>
196196
</div>

docs/app/pages/index.vue

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<script setup lang="ts">
2+
import type { Collections } from '@nuxt/content'
3+
4+
const route = useRoute()
5+
const { locale, isEnabled } = useDocusI18n()
6+
7+
const collectionName = computed(() => isEnabled.value ? `landing_${locale.value}` : 'landing')
8+
9+
const { data: page } = await useAsyncData(collectionName.value, () => queryCollection(collectionName.value as keyof Collections).path(route.path).first())
10+
if (!page.value) {
11+
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
12+
}
13+
14+
const title = page.value.seo?.title || page.value.title
15+
const description = page.value.seo?.description || page.value.description
16+
17+
useSeo({
18+
title,
19+
description,
20+
type: 'website',
21+
ogImage: page.value?.seo?.ogImage as string | undefined,
22+
})
23+
24+
if (!page.value?.seo?.ogImage) {
25+
defineOgImage('Landing', {
26+
title: title?.slice(0, 60),
27+
description: formatOgDescription(title, description),
28+
})
29+
}
30+
</script>
31+
32+
<template>
33+
<ContentRenderer
34+
v-if="page"
35+
:value="page"
36+
/>
37+
</template>

docs/content.config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import { defineCollection, defineContentConfig } from '@nuxt/content'
22

33
export default defineContentConfig({
44
collections: {
5+
landing: defineCollection({
6+
type: 'page',
7+
source: 'index.md',
8+
}),
59
content: defineCollection({
610
type: 'page',
711
source: '**/*',

docs/content/index.md

Lines changed: 4 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -4,70 +4,8 @@ description: Seamless Better Auth integration for Nuxt with automatic route prot
44
navigation: false
55
---
66

7-
Nuxt Better Auth is a Nuxt 4 module that wraps [Better Auth](https://www.better-auth.com/) with Nuxt-native configuration, route protection, SSR-safe session access, and optional NuxtHub schema generation.
7+
::landing-hero
8+
::
89

9-
## Start here
10-
11-
Use the docs in this order if you are setting up the module for the first time:
12-
13-
1. [Quickstart](/getting-started)
14-
2. [Installation](/getting-started/installation)
15-
3. [Configuration](/getting-started/configuration)
16-
4. [Client setup](/getting-started/client-setup)
17-
5. [Route protection](/core-concepts/route-protection)
18-
19-
You should finish that path with a working `/api/auth/*` backend, a client config, and a login flow that can read session state through `useUserSession()`.
20-
21-
## Choose the right setup
22-
23-
| If you want to... | Start here |
24-
| --- | --- |
25-
| Get a database-backed setup running quickly | [NuxtHub](/integrations/nuxthub) |
26-
| Plug Better Auth into your own database stack | [Custom database](/guides/custom-database) |
27-
| Reuse an external Better Auth server | [External auth backend](/guides/external-auth-backend) |
28-
| Avoid a database and accept stateless session tradeoffs | [Database-less mode](/guides/database-less-mode) |
29-
| Migrate from `nuxt-auth-utils` | [Migration guide](/guides/migrate-from-nuxt-auth-utils) |
30-
31-
## What the module adds on top of Better Auth
32-
33-
- `server/auth.config.ts` and `app/auth.config.ts` helpers
34-
- auto-imported client and server auth utilities
35-
- route protection through `routeRules` and page meta
36-
- SSR-aware session hydration
37-
- typed `AuthUser` and `AuthSession` inference from your config
38-
- optional NuxtHub database and schema integration
39-
40-
## Documentation map
41-
42-
### Getting started
43-
44-
- [Quickstart](/getting-started)
45-
- [Installation](/getting-started/installation)
46-
- [Configuration](/getting-started/configuration)
47-
- [Client setup](/getting-started/client-setup)
48-
- [Type augmentation](/getting-started/type-augmentation)
49-
- [Schema generation](/getting-started/schema-generation)
50-
51-
### Core concepts
52-
53-
- [Server auth](/core-concepts/server-auth)
54-
- [Sessions](/core-concepts/sessions)
55-
- [Route protection](/core-concepts/route-protection)
56-
- [Auto-imports and aliases](/core-concepts/auto-imports-aliases)
57-
- [Security and caveats](/core-concepts/security-caveats)
58-
59-
### Guides and integrations
60-
61-
- [Role-based access](/guides/role-based-access)
62-
- [OAuth providers](/guides/oauth-providers)
63-
- [Two-factor authentication](/guides/two-factor-auth)
64-
- [Production deployment](/guides/production-deployment)
65-
- [NuxtHub](/integrations/nuxthub)
66-
- [i18n](/integrations/i18n)
67-
68-
### API reference
69-
70-
- [Composables](/api/composables)
71-
- [Server utilities](/api/server-utils)
72-
- [Components](/api/components)
73-
- [Types](/api/types)
10+
::landing-features
11+
::

docs/nuxt.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export default defineNuxtConfig({
3333

3434
mdc: {
3535
highlight: {
36+
noApiRoute: false,
3637
theme: { default: 'synthwave-84', dark: 'synthwave-84', light: 'one-light' },
3738
langs: ['bash', 'json', 'js', 'ts', 'vue', 'html', 'css', 'yaml', 'sql'],
3839
},

docs/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@
1616
"@vercel/speed-insights": "^1.3.1",
1717
"@vueuse/core": "^14.2.1",
1818
"motion-v": "^2.0.0",
19-
"nuxt": "^4.3.1"
19+
"nuxt": "^4.3.1",
20+
"satori": "^0.26.0"
2021
},
2122
"devDependencies": {
2223
"@iconify-json/solar": "^1.2.5",
2324
"@rollup/plugin-yaml": "^4.1.2",
2425
"@vueuse/nuxt": "^14.2.1",
25-
"docus": "^5.8.1"
26+
"docus": "^5.11.0"
2627
}
2728
}

0 commit comments

Comments
 (0)