Add some SEO elements
This commit is contained in:
parent
289119f559
commit
1b37a96adf
13 changed files with 142 additions and 24 deletions
22
content/extra_page_infos.json
Normal file
22
content/extra_page_infos.json
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"title": "Nintendo Switch Emulator",
|
||||||
|
"path": "/",
|
||||||
|
"keywords": ["home"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Download",
|
||||||
|
"path": "/download",
|
||||||
|
"keywords": ["download"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Contribute",
|
||||||
|
"path": "/contribute",
|
||||||
|
"keywords": ["contribute"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Build",
|
||||||
|
"path": "/build",
|
||||||
|
"keywords": ["build"]
|
||||||
|
}
|
||||||
|
]
|
|
@ -2,5 +2,18 @@ module.exports = {
|
||||||
siteName: 'Ryujinx',
|
siteName: 'Ryujinx',
|
||||||
siteUrl: 'https://ryujinx.org',
|
siteUrl: 'https://ryujinx.org',
|
||||||
titleTemplate: 'Ryujinx - %s',
|
titleTemplate: 'Ryujinx - %s',
|
||||||
|
metadata: {
|
||||||
|
siteDescription: "Ryujinx is an open source Nintendo Switch emulator written in C# for Windows, Linux and OSX.",
|
||||||
|
siteKeywords: [
|
||||||
|
"ryujinx",
|
||||||
|
"switch",
|
||||||
|
"nintendo switch",
|
||||||
|
"emulator"
|
||||||
|
],
|
||||||
|
siteAuthor: "Ryujinx",
|
||||||
|
siteCopyright: "Ryujinx",
|
||||||
|
siteTwitter: "@RyujinxEmu",
|
||||||
|
coverImage: "/public/logo.png"
|
||||||
|
},
|
||||||
plugins: []
|
plugins: []
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,5 +26,6 @@ module.exports = function (api) {
|
||||||
api.loadSource(async actions => {
|
api.loadSource(async actions => {
|
||||||
addJSONCollection(actions, "Team", "./content/team.json")
|
addJSONCollection(actions, "Team", "./content/team.json")
|
||||||
addJSONCollection(actions, "SocialNavbarElements", "./content/ui/navbar/social.json")
|
addJSONCollection(actions, "SocialNavbarElements", "./content/ui/navbar/social.json")
|
||||||
|
addJSONCollection(actions, "ExtraPagesInfo", "./content/extra_page_infos.json")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,6 @@
|
||||||
"explore": "gridsome explore"
|
"explore": "gridsome explore"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@gridsome/source-filesystem": "^0.6.2",
|
|
||||||
"@gridsome/transformer-json": "^0.2.1",
|
|
||||||
"axios": "^0.19.2",
|
|
||||||
"gridsome": "^0.7.0",
|
"gridsome": "^0.7.0",
|
||||||
"vuetify": "^1.0.0"
|
"vuetify": "^1.0.0"
|
||||||
},
|
},
|
||||||
|
|
61
src/components/SEO.vue
Normal file
61
src/components/SEO.vue
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
<template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<static-query>
|
||||||
|
query {
|
||||||
|
metadata {
|
||||||
|
siteAuthor
|
||||||
|
siteCopyright
|
||||||
|
siteName
|
||||||
|
siteUrl
|
||||||
|
siteDescription
|
||||||
|
siteKeywords
|
||||||
|
siteTwitter
|
||||||
|
coverImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</static-query>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
metaInfo() {
|
||||||
|
const siteUrl = this.$static.metadata.siteUrl
|
||||||
|
const description = this.$page.extraPagesInfo.description || this.$static.metadata.siteDescription || ""
|
||||||
|
const coverImage = this.$page.extraPagesInfo.coverImage || this.$static.metadata.coverImage
|
||||||
|
const title = `${this.$static.metadata.siteName} - ${this.$page.extraPagesInfo.title}`
|
||||||
|
|
||||||
|
var mergedKeywordsList = this.$static.metadata.siteKeywords
|
||||||
|
|
||||||
|
if (this.$page.extraPagesInfo.keywords) {
|
||||||
|
mergedKeywordsList = mergedKeywordsList.concat(this.$page.extraPagesInfo.keywords)
|
||||||
|
}
|
||||||
|
|
||||||
|
const keywords = mergedKeywordsList.join(', ')
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: this.$page.extraPagesInfo.title,
|
||||||
|
meta: [
|
||||||
|
{ name: "author", content: this.$static.metadata.siteAuthor },
|
||||||
|
{ name: "copyright", content: this.$static.metadata.siteCopyright},
|
||||||
|
{ name: 'keywords', content: keywords},
|
||||||
|
{ name: "description", content: description },
|
||||||
|
{ property: 'og:type', content: 'website' },
|
||||||
|
{ property: 'og:locale', content: 'en_US'},
|
||||||
|
{ property: 'og:site_name', content: `${this.$static.metadata.siteName}` },
|
||||||
|
{ property: "og:title", content: title },
|
||||||
|
{ property: "og:description", content: description },
|
||||||
|
{ property: "og:image", content: siteUrl + coverImage },
|
||||||
|
{
|
||||||
|
property: "og:url",
|
||||||
|
content: siteUrl + this.$page.extraPagesInfo.path
|
||||||
|
},
|
||||||
|
{ name: "twitter:card", content: "summary" },
|
||||||
|
{ name: "twitter:site", content: this.$static.metadata.siteTwitter },
|
||||||
|
{ name: "twitter:title", content: title },
|
||||||
|
{ name: "twitter:image", content: siteUrl + coverImage },
|
||||||
|
{ name: "twitter:description", content: description }
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -1,5 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<v-app :dark="dark">
|
<v-app :dark="dark">
|
||||||
|
<!-- IMPORTANT: KEEP THIS HERE-->
|
||||||
|
<SEO/>
|
||||||
<v-toolbar fixed app>
|
<v-toolbar fixed app>
|
||||||
<v-toolbar-side-icon class="hidden-md-and-up mr-0" @click="drawer = !drawer"></v-toolbar-side-icon>
|
<v-toolbar-side-icon class="hidden-md-and-up mr-0" @click="drawer = !drawer"></v-toolbar-side-icon>
|
||||||
<v-avatar size="32px" tile class="ml-3 mr-1">
|
<v-avatar size="32px" tile class="ml-3 mr-1">
|
||||||
|
|
11
src/main.js
11
src/main.js
|
@ -1,8 +1,10 @@
|
||||||
import Vuetify from 'vuetify'
|
import Vuetify from 'vuetify'
|
||||||
import 'vuetify/dist/vuetify.min.css'
|
import 'vuetify/dist/vuetify.min.css'
|
||||||
import DefaultLayout from '~/layouts/Default.vue'
|
import DefaultLayout from '~/layouts/Default.vue'
|
||||||
|
import SEO from '~/components/SEO.vue'
|
||||||
|
|
||||||
export default function (Vue, { appOptions, head }) {
|
|
||||||
|
export default function (Vue, { appOptions, router, head }) {
|
||||||
// First inject custom CSS needed
|
// First inject custom CSS needed
|
||||||
head.link.push({
|
head.link.push({
|
||||||
rel: 'stylesheet',
|
rel: 'stylesheet',
|
||||||
|
@ -18,6 +20,10 @@ export default function (Vue, { appOptions, head }) {
|
||||||
const gIndex = head.meta.findIndex(e => e.name === 'generator')
|
const gIndex = head.meta.findIndex(e => e.name === 'generator')
|
||||||
if (gIndex !== -1) head.meta.splice(gIndex, 1)
|
if (gIndex !== -1) head.meta.splice(gIndex, 1)
|
||||||
|
|
||||||
|
// Remove the description tag as we generate a custom one in SEO
|
||||||
|
const dIndex = head.meta.findIndex(e => e.name === 'description')
|
||||||
|
if (dIndex !== -1) head.meta.splice(dIndex, 1)
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
theme: {
|
theme: {
|
||||||
ryu_blue: '#00C4E1',
|
ryu_blue: '#00C4E1',
|
||||||
|
@ -32,4 +38,7 @@ export default function (Vue, { appOptions, head }) {
|
||||||
|
|
||||||
// Set default layout as a global component
|
// Set default layout as a global component
|
||||||
Vue.component('Layout', DefaultLayout)
|
Vue.component('Layout', DefaultLayout)
|
||||||
|
|
||||||
|
// Set the SEO component
|
||||||
|
Vue.component('SEO', SEO)
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,11 +60,18 @@
|
||||||
</Layout>
|
</Layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<page-query>
|
||||||
|
query {
|
||||||
|
extraPagesInfo(path: "/build") {
|
||||||
|
path
|
||||||
|
title
|
||||||
|
keywords
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</page-query>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
metaInfo: {
|
|
||||||
title: "Build"
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
downloadURL: "",
|
downloadURL: "",
|
||||||
|
|
|
@ -123,10 +123,12 @@
|
||||||
</Layout>
|
</Layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<page-query>
|
||||||
export default {
|
query {
|
||||||
metaInfo: {
|
extraPagesInfo(path: "/contribute") {
|
||||||
title: "Contribute"
|
path
|
||||||
|
title
|
||||||
|
keywords
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
</script>
|
</page-query>
|
||||||
|
|
|
@ -139,11 +139,18 @@
|
||||||
</Layout>
|
</Layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<page-query>
|
||||||
|
query {
|
||||||
|
extraPagesInfo(path: "/download") {
|
||||||
|
path
|
||||||
|
title
|
||||||
|
keywords
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</page-query>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
metaInfo: {
|
|
||||||
title: "Download"
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
downloadURL: "",
|
downloadURL: "",
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
<v-layout column align-center justify-center class="text-xs-center">
|
<v-layout column align-center justify-center class="text-xs-center">
|
||||||
<img src="@/assets/logo.png" alt="Ryujinx" class="mb-5" />
|
<img src="@/assets/logo.png" alt="Ryujinx" class="mb-5" />
|
||||||
<p class="display-1">A simple, experimental Nintendo Switch emulator.</p>
|
<p class="display-1">A simple, experimental Nintendo Switch emulator.</p>
|
||||||
<p class="caption">Information and content is subject to change.</p>
|
|
||||||
</v-layout>
|
</v-layout>
|
||||||
</v-parallax>
|
</v-parallax>
|
||||||
</section>
|
</section>
|
||||||
|
@ -206,13 +205,11 @@ query {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
extraPagesInfo(path: "/") {
|
||||||
|
path
|
||||||
|
title
|
||||||
|
keywords
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</page-query>
|
</page-query>
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
metaInfo: {
|
|
||||||
title: "Nintendo Switch Emulator"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
BIN
static/public/logo.png
Normal file
BIN
static/public/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6 KiB |
BIN
static/public/wallp.png
Normal file
BIN
static/public/wallp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
Loading…
Reference in a new issue