Skip to content

Commit 5b504cb

Browse files
committed
feat: add proper page titles and meta descriptions
1 parent 8ff3928 commit 5b504cb

File tree

15 files changed

+88
-13
lines changed

15 files changed

+88
-13
lines changed

locales/en/common.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
{
2+
"meta_description": "A powerful, open-source, privacy-friendly online toolkit for developers, with a focus on security.",
3+
"page_title_suffix": " - string.is - a privacy-friendly toolkit for developers"
24
}

locales/en/pages-about.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@
1212
"li_goal_open_source": "It should be open-source.",
1313
"li_goal_strict_csp": "It should have a strict <0>Content Security Policy</0>.",
1414
"page_heading": "About string.is",
15-
"page_title": "About string.is",
15+
"page_title": "About",
1616
"para_icon": "The icon is based on <0>developer</0> by <1>Achmad Mulyana</1>.",
1717
"para_acknowledgements": "string.is wouldn\u2019t exist without the following open-source libraries:",
1818
"para_built": "string.is was built to meet those goals, and provide a secure, trustworthy string conversion tool.",
1919
"para_contact_twitter": "Twitter: <0>@string__is</0> or <1>@davemetrics</1>",
2020
"para_goals": "I started to wonder what the ideal conversion tool might look like, and came up with some simple goals:",
21-
"para_intro": "string.is is an <0>open-source, privacy-friendly</0> toolkit for developers.",
21+
"para_intro": "string.is is an <0>open-source, privacy-friendly</0> toolkit for developers, with a focus on security.",
2222
"para_paranoid": "Like most developers, I need to perform the same string operations regularly, but I\u2019m paranoid about pasting sensitive data into third-party online tools."
2323
}

locales/en/pages-home.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
{
2-
"page_title": "string.is"
2+
"page_heading": "Online Developer Toolkit",
3+
"page_title": "string.is - a privacy-friendly toolkit for developers"
34
}

locales/en/pages-privacy.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"li_dont_pay": "We don\u2019t request or accept payments.",
1010
"li_dont_personal": "We don\u2019t collect personal information.",
1111
"li_dont_share": "We don\u2019t share information with advertising companies or social networks.",
12+
"meta_description": "TL;DR: we don\u2019t use cookies and we don\u2019t collect any personal data. We don\u2019t provide accounts or accept payments. We are committed to complying with GDPR, CCPA, PECR and other privacy regulations.",
1213
"page_heading": "Privacy Policy",
1314
"page_title": "Privacy Policy",
1415
"para_changes": "We may update this policy as needed to comply with relevant regulations and reflect any new practices. The complete change history is <0>available on Github</0>.",

locales/en/pages-security.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"intro": "string.is has been designed from the ground up to protect your privacy. Some of the measures taken to ensure privacy include:",
1313
"local_content": "All conversion operations happen <0>client-side</0> on your browser. At no time is the data you provide sent to any third parties.",
1414
"local_heading": "Your data never leaves your browser",
15+
"meta_description": "string.is has been designed from the ground up to protect your privacy. The source code is publicly available, and your data never leaves your browser.",
1516
"open_source_content": "The source code is publicly available on <0>Github</0>, so that you can verify for yourself how your data is handled.",
1617
"open_source_heading": "Open source",
1718
"page_heading": "Security",

locales/en/pages-terms.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"meta_description": "These are the Terms of Use governing the use of this Service and the agreement that operates between You and the Company. These Terms of Use set out the rights and obligations of all users regarding the use of the Service.",
23
"page_heading": "Terms of Use",
34
"page_title": "Terms of Use"
45
}

pages/index.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { ReactElement } from 'react'
2+
import Trans from 'next-translate/Trans'
23

