mirror of
https://github.com/ArthurDanjou/nuxt-starter.git
synced 2026-01-14 12:14:38 +01:00
Init nuxt-starter
This commit is contained in:
1
.env.example
Normal file
1
.env.example
Normal file
@@ -0,0 +1 @@
|
|||||||
|
NUXT_SESSION_PASSWORD=
|
||||||
9
app/app.config.ts
Normal file
9
app/app.config.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export default defineAppConfig({
|
||||||
|
ui: {
|
||||||
|
gray: 'neutral',
|
||||||
|
primary: 'gray',
|
||||||
|
icons: {
|
||||||
|
dynamic: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
72
app/app.vue
Normal file
72
app/app.vue
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<template>
|
||||||
|
<Html
|
||||||
|
:dir="head.htmlAttrs.dir"
|
||||||
|
:lang="head.htmlAttrs.lang"
|
||||||
|
>
|
||||||
|
<Head>
|
||||||
|
<template
|
||||||
|
v-for="link in head.link"
|
||||||
|
:key="link.id"
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
:id="link.id"
|
||||||
|
:href="link.href"
|
||||||
|
:hreflang="link.hreflang"
|
||||||
|
:rel="link.rel"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template
|
||||||
|
v-for="meta in head.meta"
|
||||||
|
:key="meta.id"
|
||||||
|
>
|
||||||
|
<Meta
|
||||||
|
:id="meta.id"
|
||||||
|
:content="meta.content"
|
||||||
|
:property="meta.property"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</Head>
|
||||||
|
<Body>
|
||||||
|
<div>
|
||||||
|
<NuxtLoadingIndicator color="#808080" />
|
||||||
|
<UContainer>
|
||||||
|
<NuxtPage />
|
||||||
|
</UContainer>
|
||||||
|
</div>
|
||||||
|
</Body>
|
||||||
|
</Html>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
useHead({
|
||||||
|
link: [{ rel: 'icon', type: 'image/png', href: '/favicon.ico' }]
|
||||||
|
})
|
||||||
|
|
||||||
|
const head = useLocaleHead({
|
||||||
|
addDirAttribute: true,
|
||||||
|
identifierAttribute: 'id',
|
||||||
|
addSeoAttributes: true
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: 'DM Sans', sans-serif;
|
||||||
|
@apply h-full w-full text-neutral-700 dark:text-neutral-300;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-enter-active,
|
||||||
|
.page-leave-active {
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-enter-from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(5px);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
13
app/pages/index.vue
Normal file
13
app/pages/index.vue
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1>Home</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
7
drizzle.config.ts
Normal file
7
drizzle.config.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import type { Config } from 'drizzle-kit'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
dialect: 'sqlite',
|
||||||
|
schema: './server/database/schema.ts',
|
||||||
|
out: './server/database/migrations'
|
||||||
|
} satisfies Config
|
||||||
6
eslint.config.mjs
Normal file
6
eslint.config.mjs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// @ts-check
|
||||||
|
import withNuxt from './.nuxt/eslint.config.mjs'
|
||||||
|
|
||||||
|
export default withNuxt(
|
||||||
|
// Your custom configs here
|
||||||
|
)
|
||||||
3
server/api/test.ts
Normal file
3
server/api/test.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export default defineEventHandler(() => {
|
||||||
|
return { hello: 'API' }
|
||||||
|
})
|
||||||
5
server/database/migrations/0000_hot_thunderball.sql
Normal file
5
server/database/migrations/0000_hot_thunderball.sql
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
CREATE TABLE `users` (
|
||||||
|
`id` integer PRIMARY KEY NOT NULL,
|
||||||
|
`name` text DEFAULT '',
|
||||||
|
`created_at` text DEFAULT (CURRENT_DATE)
|
||||||
|
);
|
||||||
49
server/database/migrations/meta/0000_snapshot.json
Normal file
49
server/database/migrations/meta/0000_snapshot.json
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
{
|
||||||
|
"version": "6",
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"id": "ef8e28cd-73a1-4801-9a0b-7e80169a57c0",
|
||||||
|
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||||
|
"tables": {
|
||||||
|
"users": {
|
||||||
|
"name": "users",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true,
|
||||||
|
"autoincrement": false
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "''"
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"default": "(CURRENT_DATE)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"enums": {},
|
||||||
|
"_meta": {
|
||||||
|
"schemas": {},
|
||||||
|
"tables": {},
|
||||||
|
"columns": {}
|
||||||
|
},
|
||||||
|
"internal": {
|
||||||
|
"indexes": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
server/database/migrations/meta/_journal.json
Normal file
13
server/database/migrations/meta/_journal.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"version": "7",
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"idx": 0,
|
||||||
|
"version": "6",
|
||||||
|
"when": 1721758030188,
|
||||||
|
"tag": "0000_hot_thunderball",
|
||||||
|
"breakpoints": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
8
server/database/schema.ts
Normal file
8
server/database/schema.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
|
||||||
|
import { sql } from 'drizzle-orm'
|
||||||
|
|
||||||
|
export const users = sqliteTable('users', {
|
||||||
|
id: integer('id').primaryKey(),
|
||||||
|
name: text('name').default(''),
|
||||||
|
createdAt: text('created_at').default(sql`(CURRENT_DATE)`)
|
||||||
|
})
|
||||||
16
server/plugins/migrations.ts
Normal file
16
server/plugins/migrations.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { consola } from 'consola'
|
||||||
|
import { migrate } from 'drizzle-orm/d1/migrator'
|
||||||
|
|
||||||
|
export default defineNitroPlugin(async () => {
|
||||||
|
if (!import.meta.dev) return
|
||||||
|
|
||||||
|
onHubReady(async () => {
|
||||||
|
await migrate(useDB(), { migrationsFolder: 'server/database/migrations' })
|
||||||
|
.then(() => {
|
||||||
|
consola.success('Database migrations done')
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
consola.error('Database migrations failed', err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
19
server/routes/auth/github.get.ts
Normal file
19
server/routes/auth/github.get.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
export default oauth.githubEventHandler({
|
||||||
|
config: {
|
||||||
|
emailRequired: true
|
||||||
|
},
|
||||||
|
async onSuccess(event, { user }) {
|
||||||
|
await setUserSession(event, {
|
||||||
|
user: {
|
||||||
|
name: user.name,
|
||||||
|
imageUrl: user.avatar_url,
|
||||||
|
email: user.email
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return sendRedirect(event, '/')
|
||||||
|
},
|
||||||
|
onError(event, error) {
|
||||||
|
console.error('GitHub OAuth error:', error)
|
||||||
|
return sendRedirect(event, '/')
|
||||||
|
}
|
||||||
|
})
|
||||||
23
server/routes/auth/google.get.ts
Normal file
23
server/routes/auth/google.get.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
export default oauth.googleEventHandler({
|
||||||
|
config: {
|
||||||
|
authorizationParams: {
|
||||||
|
access_type: 'offline'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async onSuccess(event, { user }) {
|
||||||
|
await setUserSession(event, {
|
||||||
|
user: {
|
||||||
|
name: user.name,
|
||||||
|
imageUrl: user.picture,
|
||||||
|
email: user.email
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return sendRedirect(event, '/')
|
||||||
|
},
|
||||||
|
// Optional, will return a json error and 401 status code by default
|
||||||
|
onError(event, error) {
|
||||||
|
console.error('Google OAuth error:', error)
|
||||||
|
return sendRedirect(event, '/')
|
||||||
|
}
|
||||||
|
})
|
||||||
10
server/utils/db.ts
Normal file
10
server/utils/db.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { drizzle } from 'drizzle-orm/d1'
|
||||||
|
import * as schema from '../database/schema'
|
||||||
|
|
||||||
|
export { sql, eq, and, or, asc, desc, sum } from 'drizzle-orm'
|
||||||
|
|
||||||
|
export const tables = schema
|
||||||
|
|
||||||
|
export function useDB() {
|
||||||
|
return drizzle(hubDatabase(), { schema })
|
||||||
|
}
|
||||||
25
tailwind.config.ts
Normal file
25
tailwind.config.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import type { Config } from 'tailwindcss'
|
||||||
|
import typography from '@tailwindcss/typography'
|
||||||
|
|
||||||
|
export default <Partial<Config>>{
|
||||||
|
content: [
|
||||||
|
'./components/**/*.{vue,js,ts}',
|
||||||
|
'./layouts/**/*.vue',
|
||||||
|
'./pages/**/*.vue',
|
||||||
|
'./composables/**/*.{js,ts}',
|
||||||
|
'./plugins/**/*.{js,ts}',
|
||||||
|
'./utils/**/*.{js,ts}',
|
||||||
|
'./App.{js,ts,vue}',
|
||||||
|
'./app.{js,ts,vue}',
|
||||||
|
'./Error.{js,ts,vue}',
|
||||||
|
'./error.{js,ts,vue}',
|
||||||
|
'./app.config.{js,ts}',
|
||||||
|
'content/**/*.md'
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plugins: [typography]
|
||||||
|
}
|
||||||
0
types/index.ts
Normal file
0
types/index.ts
Normal file
Reference in New Issue
Block a user