Skip to content

[docs-infra] Fix blog SEO for pagination #37926

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 52 additions & 18 deletions docs/pages/blog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Divider from '@mui/material/Divider';
import Typography from '@mui/material/Typography';
import Paper from '@mui/material/Paper';
import Pagination from '@mui/material/Pagination';
import PaginationItem from '@mui/material/PaginationItem';
import Button from '@mui/material/Button';
import KeyboardArrowRightRoundedIcon from '@mui/icons-material/KeyboardArrowRightRounded';
import Chip from '@mui/material/Chip';
Expand Down Expand Up @@ -189,7 +190,11 @@ const PAGE_SIZE = 5;
export default function Blog(props: InferGetStaticPropsType<typeof getStaticProps>) {
const router = useRouter();
const postListRef = React.useRef<HTMLDivElement | null>(null);
const [page, setPage] = React.useState(0);
const [page, setPage] = React.useState(
Number.isNaN(router.query.page) || !router.query.page
? 1
: Number.parseInt(router.query.page as string, 10),
);
const [selectedTags, setSelectedTags] = React.useState<Record<string, boolean>>({});
const { allBlogPosts, tagInfo: rawTagInfo } = props;
const [firstPost, secondPost, ...otherPosts] = allBlogPosts;
Expand All @@ -215,7 +220,7 @@ export default function Blog(props: InferGetStaticPropsType<typeof getStaticProp
return Object.keys(selectedTags).includes(tag);
});
});
const pageStart = page * PAGE_SIZE;
const pageStart = (page - 1) * PAGE_SIZE;
const totalPage = Math.ceil(filteredPosts.length / PAGE_SIZE);
const displayedPosts = filteredPosts.slice(pageStart, pageStart + PAGE_SIZE);
const getTags = React.useCallback(() => {
Expand All @@ -225,15 +230,23 @@ export default function Blog(props: InferGetStaticPropsType<typeof getStaticProp
.filter((tag) => !!tag);
}, [router.query]);

const getPage = React.useCallback(() => {
const { page: pageParam = '' } = router.query;
if (typeof pageParam !== 'string' || !pageParam || Number.isNaN(pageParam)) {
return 1;
}
return Number.parseInt(pageParam, 10);
}, [router.query]);

React.useEffect(() => {
const arrayTags = getTags();
const finalTags: Record<string, boolean> = {};
arrayTags.forEach((tag) => {
finalTags[tag] = true;
});
setSelectedTags(finalTags);
setPage(0);
}, [getTags]);
setPage(getPage());
}, [getTags, getPage]);

const removeTag = (tag: string) => {
router.push(
Expand All @@ -247,6 +260,28 @@ export default function Blog(props: InferGetStaticPropsType<typeof getStaticProp
{ shallow: true },
);
};
const addTag = (tag: string) => {
router.push(
{
query: {
...router.query,
tags: [...getTags(), tag],
},
},
undefined,
{ shallow: true },
);
};

const hrefWithSpecificPage = (newPage: number) => {
const tags = getTags();

return `/blog/?${[
Copy link
Member

@oliviertassinari oliviertassinari Jul 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clicking on the first page should ideally not point to https://deploy-preview-37926--material-ui.netlify.app/blog/?. It should point to https://deploy-preview-37926--material-ui.netlify.app/blog/. This is to have more unicity of the URLs, hence less crawling budget spent on pages.

Screenshot 2023-07-11 at 18 34 30

...(newPage <= 1 ? [] : [`page=${newPage}`]),
...(tags.length === 0 ? [] : [`tags=${tags.join(',')}`]),
].join('&')}`;
};

return (
<BrandingCssVarsProvider>
<Head
Expand Down Expand Up @@ -379,28 +414,18 @@ export default function Blog(props: InferGetStaticPropsType<typeof getStaticProp
<Chip
key={tag}
variant={selected ? 'filled' : 'outlined'}
label={tag}
{...(selected
? {
label: tag,
onDelete: () => {
postListRef.current?.scrollIntoView();
removeTag(tag);
},
}
: {
label: tag,
onClick: () => {
postListRef.current?.scrollIntoView();
router.push(
{
query: {
...router.query,
tags: tag,
},
},
undefined,
{ shallow: true },
);
addTag(tag);
},
})}
size="small"
Expand Down Expand Up @@ -435,14 +460,23 @@ export default function Blog(props: InferGetStaticPropsType<typeof getStaticProp
))}
</Box>
<Pagination
page={page + 1}
page={page}
count={totalPage}
variant="outlined"
shape="rounded"
onChange={(_, value) => {
setPage(value - 1);
setPage(value);
postListRef.current?.scrollIntoView();
}}
renderItem={(item) => (
<PaginationItem
component={Link}
href={item.page ? hrefWithSpecificPage(item.page) : '/blog/'}
scroll={false}
shallow
{...item}
/>
)}
sx={{ mt: 1, mb: 8 }}
/>
</Box>
Expand Down