34
import { Application } from '@components/layout'
45
import { Home as SubHome } from '@pages/Home'
@@ -17,5 +18,10 @@ export default function Home() {
1718
* @param page - The React page comonent.
1819
*/
1920
Home.getLayout = (page: ReactElement) => (
20-
<Application maxWidth={1600}>{page}</Application>
21+
<Application
22+
maxWidth={1600}
23+
pageHeading={<Trans i18nKey={`pages-home:page_heading`} />}
24+
>
25+
{page}
26+
</Application>
2127
)

src/components/pages/About.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,12 @@ export const About = () => {
2222
return (
2323
<Pane display="flex">
2424
<Head>
25-
<title>{t('page_title')}</title>
25+
<title>
26+
{t('page_title')}
27+
{t('common:page_title_suffix')}
28+
</title>
29+
<meta content={t('page_title')} key="title" property="og:title" />
30+
<meta content={t('common:meta_description')} name="description" />
2631
</Head>
2732

2833
<Card title={t('page_heading')}>

src/components/pages/Converter.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { Link, Pane, Text, majorScale } from 'evergreen-ui'
22
import { ReactElement, useEffect } from 'react'
3+
import Head from 'next/head'
34
import Trans from 'next-translate/Trans'
45

56
import type { Converter as ConverterType } from '@lib/converters'
67
import { Home } from '@pages/Home'
8+
import { removeTags } from '@lib/utilities/String'
79
import { useBreakpoints } from '@services/Responsive'
810
import { useConverterContext } from '@contexts/ConverterContext'
911
import useTranslation from 'next-translate/useTranslation'
@@ -37,6 +39,21 @@ export const Converter = ({ converter }: Props): ReactElement => {
3739

3840
return (
3941
<>
42+
<Head>
43+
<title>
44+
{t(`pages-converter:${converter.id}-heading`)}
45+
{t('common:page_title_suffix')}
46+
</title>
47+
<meta
48+
content={t(`pages-converter:${converter.id}-heading`)}
49+
key="title"
50+
property="og:title"
51+
/>
52+
<meta
53+
content={removeTags(t(`pages-converter:${converter.id}-intro`))}
54+
name="description"
55+
/>
56+
</Head>
4057
<Pane
4158
alignSelf="center"
4259
marginBottom={isMobile ? 0 : majorScale(3)}
@@ -58,7 +75,7 @@ export const Converter = ({ converter }: Props): ReactElement => {
5875
</Text>
5976
</Pane>
6077

61-
<Home />
78+
<Home isRootPage={false} />
6279
</>
6380
)
6481
}

src/components/pages/Home.tsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ import { useState } from 'react'
44
import Head from 'next/head'
55
import useTranslation from 'next-translate/useTranslation'
66

7+
interface Props {
8+
/**
9+
* If true, this component is embedded in the '/' root page. If false.
10+
* it is embedded in a landing page for a specific converter.
11+
*/
12+
isRootPage?: boolean
13+
}
14+
715
/**
816
* Renders the 'convert' page, which is basically the heart of the
917
* application. It provides an input textarea, a conversion selector,
@@ -21,16 +29,20 @@ import {
2129
import { Card } from '@components/layout/Card'
2230
import { useBreakpoints } from '@services/Responsive'
2331

24-
export const Home = () => {
32+
export const Home = ({ isRootPage }: Props) => {
2533
const { t } = useTranslation('pages-home')
2634
const { isMobile } = useBreakpoints()
2735
const [focusOutput, setFocusOutput] = useState<boolean>(false)
2836

2937
return (
3038
<Pane display="flex" gap={majorScale(2)}>
31-
<Head>
32-
<title>{t('page_title')}</title>
33-
</Head>
39+
{isRootPage ? (
40+
<Head>
41+
<title>{t('page_title')}</title>
42+
<meta content={t('page_title')} key="title" property="og:title" />
43+
<meta content={t('common:meta_description')} name="description" />
44+
</Head>
45+
) : null}
3446

3547
<Card>
3648
<Pane
@@ -64,3 +76,7 @@ export const Home = () => {
6476
</Pane>
6577
)
6678
}
79+
80+
Home.defaultProps = {
81+
isRootPage: true,
82+
}

0 commit comments

Comments
 (0)