mirror of
https://github.com/ArthurDanjou/spanish-learner.git
synced 2026-01-14 12:14:39 +01:00
Initial commit
This commit is contained in:
1
.env.example
Normal file
1
.env.example
Normal file
@@ -0,0 +1 @@
|
||||
NUXT_SESSION_PASSWORD=
|
||||
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Nuxt dev/build outputs
|
||||
.output
|
||||
.data
|
||||
.nuxt
|
||||
.nitro
|
||||
.cache
|
||||
dist
|
||||
|
||||
# Node dependencies
|
||||
node_modules
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.fleet
|
||||
.idea
|
||||
|
||||
# Local env files
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
75
README.md
Normal file
75
README.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Nuxt UI Minimal Starter
|
||||
|
||||
Look at [Nuxt docs](https://nuxt.com/docs/getting-started/introduction) and [Nuxt UI docs](https://ui.nuxt.com) to learn more.
|
||||
|
||||
## Setup
|
||||
|
||||
Make sure to install the dependencies:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm install
|
||||
|
||||
# pnpm
|
||||
pnpm install
|
||||
|
||||
# yarn
|
||||
yarn install
|
||||
|
||||
# bun
|
||||
bun install
|
||||
```
|
||||
|
||||
## Development Server
|
||||
|
||||
Start the development server on `http://localhost:3000`:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run dev
|
||||
|
||||
# pnpm
|
||||
pnpm run dev
|
||||
|
||||
# yarn
|
||||
yarn dev
|
||||
|
||||
# bun
|
||||
bun run dev
|
||||
```
|
||||
|
||||
## Production
|
||||
|
||||
Build the application for production:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run build
|
||||
|
||||
# pnpm
|
||||
pnpm run build
|
||||
|
||||
# yarn
|
||||
yarn build
|
||||
|
||||
# bun
|
||||
bun run build
|
||||
```
|
||||
|
||||
Locally preview production build:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run preview
|
||||
|
||||
# pnpm
|
||||
pnpm run preview
|
||||
|
||||
# yarn
|
||||
yarn preview
|
||||
|
||||
# bun
|
||||
bun run preview
|
||||
```
|
||||
|
||||
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
||||
6
app.config.ts
Normal file
6
app.config.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export default defineAppConfig({
|
||||
ui: {
|
||||
primary: 'lime',
|
||||
gray: 'neutral',
|
||||
},
|
||||
})
|
||||
24
app.vue
Normal file
24
app.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<UContainer>
|
||||
<UCard class="mt-10">
|
||||
<template #header>
|
||||
<div class="flex justify-between">
|
||||
<h1>Welcome to Nuxt UI Starter</h1>
|
||||
<ColorScheme>
|
||||
<USelect
|
||||
v-model="$colorMode.preference"
|
||||
:options="['system', 'light', 'dark']"
|
||||
/>
|
||||
</ColorScheme>
|
||||
</div>
|
||||
</template>
|
||||
<UButton
|
||||
icon="i-heroicons-book-open"
|
||||
to="https://ui.nuxt.com"
|
||||
target="_blank"
|
||||
>
|
||||
Open Nuxt UI Documentation
|
||||
</UButton>
|
||||
</UCard>
|
||||
</UContainer>
|
||||
</template>
|
||||
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 @@
|
||||
<script lang="ts" setup>
|
||||
useHead({
|
||||
link: [{ rel: 'icon', type: 'image/png', href: '/favicon.ico' }],
|
||||
})
|
||||
|
||||
const head = useLocaleHead({
|
||||
addDirAttribute: true,
|
||||
identifierAttribute: 'id',
|
||||
addSeoAttributes: true,
|
||||
})
|
||||
</script>
|
||||
|
||||
<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>
|
||||
|
||||
<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
|
||||
3
eslint.config.mjs
Normal file
3
eslint.config.mjs
Normal file
@@ -0,0 +1,3 @@
|
||||
import antfu from '@antfu/eslint-config'
|
||||
|
||||
export default antfu()
|
||||
98
nuxt.config.ts
Normal file
98
nuxt.config.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
export default defineNuxtConfig({
|
||||
future: { compatibilityVersion: 4 },
|
||||
|
||||
// Nuxt App
|
||||
app: {
|
||||
pageTransition: { name: 'page', mode: 'out-in' },
|
||||
head: {
|
||||
templateParams: {
|
||||
separator: '•',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Nuxt Modules
|
||||
modules: [
|
||||
'@nuxthub/core',
|
||||
'@nuxt/ui',
|
||||
'@nuxt/content',
|
||||
'@vueuse/nuxt',
|
||||
'@nuxtjs/google-fonts',
|
||||
'@nuxthq/studio',
|
||||
'@nuxt/image',
|
||||
'@nuxtjs/i18n',
|
||||
'@pinia/nuxt',
|
||||
'@pinia-plugin-persistedstate/nuxt',
|
||||
'nuxt-auth-utils',
|
||||
],
|
||||
|
||||
// Nuxt Hub
|
||||
hub: {
|
||||
cache: true,
|
||||
kv: true,
|
||||
database: true,
|
||||
analytics: true,
|
||||
},
|
||||
|
||||
// Nuxt Content
|
||||
content: {
|
||||
highlight: {
|
||||
theme: 'github-dark',
|
||||
},
|
||||
},
|
||||
|
||||
// Nuxt Color Mode
|
||||
colorMode: {
|
||||
preference: 'system',
|
||||
fallback: 'light',
|
||||
},
|
||||
|
||||
// Nuxt Devtools
|
||||
devtools: {
|
||||
enabled: true,
|
||||
timeline: { enabled: true },
|
||||
},
|
||||
|
||||
// Nuxt I18N
|
||||
i18n: {
|
||||
strategy: 'no_prefix',
|
||||
locales: [
|
||||
{
|
||||
code: 'en',
|
||||
iso: 'en-EN',
|
||||
icon: 'i-twemoji-flag-united-kingdom',
|
||||
},
|
||||
{
|
||||
code: 'fr',
|
||||
iso: 'fr-FR',
|
||||
icon: 'i-twemoji-flag-france',
|
||||
},
|
||||
],
|
||||
defaultLocale: 'en',
|
||||
},
|
||||
|
||||
// Nuxt Google Fonts
|
||||
googleFonts: {
|
||||
display: 'swap',
|
||||
families: {
|
||||
'Inter': [400, 500, 600, 700, 800, 900],
|
||||
'DM Sans': [400, 500, 600, 700, 800, 900],
|
||||
},
|
||||
},
|
||||
|
||||
// Nitro
|
||||
nitro: {
|
||||
experimental: {
|
||||
openAPI: true,
|
||||
},
|
||||
},
|
||||
|
||||
// Nuxt Env
|
||||
runtimeConfig: {
|
||||
public: {
|
||||
test: '',
|
||||
},
|
||||
},
|
||||
|
||||
compatibilityDate: '2024-07-23',
|
||||
})
|
||||
47
package.json
Normal file
47
package.json
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "nuxt-starter",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@9.5.0",
|
||||
"scripts": {
|
||||
"build": "nuxt build",
|
||||
"dev": "nuxt dev --host",
|
||||
"generate": "nuxt generate",
|
||||
"preview": "nuxt preview",
|
||||
"postinstall": "nuxt prepare",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"db:generate": "drizzle-kit generate"
|
||||
},
|
||||
"dependencies": {
|
||||
"@iconify/json": "^2.2.230",
|
||||
"@nuxt/content": "^2.13.2",
|
||||
"@nuxt/image": "^1.7.0",
|
||||
"@nuxt/ui": "^2.17.0",
|
||||
"@nuxthq/studio": "^2.0.3",
|
||||
"@nuxthub/core": "^0.7.1",
|
||||
"@nuxtjs/google-fonts": "^3.2.0",
|
||||
"@nuxtjs/i18n": "^8.3.1",
|
||||
"@pinia/nuxt": "^0.5.1",
|
||||
"drizzle-orm": "^0.32.1",
|
||||
"h3-zod": "^0.5.3",
|
||||
"nuxt": "^3.12.4",
|
||||
"nuxt-auth-utils": "^0.2.0",
|
||||
"pinia": "^2.1.7",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^2.23.2",
|
||||
"@nuxt/devtools": "^1.3.9",
|
||||
"@nuxt/ui": "^2.17.0",
|
||||
"@pinia-plugin-persistedstate/nuxt": "^1.2.1",
|
||||
"@types/node": "^20.14.11",
|
||||
"@vueuse/core": "^10.11.0",
|
||||
"@vueuse/nuxt": "^10.11.0",
|
||||
"drizzle-kit": "^0.23.0",
|
||||
"eslint": "^9.7.0",
|
||||
"typescript": "^5.5.4",
|
||||
"vue-tsc": "^2.0.28",
|
||||
"wrangler": "^3.66.0"
|
||||
}
|
||||
}
|
||||
13074
pnpm-lock.yaml
generated
Normal file
13074
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
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)`),
|
||||
})
|
||||
17
server/plugins/migrations.ts
Normal file
17
server/plugins/migrations.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
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, '/')
|
||||
},
|
||||
})
|
||||
3
server/tsconfig.json
Normal file
3
server/tsconfig.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "../.nuxt/tsconfig.server.json"
|
||||
}
|
||||
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],
|
||||
}
|
||||
4
tsconfig.json
Normal file
4
tsconfig.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
// https://nuxt.com/docs/guide/concepts/typescript
|
||||
"extends": "./.nuxt/tsconfig.json"
|
||||
}
|
||||
0
types/index.ts
Normal file
0
types/index.ts
Normal file
Reference in New Issue
Block a user