├── .gitignore ├── README.md ├── components ├── Blog │ ├── Post.vue │ ├── PostList.vue │ └── PostPreview.vue ├── TheHeader.vue └── TheIntro.vue ├── layouts ├── admin.vue └── default.vue ├── middleware ├── auth-check.global.js └── auth.js ├── nuxt.config.ts ├── package-lock.json ├── package.json ├── pages ├── about.vue ├── admin │ └── index.vue ├── auth.vue ├── blog │ └── [id].vue └── index.vue ├── stores ├── auth.js └── blog.js └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log* 3 | .nuxt 4 | .nitro 5 | .cache 6 | .output 7 | .env 8 | /dist -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nuxt 3 Minimal Starter 2 | 3 | Look at the [nuxt 3 documentation](https://v3.nuxtjs.org) to learn more. 4 | 5 | ## Setup 6 | 7 | Make sure to install the dependencies: 8 | 9 | ```bash 10 | # yarn 11 | yarn install 12 | 13 | # npm 14 | npm install 15 | 16 | # pnpm 17 | pnpm install --shamefully-hoist 18 | ``` 19 | 20 | ## Development Server 21 | 22 | Start the development server on http://localhost:3000 23 | 24 | ```bash 25 | npm run dev 26 | ``` 27 | 28 | ## Production 29 | 30 | Build the application for production: 31 | 32 | ```bash 33 | npm run build 34 | ``` 35 | 36 | Locally preview production build: 37 | 38 | ```bash 39 | npm run preview 40 | ``` 41 | 42 | Checkout the [deployment documentation](https://v3.nuxtjs.org/docs/deployment) for more information. 43 | -------------------------------------------------------------------------------- /components/Blog/Post.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ post.title }} 5 | 6 | {{ post.descr }} 7 | 8 | 9 | {{ post.content }} 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /components/Blog/PostList.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /components/Blog/PostPreview.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ post.title }} 7 | 8 | {{ post.descr }} 9 | 10 | 11 | 12 | 13 | 14 | 15 | 30 | 31 | 44 | -------------------------------------------------------------------------------- /components/TheHeader.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Nuxt.js 3 Site 5 | 6 | 7 | 8 | Home 9 | 10 | 11 | About 12 | 13 | 14 | 15 | Admin 16 | 17 | 18 | 19 | Logout 20 | 21 | 22 | 23 | Sign in 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /components/TheIntro.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | Test site on nuxt.js 3 4 | The site uses: pinia.js, bootstrap 5, firebase, ssr, dynamic routes 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /layouts/admin.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 20 | -------------------------------------------------------------------------------- /layouts/default.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 14 | -------------------------------------------------------------------------------- /middleware/auth-check.global.js: -------------------------------------------------------------------------------- 1 | import {authStore} from '../stores/auth' 2 | 3 | export default defineNuxtRouteMiddleware((to) => { 4 | const {ssrContext} = useNuxtApp() 5 | const storeAuth = authStore() 6 | 7 | // console.log('ssrContext', ssrContext) 8 | 9 | if (process.client) { 10 | storeAuth.initAuth(null) 11 | } else { 12 | storeAuth.initAuth(ssrContext?.req?.rawHeaders) 13 | } 14 | 15 | }) 16 | -------------------------------------------------------------------------------- /middleware/auth.js: -------------------------------------------------------------------------------- 1 | import {authStore} from '../stores/auth' 2 | 3 | export default defineNuxtRouteMiddleware((to) => { 4 | const storeAuth = authStore() 5 | 6 | if(!storeAuth.checkAuthUser) { 7 | return '/auth' 8 | } 9 | 10 | }) 11 | 12 | 13 | -------------------------------------------------------------------------------- /nuxt.config.ts: -------------------------------------------------------------------------------- 1 | // https://v3.nuxtjs.org/api/configuration/nuxt.config 2 | export default defineNuxtConfig({ 3 | app: { 4 | head: { 5 | link: [ 6 | { 7 | rel: "stylesheet", 8 | href: "https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css", 9 | }, 10 | ], 11 | }, 12 | pageTransition: true 13 | }, 14 | 15 | modules: [ 16 | "@pinia/nuxt", 17 | //"vee-validate", 18 | //"yup" 19 | ], 20 | css: [], 21 | }); 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "build": "nuxt build", 5 | "dev": "nuxt dev", 6 | "generate": "nuxt generate", 7 | "preview": "nuxt preview" 8 | }, 9 | "devDependencies": { 10 | "nuxt": "3.0.0-rc.12" 11 | }, 12 | "dependencies": { 13 | "@pinia/nuxt": "^0.4.3", 14 | "js-cookie": "^3.0.1", 15 | "vee-validate": "^4.5.11", 16 | "yup": "^0.32.11" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /pages/about.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | About 4 | 5 | -------------------------------------------------------------------------------- /pages/admin/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | Admin dashboard 4 | 5 | 6 | 7 | 18 | -------------------------------------------------------------------------------- /pages/auth.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | Auth 4 | 5 | 6 | 7 | 8 | Email address 9 | 17 | 18 | {{ emailError }} 19 | 20 | 21 | 22 | Password 23 | 31 | {{ passError }} 32 | 33 | Submit 34 | 35 | 36 | 37 | 38 | 39 | 40 | 66 | -------------------------------------------------------------------------------- /pages/blog/[id].vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 20 | -------------------------------------------------------------------------------- /pages/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Загрузка... 5 | {{error.message}} 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /stores/auth.js: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import Cookies from 'js-cookie' 3 | 4 | export const authStore = defineStore('auth', { 5 | state: () => { 6 | return { 7 | token: null 8 | } 9 | }, 10 | getters: { 11 | checkAuthUser(state) { 12 | return !!state.token 13 | } 14 | }, 15 | actions: { 16 | async authUser(userData) { 17 | const key = 'AIzaSyCcFderO-gm1_ki1Z1UhzpGfh0AXY9OKkw' 18 | // console.log('login: ', userData) 19 | 20 | try { 21 | const response = await $fetch(`https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=${key}`, {method: 'POST', body: {...userData, "returnSecureToken": true}}) 22 | 23 | const token = response.idToken 24 | 25 | this.token = token 26 | localStorage.setItem('jwt', token) 27 | Cookies.set('jwt', token, {sameSite: 'None', secure: true}) 28 | 29 | 30 | //response.idToken 31 | } catch (error) { 32 | console.log(error) 33 | } 34 | }, 35 | 36 | logoutUser() { 37 | this.token = null 38 | localStorage.removeItem('jwt') 39 | Cookies.remove('jwt') 40 | 41 | }, 42 | 43 | initAuth(req) { 44 | // this.token = Cookies.get('jwt') 45 | let token 46 | if(req) { 47 | const jwtToken = req.find(t => t.trim().startsWith('jwt=')) 48 | 49 | if(jwtToken) { 50 | token = jwtToken.split('=')[1] 51 | this.token = token 52 | } else { 53 | return false 54 | } 55 | 56 | } else { 57 | if(process.client) { 58 | token = localStorage.getItem('jwt') 59 | } 60 | this.token = token 61 | } 62 | }, 63 | 64 | } 65 | }) -------------------------------------------------------------------------------- /stores/blog.js: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | 3 | export const useBlogStore = defineStore('blog', { 4 | state: () => { 5 | return { 6 | posts: [], 7 | error: null, 8 | postLoading: false 9 | } 10 | }, 11 | getters: { 12 | getPosts(state){ 13 | return state.posts 14 | } 15 | }, 16 | actions: { 17 | async loadPosts() { 18 | try { 19 | this.postLoading = true 20 | const res = await $fetch('https://blog-nuxtjs-c3952-default-rtdb.asia-southeast1.firebasedatabase.app/posts.json') 21 | this.posts = Object.keys(res).map(key => { 22 | return {...res[key], id: key} 23 | }) 24 | 25 | } catch (error) { 26 | this.error = error 27 | console.log(error) 28 | } finally { 29 | this.postLoading = false 30 | } 31 | 32 | } 33 | } 34 | }) -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://v3.nuxtjs.org/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json" 4 | } 5 | --------------------------------------------------------------------------------
{{ post.descr }}
8 | {{ post.descr }} 9 |
Загрузка...
{{error.message}}