Last active
March 27, 2019 18:07
-
-
Save jermsam/673380b2cf8451d88362c9c1c473e3a1 to your computer and use it in GitHub Desktop.
trouble implementing seo correctly in next.js app using next-seo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import App, { Container } from 'next/app'; | |
import NextSeo from 'next-seo'; | |
import 'semantic-ui-css/semantic.min.css'; | |
import 'react-dropzone-component/styles/filepicker.css'; | |
import 'react-toastify/dist/ReactToastify.css'; | |
import 'dropzone/dist/min/dropzone.min.css'; | |
import 'react-image-crop/dist/ReactCrop.css'; | |
import 'react-datepicker/dist/react-datepicker.css'; | |
import { loadReCaptcha } from 'react-recaptcha-google'; | |
import { AuthProvider } from '../AuthContext'; | |
import '../static/css/style.css'; | |
import '../static/css/upload.css'; | |
// import your default seo configuration | |
import SEO from './next-seo.config'; | |
export default class MyApp extends App { | |
state = {}; | |
componentDidMount() { | |
loadReCaptcha(); | |
} | |
static async getInitialProps({ Component, ctx }) { | |
let pageProps = {}; | |
if (Component.getInitialProps) { | |
pageProps = await Component.getInitialProps(ctx); | |
} | |
return { pageProps }; | |
} | |
render() { | |
const { Component, pageProps } = this.props; | |
return ( | |
<AuthProvider> | |
<Container> | |
{/* Here we call NextSeo and pass our default configuration to it */} | |
<NextSeo config={SEO} /> | |
<Component {...pageProps} /> | |
</Container> | |
</AuthProvider> | |
); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from 'react'; | |
import { Grid, Container } from 'semantic-ui-react'; | |
// import NextSeo from 'next-seo'; | |
import NextSeo from 'next-seo'; | |
import { app } from '../feathers'; | |
import ApplyForAUserCategory from './components/dashboards/ApplyForAUserCategory'; | |
import SuperUserMenu from './components/dashboards/superuser/SuperUserMenu'; | |
import CreateYourCampaign from './components/dashboards/student/CreateYourCampaign'; | |
import JoinVillage from './components/dashboards/JoinVillage'; | |
import ProvideFALicense from './components/dashboards/fa/ProvideFALicense'; | |
import StudentDashboard from './components/dashboards/student/StudentDashboard'; | |
import FADashboard from './components/dashboards/fa/FADashboard'; | |
import TopMenu from './components/menus/TopMenu'; | |
const INITIAL_STATE = { | |
isProspectiveSuperUser: false, | |
isSuperUser: false, | |
user: { | |
id: null, | |
avatar: null, | |
firstname: '', | |
lastname: '', | |
story: { | |
id: null, | |
coverphoto: '', | |
school: '', | |
birthdate: '', | |
title: '', | |
story: '', | |
goal: '', | |
createdAt: null, | |
likes: 0, | |
userId: null | |
}, | |
address: { | |
zip: '', | |
street: '', | |
state: '', | |
city: '' | |
}, | |
license: null | |
} | |
}; | |
export default class Page extends Component { | |
state = INITIAL_STATE; | |
_isMounted = false; | |
componentDidMount() { | |
this._isMounted = true; | |
this.getUser(); | |
app.service('users').on('patched', this.getUser); | |
app.service('locations').on('patched', this.getUser); | |
app.service('categories').on('created', this.getUser); | |
app.service('categories').on('patched', this.getUser); | |
app.service('stories').on('created', this.getUser); | |
app.service('stories').on('patched', this.getUser); | |
app.service('license').on('created', this.getUser); | |
app.service('license').on('patched', this.getUser); | |
} | |
componentWillUnmount() { | |
this._isMounted = false; | |
} | |
getUser = async () => { | |
const { userId } = this.props; | |
const user = await app.service('users').get(userId); | |
if (this._isMounted) { | |
this.setState({ user }); | |
} | |
}; | |
render() { | |
const { user } = this.state; | |
const { category, id, story, address, license } = user; | |
return ( | |
<> | |
{story && ( | |
<NextSeo | |
config={{ | |
title: story.title, | |
description: `${story.story | |
.split(' ') | |
.slice(0, 30) | |
.join('+')}`, | |
openGraph: { | |
type: 'profile', | |
profile: { | |
firstName: user.firstname, | |
lastName: user.lastname | |
}, | |
url: `${process.env.FRONTEND_URL}/dashboard?userId=${id}`, | |
title: story.title, | |
description: story.story, | |
images: [ | |
{ | |
url: story.coverphoto, | |
width: 850, | |
height: 650, | |
alt: 'Story Cover Photo' | |
}, | |
{ | |
url: user.avatar, | |
width: 850, | |
height: 650, | |
alt: 'Profile Picture' | |
} | |
], | |
site_name: 'Takesavillage' | |
} | |
}} | |
/> | |
)} | |
{<TopMenu />} | |
<Container fluid> | |
<Grid textAlign="center" style={{ height: '100vh' }}> | |
<Grid.Column> | |
{category ? ( | |
<> | |
{category.category === 'Super User' ? ( | |
<> | |
<SuperUserMenu userId={id} /> | |
</> | |
) : ( | |
<> | |
{category.category === 'Students' && ( | |
<> | |
{!story ? ( | |
<CreateYourCampaign userId={id} /> | |
) : ( | |
<> | |
{!address ? ( | |
<JoinVillage userId={id} /> | |
) : ( | |
<StudentDashboard userId={id} /> | |
)} | |
</> | |
)} | |
</> | |
)} | |
{category.category === 'Financial Advisors' && ( | |
<> | |
{!license ? ( | |
<ProvideFALicense userId={id} /> | |
) : ( | |
<> | |
{!address ? ( | |
<JoinVillage userId={id} /> | |
) : ( | |
<> | |
<FADashboard userId={id} /> | |
</> | |
)} | |
</> | |
)} | |
</> | |
)} | |
{category.category === 'Guardians' && ( | |
<> | |
2/3 Set up your an education crowd funding Campaign | |
for the child under your care | |
</> | |
)} | |
{category.category === 'Members' && ( | |
<>2/3 Agree to specific instructions</> | |
)} | |
{category.category === 'Takesavillage Staff' && ( | |
<>2/3 Apply For Available Staff Roles</> | |
)} | |
</> | |
)} | |
</> | |
) : ( | |
<ApplyForAUserCategory userId={id} /> | |
)} | |
</Grid.Column> | |
</Grid> | |
</Container> | |
</> | |
); | |
} | |
} | |
Page.getInitialProps = ({ query: { userId } }) => ({ userId }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default { | |
title: 'The #1 Education Crowdfunding Website', | |
titleTemplate: `Takesavillage | %s`, | |
itemScope: true, | |
itemType: 'http://schema.org/Article', | |
prefix: 'og: http://ogp.me/ns#', | |
openGraph: { | |
type: 'website', | |
locale: 'en_IE', | |
url: `${process.env.FRONTEND_URL}`, | |
site_name: 'Takesavillage' | |
}, | |
twitter: { | |
handle: '@takesavillage', | |
site: '@takesavillage', | |
cardType: 'summary_large_image' | |
}, | |
facebook: { | |
appId: process.env.FACEBOOK_APP_ID | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
hi guys...
I am using next-seo to implement seo in my next.js app. This app uses feather.js in the backend api ...
I have implemented a default seo config in _app.js file as per the instruction ... I need to override this in the users' dashboard with user info ... but this info comes from the feathers.js backend api .... so it's fetched asynchronously ...
I fetched the info in ComponentDidMount ...
What baffles me is that much as the overrides are reflected when I go to the users dashboard, when I view page source on the page in the dashboard, the override is not reflected ... the metatags and title in that html remain the same as they were in pages like the landing page which never overrode the seo...
Kindly advise what I should do to fix this. Thanks ....
find my code snippets in files above ...
Thanks