From 9dea14085997fbc7a5e247107d401fa760f97b4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Demenech?= Date: Wed, 19 Jul 2023 07:23:06 -0300 Subject: [PATCH] SEO Improvements (#983) * [site,seo][xs]: add custom _document with lang prop, add description to meta tags, make title larger * [site,seo][xs]: add apple touch icon, add alt props to images * [site,seo][xs]: add icon to default seo * [site,seo][s]: implement next-sitemap * [site,seo][s]: review page titles * Rebuild package-lock.json files * Regenerate package-lock --- package-lock.json | 2 +- package.json | 4 ++- site/.gitignore | 5 ++++ site/components/Features.tsx | 2 +- site/components/MDXPage.tsx | 1 - site/content/config.js | 8 ++++-- site/content/guide/index.md | 4 ++- site/content/howtos/index.md | 4 ++- site/layouts/default.tsx | 2 +- site/layouts/docs.tsx | 2 +- site/next-sitemap.config.js | 5 ++++ site/package-lock.json | 49 +++++++++++++++++++++++++++++++++++ site/package.json | 2 ++ site/pages/_app.tsx | 7 ++++- site/pages/_document.tsx | 13 ++++++++++ site/pages/blog.tsx | 2 ++ site/public/icon.png | Bin 0 -> 12419 bytes 17 files changed, 101 insertions(+), 11 deletions(-) create mode 100644 site/next-sitemap.config.js create mode 100644 site/pages/_document.tsx create mode 100644 site/public/icon.png diff --git a/package-lock.json b/package-lock.json index a483b05d..f82be366 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40048,7 +40048,7 @@ }, "packages/components": { "name": "@portaljs/components", - "version": "0.2.0", + "version": "0.3.1", "dependencies": { "@githubocto/flat-ui": "^0.14.1", "@heroicons/react": "^2.0.17", diff --git a/package.json b/package.json index f80922fa..c385cd47 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,8 @@ { "name": "portaljs", - "workspaces": ["./packages/*"], + "workspaces": [ + "./packages/*" + ], "version": "0.0.0", "license": "MIT", "scripts": { diff --git a/site/.gitignore b/site/.gitignore index 47575e0f..4cb0e8da 100644 --- a/site/.gitignore +++ b/site/.gitignore @@ -35,3 +35,8 @@ yarn-error.log* # markdowndb markdown.db + +# seo +robots.txt +sitemap-0.xml +sitemap.xml diff --git a/site/components/Features.tsx b/site/components/Features.tsx index 835336e5..19976f1d 100644 --- a/site/components/Features.tsx +++ b/site/components/Features.tsx @@ -58,7 +58,7 @@ export default function Features() { >
- + {feature.title}

{feature.title} diff --git a/site/components/MDXPage.tsx b/site/components/MDXPage.tsx index 913887c3..31e060e1 100644 --- a/site/components/MDXPage.tsx +++ b/site/components/MDXPage.tsx @@ -12,7 +12,6 @@ export default function MDXPage({ source, frontMatter }) { return {children}; }; - return ( diff --git a/site/content/config.js b/site/content/config.js index d7a50a0d..0265e7b8 100644 --- a/site/content/config.js +++ b/site/content/config.js @@ -1,7 +1,7 @@ const config = { - title: 'PortalJS', + title: 'PortalJS - The JavaScript framework for data portals.', description: - 'PortalJS is a framework for rapidly building rich data portal frontends using a modern frontend approach. PortalJS can be used to present a single dataset or build a full-scale data catalog/portal.', + 'PortalJS is a framework for rapidly building rich data portal frontends using a modern frontend approach.', theme: { default: 'dark', toggleIcon: '/images/theme-button.svg', @@ -36,6 +36,10 @@ const config = { ], footerLinks: [], nextSeo: { + additionalLinkTags: [ + { rel: 'icon', href: '/favicon.ico' }, + { rel: 'apple-touch-icon', href: '/icon.png', sizes: '120x120' }, + ], openGraph: { type: 'website', title: diff --git a/site/content/guide/index.md b/site/content/guide/index.md index d991dfb3..6bd11b3f 100644 --- a/site/content/guide/index.md +++ b/site/content/guide/index.md @@ -1,6 +1,8 @@ --- showToc: false showSidebar: false +title: "Markdown-based Websites Guide" +disableTitle: true --- @@ -79,4 +81,4 @@ Below is a screenshot of how the final website will look like: - Visit the site! Yay! Your changes are live! 🎉 > [!tip] -> Read full tutorial [[edit-a-website-locally|here!]] \ No newline at end of file +> Read full tutorial [[edit-a-website-locally|here!]] diff --git a/site/content/howtos/index.md b/site/content/howtos/index.md index b5d16d1c..c73760e8 100644 --- a/site/content/howtos/index.md +++ b/site/content/howtos/index.md @@ -1,4 +1,6 @@ -# Guides and tutorials +--- +title: Guides and Tutorials +--- - [[howtos/analytics|How to add web analytics?]] - [[howtos/seo|How to customize page metadata for SEO?]] diff --git a/site/layouts/default.tsx b/site/layouts/default.tsx index ac4525f5..09d2919b 100644 --- a/site/layouts/default.tsx +++ b/site/layouts/default.tsx @@ -6,7 +6,7 @@ export default function DefaultLayout({ children, ...frontMatter }) { {/* Default layout */} {!frontMatter.layout && ( <> -

{frontMatter.title}

+ {!frontMatter.disableTitle &&

{frontMatter.title}

} {frontMatter.author && (

{frontMatter.author}

diff --git a/site/layouts/docs.tsx b/site/layouts/docs.tsx index e08f5d69..612eebf2 100644 --- a/site/layouts/docs.tsx +++ b/site/layouts/docs.tsx @@ -13,7 +13,7 @@ export const DocsLayout: React.FC = ({ children, ...frontMatter }) => {

)} - {title &&

{title}

} + {!frontMatter.disableTitle && title &&

{title}

}
{children}
diff --git a/site/next-sitemap.config.js b/site/next-sitemap.config.js new file mode 100644 index 00000000..a9e6b66b --- /dev/null +++ b/site/next-sitemap.config.js @@ -0,0 +1,5 @@ +/** @type {import('next-sitemap').IConfig} */ +module.exports = { + siteUrl: process.env.SITE_URL || 'https://portaljs.org', + generateRobotsTxt: true, +} diff --git a/site/package-lock.json b/site/package-lock.json index b168c763..57d24db8 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -50,6 +50,7 @@ "devDependencies": { "@tailwindcss/typography": "^0.5.9", "autoprefixer": "^10.4.14", + "next-sitemap": "^4.1.8", "postcss": "^8.4.22", "prettier": "^2.8.7", "remark": "^14.0.2", @@ -229,6 +230,12 @@ "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.2.tgz", "integrity": "sha512-Tbsj02wXCbqGmzdnXNk0SOF19ChhRU70BsroIi4Pm6Ehp56in6vch94mfbdQ17DozxkL3BAVjbZ4Qc1a0HFRAg==" }, + "node_modules/@corex/deepmerge": { + "version": "4.0.43", + "resolved": "https://registry.npmjs.org/@corex/deepmerge/-/deepmerge-4.0.43.tgz", + "integrity": "sha512-N8uEMrMPL0cu/bdboEWpQYb/0i2K5Qn8eCsxzOmxSggJbbQte7ljMRoXm917AbntqTGOzdTu+vP3KOOzoC70HQ==", + "dev": true + }, "node_modules/@docsearch/css": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.5.0.tgz", @@ -7087,6 +7094,15 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/minipass": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", @@ -7330,6 +7346,39 @@ "react-dom": ">=16.0.0" } }, + "node_modules/next-sitemap": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-4.1.8.tgz", + "integrity": "sha512-XAXpBHX4o89JfMgvrm0zimlZwpu2iBPXHpimJMUrqOZSc4C2oB1Lv89mxuVON9IE8HOezaM+w4GjJxcYCuGPTQ==", + "dev": true, + "funding": [ + { + "url": "https://github.com/iamvishnusankar/next-sitemap.git" + } + ], + "dependencies": { + "@corex/deepmerge": "^4.0.43", + "@next/env": "^13.4.3", + "fast-glob": "^3.2.12", + "minimist": "^1.2.8" + }, + "bin": { + "next-sitemap": "bin/next-sitemap.mjs", + "next-sitemap-cjs": "bin/next-sitemap.cjs" + }, + "engines": { + "node": ">=14.18" + }, + "peerDependencies": { + "next": "*" + } + }, + "node_modules/next-sitemap/node_modules/@next/env": { + "version": "13.4.10", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.10.tgz", + "integrity": "sha512-3G1yD/XKTSLdihyDSa8JEsaWOELY+OWe08o0LUYzfuHp1zHDA8SObQlzKt+v+wrkkPcnPweoLH1ImZeUa0A1NQ==", + "dev": true + }, "node_modules/next-themes": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.2.1.tgz", diff --git a/site/package.json b/site/package.json index 7e467d05..0da92a7a 100644 --- a/site/package.json +++ b/site/package.json @@ -6,6 +6,7 @@ "dev": "npm run mddb && next dev", "build": "next build", "prebuild": "npm run mddb && node ./scripts/fix-symlinks.mjs", + "postbuild": "next-sitemap", "start": "next start", "mddb": "mddb content" }, @@ -52,6 +53,7 @@ "devDependencies": { "@tailwindcss/typography": "^0.5.9", "autoprefixer": "^10.4.14", + "next-sitemap": "^4.1.8", "postcss": "^8.4.22", "prettier": "^2.8.7", "remark": "^14.0.2", diff --git a/site/pages/_app.tsx b/site/pages/_app.tsx index cacf8f4b..00133045 100644 --- a/site/pages/_app.tsx +++ b/site/pages/_app.tsx @@ -47,7 +47,12 @@ function MyApp({ Component, pageProps }) { defaultTheme={siteConfig.theme.default} forcedTheme={siteConfig.theme.default ? null : 'light'} > - + {/* Global Site Tag (gtag.js) - Google Analytics */} {siteConfig.analytics && ( diff --git a/site/pages/_document.tsx b/site/pages/_document.tsx new file mode 100644 index 00000000..e1e9cbbb --- /dev/null +++ b/site/pages/_document.tsx @@ -0,0 +1,13 @@ +import { Html, Head, Main, NextScript } from 'next/document'; + +export default function Document() { + return ( + + + +
+ + + + ); +} diff --git a/site/pages/blog.tsx b/site/pages/blog.tsx index e15552b1..9a723cba 100644 --- a/site/pages/blog.tsx +++ b/site/pages/blog.tsx @@ -3,10 +3,12 @@ import computeFields from '@/lib/computeFields'; import clientPromise from '@/lib/mddb'; import { BlogsList, SimpleLayout } from '@portaljs/core'; import * as fs from 'fs'; +import {NextSeo} from 'next-seo'; export default function Blog({ blogs }) { return ( <> + diff --git a/site/public/icon.png b/site/public/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..dc790d81dec098bdb3f214c9881e3efe362a0034 GIT binary patch literal 12419 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 literal 0 HcmV?d00001