Skip to content

Commit

Permalink
feat: Configure head / og tags using react-helmet
Browse files Browse the repository at this point in the history
  • Loading branch information
drikusroor committed May 2, 2024
1 parent 5f3ead9 commit e407466
Show file tree
Hide file tree
Showing 8 changed files with 208 additions and 129 deletions.
80 changes: 46 additions & 34 deletions frontend/.pnp.cjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 0 additions & 13 deletions frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,9 @@
/>
<meta name="mobile-web-app-capable" content="yes" />
<meta name="theme-color" content="#212529" />
<meta name="description" content="%VITE_HTML_OG_DESCRIPTION%" />
<meta property="og:title" content="%VITE_HTML_OG_TITLE%" />
<meta property="og:image" content="%VITE_HTML_OG_IMAGE%" />
<meta property="og:image:url" content="%VITE_HTML_OG_IMAGE%" />
<meta property="og:image:height" content="628" />
<meta property="og:image:width" content="1200"/>
<meta property="og:image:type" content="image/png"/>
<meta property="twitter:image" content="%VITE_HTML_OG_IMAGE%" />
<meta name="twitter:card" content="summary_large_image" />
<meta
property="og:description"
content="%VITE_HTML_OG_DESCRIPTION%"
/>
<meta property="og:url" content="%VITE_HTML_OG_URL%" />

<link rel="apple-touch-icon" href="/logo192.png" />
<link rel="manifest" href="/manifest.json" />
<link
rel="stylesheet"
Expand Down
3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"qs": "^6.10.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-helmet-async": "^2.0.4",
"react-helmet": "^6.1.0",
"react-rangeslider": "^2.2.0",
"react-router": "5.2.0",
"react-router-dom": "5.2.0",
Expand Down Expand Up @@ -84,6 +84,7 @@
"@testing-library/user-event": "^14.5.1",
"@types/react": "^18.2.73",
"@types/react-dom": "^18.2.23",
"@types/react-helmet": "^6",
"@types/react-router-dom": "^5.3.3",
"@vitest/coverage-istanbul": "^1.4.0",
"@vitest/coverage-v8": "^1.4.0",
Expand Down
76 changes: 40 additions & 36 deletions frontend/src/components/App/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import Profile from "../Profile/Profile";
import Reload from "../Reload/Reload";
import StoreProfile from "../StoreProfile/StoreProfile";
import useDisableRightClickOnTouchDevices from "../../hooks/useDisableRightClickOnTouchDevices";
import Helmet from "@/components/Helmet/Helmet";


// App is the root component of our application
Expand Down Expand Up @@ -55,45 +56,48 @@ const App = () => {
}

return (
<Router className="aha__app">
<ConditionalRender condition={!!participant} fallback={<LoaderContainer />}>
<Switch>
{/* Request reload for given participant */}
<Route path={URLS.reloadParticipant}>
<Reload />
</Route>

{/* Default experiment */}
<Route path="/" exact>
<Redirect
to={URLS.experiment.replace(":slug", EXPERIMENT_SLUG)}
<>
<Helmet />
<Router className="aha__app">
<ConditionalRender condition={!!participant} fallback={<LoaderContainer />}>
<Switch>
{/* Request reload for given participant */}
<Route path={URLS.reloadParticipant}>
<Reload />
</Route>

{/* Default experiment */}
<Route path="/" exact>
<Redirect
to={URLS.experiment.replace(":slug", EXPERIMENT_SLUG)}
/>
</Route>

{/* Profile */}
<Route path={URLS.profile} exact>
<Profile slug={EXPERIMENT_SLUG} />
</Route>

{/* Experiment Collection */}
<Route path={URLS.experimentCollection} component={ExperimentCollection} />

{/* Experiment */}
<Route path={URLS.experiment} component={Experiment} />

<Route path={URLS.session} />

{/* Store profile */}
<Route
path={URLS.storeProfile}
exact
component={StoreProfile}
/>
</Route>
</Switch>
</ConditionalRender>

{/* Profile */}
<Route path={URLS.profile} exact>
<Profile slug={EXPERIMENT_SLUG} />
</Route>

{/* Experiment Collection */}
<Route path={URLS.experimentCollection} component={ExperimentCollection} />

{/* Experiment */}
<Route path={URLS.experiment} component={Experiment} />

<Route path={URLS.session} />

{/* Store profile */}
<Route
path={URLS.storeProfile}
exact
component={StoreProfile}
/>
</Switch>
</ConditionalRender>


</Router >
</Router >
</>
);
};

Expand Down
17 changes: 17 additions & 0 deletions frontend/src/components/Experiment/Experiment.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import Info from "../Info/Info";
import FloatingActionButton from "@/components/FloatingActionButton/FloatingActionButton";
import UserFeedback from "@/components/UserFeedback/UserFeedback";
import FontLoader from "@/components/FontLoader/FontLoader";
import { API_ROOT } from "../../config";

// Experiment handles the main experiment flow:
// - Loads the experiment and participant
Expand All @@ -36,6 +37,9 @@ const Experiment = ({ match }) => {
const theme = useBoundStore((state) => state.theme);
const setTheme = useBoundStore((state) => state.setTheme);

const setHeadData = useBoundStore((state) => state.setHeadData);
const resetHeadData = useBoundStore((state) => state.resetHeadData);

// Current experiment state
const [actions, setActions] = useState([]);
const [state, setState] = useState(startState);
Expand Down Expand Up @@ -108,6 +112,14 @@ const Experiment = ({ match }) => {
// Loading succeeded
if (experiment) {
setSession(null);
// Set Helmet Head data
setHeadData({
title: experiment.name,
description: experiment.description,
image: `${API_ROOT}/${experiment.image}`,
url: window.location.href
});

// Set theme
if (experiment.theme) {
setTheme(experiment.theme);
Expand All @@ -125,6 +137,11 @@ const Experiment = ({ match }) => {
setError("Could not load experiment");
}
}

// Cleanup
return () => {
resetHeadData();
};
}, [
experiment,
loadingExperiment,
Expand Down
42 changes: 42 additions & 0 deletions frontend/src/components/Helmet/Helmet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Helmet as ReactHelmet } from 'react-helmet';
import useBoundStore from "../../util/stores";

const Helmet = () => {
const headData = useBoundStore(state => state.headData);
const { description, image, url } = headData;

const structuredData = {
"@context": "http://schema.org",
"@type": "Organization",
url: url,
logo: image,
};

return (
<ReactHelmet>
<title>{headData.title}</title>
<meta name="description" content={description} />
<meta property="og:title" content={headData.title} />
<meta property="og:description" content={description} />
<meta property="og:image" content={image} />
<meta property="og:url" content={url} />

<meta name="twitter:title" content={headData.title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={image} />
<meta name="twitter:card" content="summary_large_image" />

<link rel="canonical" href={url} />

<link rel="icon" type="image/png" href="/favicon.ico" />
<link rel="apple-touch-icon" href="/favicon.ico" />

<script type="application/ld+json">
{JSON.stringify(structuredData)}
</script>
</ReactHelmet>

);
};

export default Helmet;
Loading

0 comments on commit e407466

Please sign in to comment.