Merge branch 'master' of https://github.com/lucasPDY/oxen-website into add-faq

This commit is contained in:
Lucas Phang 2021-05-07 15:52:12 +10:00
commit 4fc0d4c30e
18 changed files with 205 additions and 102 deletions

View File

@ -13,7 +13,7 @@ interface Props {
} }
export function CardGrid({ rows, children }: Props) { export function CardGrid({ rows, children }: Props) {
const { isMobile, isDesktop, isHuge } = useContext(ScreenContext); const { isDesktop, isHuge } = useContext(ScreenContext);
const [ref, { width }] = useMeasure(); const [ref, { width }] = useMeasure();
const widthOfCardPx = 200; const widthOfCardPx = 200;
@ -37,25 +37,7 @@ export function CardGrid({ rows, children }: Props) {
return ( return (
<> <>
{isMobile ? ( {
<div className="">
<HorizontalScrollable>
{children.map(child => (
<div
key={uuid()}
style={{
width: '80vw',
minWidth: '275px',
maxWidth: '330px',
}}
className="py-4"
>
{child}
</div>
))}
</HorizontalScrollable>
</div>
) : (
<Contained> <Contained>
<div ref={ref} className={classNames('flex flex-col', spacingY)}> <div ref={ref} className={classNames('flex flex-col', spacingY)}>
{_.chunk(cards, grouping).map(group => ( {_.chunk(cards, grouping).map(group => (
@ -69,7 +51,7 @@ export function CardGrid({ rows, children }: Props) {
))} ))}
</div> </div>
</Contained> </Contained>
)} }
</> </>
); );
} }

View File

@ -60,8 +60,8 @@ export function MobileHeader() {
<TriangleSVG <TriangleSVG
onClick={() => toggleSideMenu()} onClick={() => toggleSideMenu()}
className={classNames( className={classNames(
'h-3 fill-current text-primary transform outline-none duration-300 cursor-pointer', 'h-4 fill-current text-primary transform outline-none duration-300 cursor-pointer',
sideMenuExpanded ? 'rotate-180' : '-rotate-60', sideMenuExpanded ? 'rotate-90' : '',
)} )}
/> />
)} )}
@ -71,8 +71,8 @@ export function MobileHeader() {
<TriangleSVG <TriangleSVG
onClick={() => toggleMobileMenu()} onClick={() => toggleMobileMenu()}
className={classNames( className={classNames(
'h-4 transform outline-none duration-300 cursor-pointer', 'h-4 fill-current text-primary transform outline-none duration-300 cursor-pointer',
headerMobileMenuExpanded ? '-rotate-90' : 'rotate-90', headerMobileMenuExpanded ? 'rotate-90' : '',
)} )}
/> />
<MobileMenu /> <MobileMenu />

View File

@ -59,7 +59,7 @@ export function SideMenuInner() {
{!isDesktop && ( {!isDesktop && (
<div <div
className={classNames( className={classNames(
'flex flex-col pt-8 font-medium uppercase font-prompt text-lg', 'flex flex-col pt-8 pl-6 font-medium uppercase font-prompt text-lg',
)} )}
> >
{_.chunk(NAVIGATION.MENU_ITEMS, 2).map(group => ( {_.chunk(NAVIGATION.MENU_ITEMS, 2).map(group => (
@ -80,28 +80,32 @@ export function SideMenuInner() {
<div className="px-6 pb-3"> <div className="px-6 pb-3">
<SocialsRow /> <SocialsRow />
<div className="flex items-center justify-between font-medium text-secondary whitespace-nowrap"> <div className="flex items-center justify-between font-medium whitespace-nowrap">
View Oxen on{' '} <a
<div className="flex items-center"> href="/downloads/oxen-media-kit.zip"
<a target="_blank"
href="https://www.coingecko.com/en/coins/oxen" className="flex items-center space-x-1 hover:underline hover:text-secondary"
target="_blank" >
rel="dofollow" <span>Media Kit</span>
className="flex items-center mx-2 space-x-1 font-bold hover:underline" </a>
> <a
<img className="h-5" src="/img/coingecko.png" /> href="https://coinmarketcap.com/currencies/oxen/"
<span>CoinGecko</span> target="_blank"
</a> rel="nofollow"
<a className="flex items-center space-x-1 hover:underline hover:text-secondary"
href="https://coinmarketcap.com/currencies/oxen/" >
target="_blank" <img className="h-5" src="/img/coinmarketcap.png" />
rel="dofollow" <span>CMC</span>
className="flex items-center mx-2 space-x-1 font-bold hover:underline" </a>
> <a
<img className="h-5" src="/img/coinmarketcap.png" /> href="https://www.coingecko.com/en/coins/oxen"
<span>CMC</span> target="_blank"
</a> rel="nofollow"
</div> className="flex items-center space-x-1 hover:underline hover:text-secondary"
>
<img className="h-5" src="/img/coingecko.png" />
<span>CoinGecko</span>
</a>
</div> </div>
</div> </div>
) : ( ) : (
@ -114,13 +118,13 @@ export function SideMenuInner() {
} }
const SocialsRow = () => { const SocialsRow = () => {
const { isDesktop } = useContext(ScreenContext); const { isTablet } = useContext(ScreenContext);
return ( return (
<div <div
className={classNames( className={classNames(
'flex pt-3 pb-3 space-x-3 justify-between', 'flex pt-3 pb-3',
isDesktop && 'justify-between', isTablet ? 'justify-start space-x-5 px-6' : 'justify-between',
)} )}
> >
<a href="https://t.me/Oxen_Community" target="_blank" rel="noreferrer"> <a href="https://t.me/Oxen_Community" target="_blank" rel="noreferrer">

View File

@ -1,6 +1,18 @@
const METADATA = { const METADATA = {
OXEN_HOST_URL: 'https://oxen.io', OXEN_HOST_URL: 'https://oxen.io',
TITLE_SUFFIX: 'Oxen | Privacy made simple.', TITLE_SUFFIX: 'Oxen | Privacy made simple.',
SITE_META_DESCRIPTION:
'Oxen is built by the OPTF, a passionate team of advocates, creatives, and engineers building a world where the internet is open, software is free and accessible, and your privacy is protected. The OPTF also builds other platforms using Oxen technology, and supports other developers in building on Oxen.',
ROADMAP: {
DESCRIPTION: "View Oxen's plan for the future here.",
},
404: {
DESCRIPTION: "Oopsy, here's our 404 page.",
},
BLOG: {
DESCRIPTION: "View Oxen's Blog Updates Here",
URL: 'https://oxen.io/blog',
},
}; };
export default METADATA; export default METADATA;

View File

@ -127,8 +127,6 @@ const NAVIGATION = {
SIDE_MENU_ITEMS, SIDE_MENU_ITEMS,
BLOG_REGEX: /^\/(blog)([?tag=[\w-]*)?([?&]page=[0-9]{1,3})?/, BLOG_REGEX: /^\/(blog)([?tag=[\w-]*)?([?&]page=[0-9]{1,3})?/,
POST_REGEX: /^\/(blog\/)(([\w-]{1,100})|(\[slug\]))$/, POST_REGEX: /^\/(blog\/)(([\w-]{1,100})|(\[slug\]))$/,
SITE_META_DESCRIPTION:
'Oxen is built by the Loki Foundation, a passionate team of advocates, creatives, and engineers building a world where the internet is open, software is free and accessible, and your privacy is protected. The Loki Foundation also builds other platforms using Oxen technology, and supports other developers in building on Oxen.',
}; };
export default NAVIGATION; export default NAVIGATION;

View File

@ -2,9 +2,9 @@ import classNames from 'classnames';
import Head from 'next/head'; import Head from 'next/head';
import React, { useContext } from 'react'; import React, { useContext } from 'react';
// import _404 from '../assets/svgs/404.svg'; // import _404 from '../assets/svgs/404.svg';
import { UI } from '../constants'; import { UI, METADATA } from '../constants';
import { ScreenContext } from '../contexts/screen'; import { ScreenContext } from '../contexts/screen';
import { generateTitle } from '../utils/metadata'; import { generateTitle, generateURL } from '../utils/metadata';
function oxen404() { function oxen404() {
const { isMobile, isTablet, isDesktop, isHuge } = useContext(ScreenContext); const { isMobile, isTablet, isDesktop, isHuge } = useContext(ScreenContext);
@ -47,10 +47,24 @@ function oxen404() {
width: '9rem', width: '9rem',
}; };
const pageTitle = generateTitle('404');
const pageURL = generateURL('/404');
return ( return (
<div className="flex items-center justify-center flex-grow h-full"> <div className="flex items-center justify-center flex-grow h-full">
<Head> <Head>
<title>{generateTitle('404')}</title> <title>{pageTitle}</title>
<meta name="description" content={METADATA['404'].DESCRIPTION}></meta>
<meta property="og:title" content={pageTitle} key="ogtitle" />
<meta
property="og:description"
content={METADATA['404'].DESCRIPTION}
key="ogdesc"
/>
<meta property="og:type" content="website" />
<meta property="og:url" content={pageURL} />
<link rel="canonical" href={pageURL}></link>
</Head> </Head>
<div style={wrapperStyles} className="flex items-center flex-grow"> <div style={wrapperStyles} className="flex items-center flex-grow">
@ -65,13 +79,13 @@ function oxen404() {
<div style={_404SectionStyles} className="absolute left-0 z-50"> <div style={_404SectionStyles} className="absolute left-0 z-50">
<h1 <h1
style={_404TitleStyles} style={_404TitleStyles}
className="-mb-4 text-opacity-25 font-sans text-primary text-8xl" className="-mb-4 font-sans text-opacity-25 text-primary text-8xl"
> >
404 404
</h1> </h1>
<p <p
style={_404TextStyles} style={_404TextStyles}
className="text-4xl tracking-tight font-sans text-primary" className="font-sans text-4xl tracking-tight text-primary"
> >
Nothing found here. Nothing found here.
</p> </p>

View File

@ -4,11 +4,11 @@ import React, { useEffect } from 'react';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { Contained } from '../components/Contained'; import { Contained } from '../components/Contained';
import { RichBody } from '../components/RichBody'; import { RichBody } from '../components/RichBody';
import { NAVIGATION } from '../constants'; import { NAVIGATION, METADATA } from '../constants';
import { CmsApi, unslugify } from '../services/cms'; import { CmsApi, unslugify } from '../services/cms';
import { PageType, setPageType, SideMenuItem } from '../state/navigation'; import { PageType, setPageType, SideMenuItem } from '../state/navigation';
import { ISplitPage } from '../types/cms'; import { ISplitPage } from '../types/cms';
import { generateTitle } from '../utils/metadata'; import { generateTitle, generateURL } from '../utils/metadata';
interface IPath { interface IPath {
params: { page: string; isRoadmap?: boolean }; params: { page: string; isRoadmap?: boolean };
@ -19,7 +19,6 @@ export async function getStaticPaths() {
// Hardcoded in navigation constants. // Hardcoded in navigation constants.
// Contentful can edit entries but cannot add/remove // Contentful can edit entries but cannot add/remove
// without touching code. // without touching code.
const paths: IPath[] = Object.values(NAVIGATION.SIDE_MENU_ITEMS).map( const paths: IPath[] = Object.values(NAVIGATION.SIDE_MENU_ITEMS).map(
item => ({ item => ({
params: { page: item.href }, params: { page: item.href },
@ -30,8 +29,8 @@ export async function getStaticPaths() {
} }
export async function getStaticProps({ params }) { export async function getStaticProps({ params }) {
const id = unslugify(String(params?.page) ?? ''); const href = params?.page ?? '';
const id = unslugify(String(href));
// Roadmap page is special 👁️👄👁️ // Roadmap page is special 👁️👄👁️
if (SideMenuItem[id] == [SideMenuItem.ROADMAP]) { if (SideMenuItem[id] == [SideMenuItem.ROADMAP]) {
// query all FAQ items from contentful // query all FAQ items from contentful
@ -39,6 +38,7 @@ export async function getStaticProps({ params }) {
props: { props: {
page: null, page: null,
isRoadmap: true, isRoadmap: true,
href: `/${href}`, // the '/' is removed from the href from getStaticPaths(), so let's add it back here
}, },
revalidate: 60, revalidate: 60,
}; };
@ -57,7 +57,6 @@ export async function getStaticProps({ params }) {
const cms = new CmsApi(); const cms = new CmsApi();
const page = await cms.fetchPageById(SideMenuItem[id]); const page = await cms.fetchPageById(SideMenuItem[id]);
if (!page) { if (!page) {
return { notFound: true }; return { notFound: true };
} }
@ -66,6 +65,7 @@ export async function getStaticProps({ params }) {
props: { props: {
page, page,
isRoadmap: false, isRoadmap: false,
href: `/${href}`,
}, },
revalidate: 60, revalidate: 60,
}; };
@ -74,25 +74,54 @@ export async function getStaticProps({ params }) {
function Page({ function Page({
page, page,
isRoadmap, isRoadmap,
href,
}: { }: {
page: ISplitPage | null; page: ISplitPage | null;
isRoadmap?: boolean; isRoadmap?: boolean;
href: string;
}) { }) {
const dispatch = useDispatch(); const dispatch = useDispatch();
useEffect(() => { useEffect(() => {
dispatch(setPageType(PageType.NORMAL)); dispatch(setPageType(PageType.NORMAL));
}, []); }, []);
const pageTitle = generateTitle(
isRoadmap
? NAVIGATION.SIDE_MENU_ITEMS[SideMenuItem.ROADMAP].label
: page?.label,
);
const pageDescription = isRoadmap
? METADATA.ROADMAP.DESCRIPTION
: page?.title;
const pageURL = generateURL(
isRoadmap ? NAVIGATION.SIDE_MENU_ITEMS[SideMenuItem.ROADMAP].href : href,
);
return ( return (
<> <>
<Head> <Head>
<title> <title>{pageTitle}</title>
{generateTitle( <meta name="description" content={pageDescription}></meta>
isRoadmap <meta property="og:title" content={pageTitle} key="ogtitle" />
? NAVIGATION.SIDE_MENU_ITEMS[SideMenuItem.ROADMAP].label <meta
: page?.label, property="og:description"
)} content={pageDescription}
</title> key="ogdesc"
/>
<meta property="og:type" content="website" />
<meta
property="og:image"
content={page?.hero?.imageUrl}
key="ogimage"
/>
<meta property="og:url" content={pageURL} />
<link rel="canonical" href={pageURL}></link>
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={pageTitle} />
<meta name="twitter:description" content={pageDescription} />
<meta name="twitter:image" content={page?.hero?.imageUrl} />
</Head> </Head>
<div className="bg-alt"> <div className="bg-alt">

View File

@ -63,6 +63,9 @@ function App({ Component, pageProps }: AppProps) {
name="viewport" name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1" content="width=device-width, initial-scale=1, maximum-scale=1"
></meta> ></meta>
<meta property="og:site_name" content="Oxen" key="ogsitename" />
<meta property="og:locale" content="en_US" />
<meta name="apple-itunes-app" content="app-id=1547745078" />
</Head> </Head>
<Layout> <Layout>

View File

@ -6,7 +6,7 @@ import { Article } from '../../components/article/Article';
import { CmsApi } from '../../services/cms'; import { CmsApi } from '../../services/cms';
import { PageType, setPageType, setPostTitle } from '../../state/navigation'; import { PageType, setPageType, setPostTitle } from '../../state/navigation';
import { IPost } from '../../types/cms'; import { IPost } from '../../types/cms';
import { generateTitle } from '../../utils/metadata'; import { generateTitle, generateURL } from '../../utils/metadata';
interface IPath { interface IPath {
params: { slug: string }; params: { slug: string };
@ -43,7 +43,7 @@ export async function getStaticProps({ params }) {
const cms = new CmsApi(); const cms = new CmsApi();
const post = await cms.fetchBlogBySlug(String(params?.slug) ?? ''); const post = await cms.fetchBlogBySlug(String(params?.slug) ?? '');
const url = generateURL(params?.slug ? `/blog/${params?.slug}` : '/blog');
if (!post) { if (!post) {
return { notFound: true }; return { notFound: true };
} }
@ -51,13 +51,14 @@ export async function getStaticProps({ params }) {
return { return {
props: { props: {
post, post,
url,
}, },
revalidate: 60, revalidate: 60,
}; };
} }
// Parallax on bg as mouse moves // Parallax on bg as mouse moves
function Post({ post }: { post: IPost }) { function Post({ post, url }: { post: IPost; url: string }) {
const dispatch = useDispatch(); const dispatch = useDispatch();
useEffect(() => { useEffect(() => {
@ -66,28 +67,30 @@ function Post({ post }: { post: IPost }) {
}, []); }, []);
const pageTitle = generateTitle(post?.title); const pageTitle = generateTitle(post?.title);
const imageURL = post?.featureImage?.imageUrl;
return ( return (
<> <>
<Head> <Head>
<title>{pageTitle}</title> <title>{pageTitle}</title>
<meta name="description" content={post?.description}></meta>
<meta name="image_src" content={post?.featureImage?.imageUrl} />
<meta name="image_url" content={post?.featureImage?.imageUrl} />
<meta name="keywords" content={post?.tags?.join(' ')} />
<meta
property="og:image"
content={post?.featureImage?.imageUrl}
key="ogimage"
/>
<meta property="og:site_name" content="oxen.io" key="ogsitename" />
<meta property="og:title" content={pageTitle} key="ogtitle" /> <meta property="og:title" content={pageTitle} key="ogtitle" />
<meta <meta
property="og:description" property="og:description"
content={post?.description} content={post?.description}
key="ogdesc" key="ogdesc"
/> />
<meta property="og:type" content="article" />
<meta name="image_src" content={imageURL} />
<meta name="image_url" content={imageURL} />
<meta name="keywords" content={post?.tags?.join(' ')} />
<meta property="og:image" content={imageURL} key="ogimage" />
<meta property="og:url" content={url} />
<link rel="canonical" href={url}></link>{' '}
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={pageTitle} />
<meta name="twitter:description" content={post?.description} />
<meta name="twitter:image" content={imageURL} />
</Head> </Head>
<div className="bg-alt"> <div className="bg-alt">

View File

@ -9,7 +9,7 @@ import { ArticleCardFeature } from '../../components/cards/ArticleCardFeature';
import { CardGrid } from '../../components/cards/CardGrid'; import { CardGrid } from '../../components/cards/CardGrid';
import { Contained } from '../../components/Contained'; import { Contained } from '../../components/Contained';
import { TagBlock } from '../../components/TagBlock'; import { TagBlock } from '../../components/TagBlock';
import { CMS } from '../../constants'; import { CMS, METADATA } from '../../constants';
import { CmsApi } from '../../services/cms'; import { CmsApi } from '../../services/cms';
import { PageType, setPageType } from '../../state/navigation'; import { PageType, setPageType } from '../../state/navigation';
import { IPost } from '../../types/cms'; import { IPost } from '../../types/cms';
@ -131,10 +131,28 @@ const Blog = (props: Props) => {
</Contained> </Contained>
); );
const pageTitle = generateTitle('Blog');
const featuredImageURL = featuredPost?.featureImage?.imageUrl;
return ( return (
<div> <div>
<Head> <Head>
<title>{generateTitle('Blog')}</title> <title>{pageTitle}</title>
<meta name="description" content={METADATA.BLOG.DESCRIPTION}></meta>
<meta property="og:title" content={pageTitle} key="ogtitle" />
<meta
property="og:description"
content={METADATA.BLOG.DESCRIPTION}
key="ogdesc"
/>
<meta property="og:type" content="website" />
<meta property="og:image" content={featuredImageURL} key="ogimage" />
<meta property="og:url" content={METADATA.BLOG.URL} />
<link rel="canonical" href={METADATA.BLOG.URL}></link>
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={pageTitle} />
<meta name="twitter:description" content={METADATA.BLOG.DESCRIPTION} />
<meta name="twitter:image" content={featuredImageURL} />
</Head> </Head>
<div className="flex flex-col w-full mt-12 mb-6 space-y-6 bg-alt"> <div className="flex flex-col w-full mt-12 mb-6 space-y-6 bg-alt">

View File

@ -2,26 +2,40 @@ import Head from 'next/head';
import React from 'react'; import React from 'react';
import { HomeHero } from '../components/HomeHero'; import { HomeHero } from '../components/HomeHero';
import { HomeHeroBubble } from '../components/HomeHeroBubble'; import { HomeHeroBubble } from '../components/HomeHeroBubble';
import { METADATA, NAVIGATION } from '../constants'; import { METADATA } from '../constants';
const Index = () => { const Index = () => {
const imageURL = `${METADATA.OXEN_HOST_URL}/site-banner.png`;
return ( return (
<> <>
<Head> <Head>
<title>{METADATA.TITLE_SUFFIX}</title> <title>{METADATA.TITLE_SUFFIX}</title>
<meta
name="description"
content={METADATA.SITE_META_DESCRIPTION}
></meta>
<meta <meta
property="og:title" property="og:title"
content="Oxen - Privacy should be simple." content={METADATA.TITLE_SUFFIX}
key="title" key="ogtitle"
/> />
<meta property="og:image" content={'site-banner.png'} key="ogimage" />
<meta property="og:site_name" content="oxen.io" key="ogsitename" />
<meta property="og:title" content={'Oxen'} key="ogtitle" />
<meta <meta
property="og:description" property="og:description"
content={NAVIGATION.SITE_META_DESCRIPTION} content={METADATA.SITE_META_DESCRIPTION}
key="ogdesc" key="ogdesc"
/> />
<meta property="og:type" content="website" />
<meta property="og:image" content={imageURL} key="ogimage" />
<meta property="og:url" content={METADATA.OXEN_HOST_URL} />
<link rel="canonical" href={METADATA.OXEN_HOST_URL}></link>
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={METADATA.TITLE_SUFFIX} />
<meta
name="twitter:description"
content={METADATA.SITE_META_DESCRIPTION}
/>
<meta name="twitter:image" content={imageURL} />
</Head> </Head>
{/* Only visible when no pages are open */} {/* Only visible when no pages are open */}

View File

@ -1,9 +1,9 @@
import Head from 'next/head'; import Head from 'next/head';
import React from 'react'; import React from 'react';
import { useMeasure } from 'react-use'; import { useMeasure } from 'react-use';
import { NAVIGATION } from '../constants'; import { NAVIGATION, METADATA } from '../constants';
import { SideMenuItem } from '../state/navigation'; import { SideMenuItem } from '../state/navigation';
import { generateTitle } from '../utils/metadata'; import { generateTitle, generateURL } from '../utils/metadata';
function Roadmap() { function Roadmap() {
const [ref, { width, height }] = useMeasure(); const [ref, { width, height }] = useMeasure();
@ -18,14 +18,36 @@ function Roadmap() {
console.log('roadmap ➡️ width:', width); console.log('roadmap ➡️ width:', width);
console.log('roadmap ➡️ ratio:', aspectRatio); console.log('roadmap ➡️ ratio:', aspectRatio);
const pageTitle = generateTitle(
NAVIGATION.SIDE_MENU_ITEMS[SideMenuItem.ROADMAP].label,
);
const pageURL = generateURL(
NAVIGATION.SIDE_MENU_ITEMS[SideMenuItem.ROADMAP].href,
);
const imageURL = `${METADATA.OXEN_HOST_URL}/site-banner.png`;
return ( return (
<> <>
<Head> <Head>
<title> <title>{pageTitle}</title>
{generateTitle( <meta name="description" content={METADATA.ROADMAP.DESCRIPTION}></meta>
NAVIGATION.SIDE_MENU_ITEMS[SideMenuItem.ROADMAP].label, <meta property="og:title" content={pageTitle} key="ogtitle" />
)} <meta
</title> property="og:description"
content={METADATA.ROADMAP.DESCRIPTION}
key="ogdesc"
/>
<meta property="og:type" content="website" />
<meta property="og:url" content={pageURL} />
<link rel="canonical" href={pageURL}></link>
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={pageTitle} />
<meta
name="twitter:description"
content={METADATA.ROADMAP.DESCRIPTION}
/>
<meta name="twitter:image" content={imageURL} />
</Head> </Head>
<div className="mx-4"> <div className="mx-4">
@ -46,7 +68,7 @@ function Roadmap() {
</h2> </h2>
<img <img
style={{ maxHeight: horizontal ? '90%' : 'auto' }} style={{ maxHeight: horizontal ? '90%' : 'auto' }}
src={`img/session-${horizontal ? 'x' : 'y'}.jpg`} src={`img/session-${horizontal ? 'x' : 'y'}.png`}
className="w-full rounded-md" className="w-full rounded-md"
/> />
</div> </div>

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 KiB

BIN
public/img/session-x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 267 KiB

BIN
public/img/session-y.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 873 KiB

View File

@ -6,3 +6,7 @@ export function generateTitle(prefix: string) {
? `${titleCase(prefix)} - ${METADATA.TITLE_SUFFIX}` ? `${titleCase(prefix)} - ${METADATA.TITLE_SUFFIX}`
: METADATA.TITLE_SUFFIX; : METADATA.TITLE_SUFFIX;
} }
export function generateURL(prefix: string) {
return prefix ? `${METADATA.OXEN_HOST_URL}${prefix}` : METADATA.OXEN_HOST_URL;
}