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) {
const { isMobile, isDesktop, isHuge } = useContext(ScreenContext);
const { isDesktop, isHuge } = useContext(ScreenContext);
const [ref, { width }] = useMeasure();
const widthOfCardPx = 200;
@ -37,25 +37,7 @@ export function CardGrid({ rows, children }: Props) {
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>
<div ref={ref} className={classNames('flex flex-col', spacingY)}>
{_.chunk(cards, grouping).map(group => (
@ -69,7 +51,7 @@ export function CardGrid({ rows, children }: Props) {
))}
</div>
</Contained>
)}
}
</>
);
}

View File

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

View File

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

View File

@ -1,6 +1,18 @@
const METADATA = {
OXEN_HOST_URL: 'https://oxen.io',
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;

View File

@ -127,8 +127,6 @@ const NAVIGATION = {
SIDE_MENU_ITEMS,
BLOG_REGEX: /^\/(blog)([?tag=[\w-]*)?([?&]page=[0-9]{1,3})?/,
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;

View File

@ -2,9 +2,9 @@ import classNames from 'classnames';
import Head from 'next/head';
import React, { useContext } from 'react';
// import _404 from '../assets/svgs/404.svg';
import { UI } from '../constants';
import { UI, METADATA } from '../constants';
import { ScreenContext } from '../contexts/screen';
import { generateTitle } from '../utils/metadata';
import { generateTitle, generateURL } from '../utils/metadata';
function oxen404() {
const { isMobile, isTablet, isDesktop, isHuge } = useContext(ScreenContext);
@ -47,10 +47,24 @@ function oxen404() {
width: '9rem',
};
const pageTitle = generateTitle('404');
const pageURL = generateURL('/404');
return (
<div className="flex items-center justify-center flex-grow h-full">
<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>
<div style={wrapperStyles} className="flex items-center flex-grow">
@ -65,13 +79,13 @@ function oxen404() {
<div style={_404SectionStyles} className="absolute left-0 z-50">
<h1
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
</h1>
<p
style={_404TextStyles}
className="text-4xl tracking-tight font-sans text-primary"
className="font-sans text-4xl tracking-tight text-primary"
>
Nothing found here.
</p>

View File

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

View File

@ -63,6 +63,9 @@ function App({ Component, pageProps }: AppProps) {
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1"
></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>
<Layout>

View File

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

View File

@ -9,7 +9,7 @@ import { ArticleCardFeature } from '../../components/cards/ArticleCardFeature';
import { CardGrid } from '../../components/cards/CardGrid';
import { Contained } from '../../components/Contained';
import { TagBlock } from '../../components/TagBlock';
import { CMS } from '../../constants';
import { CMS, METADATA } from '../../constants';
import { CmsApi } from '../../services/cms';
import { PageType, setPageType } from '../../state/navigation';
import { IPost } from '../../types/cms';
@ -131,10 +131,28 @@ const Blog = (props: Props) => {
</Contained>
);
const pageTitle = generateTitle('Blog');
const featuredImageURL = featuredPost?.featureImage?.imageUrl;
return (
<div>
<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>
<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 { HomeHero } from '../components/HomeHero';
import { HomeHeroBubble } from '../components/HomeHeroBubble';
import { METADATA, NAVIGATION } from '../constants';
import { METADATA } from '../constants';
const Index = () => {
const imageURL = `${METADATA.OXEN_HOST_URL}/site-banner.png`;
return (
<>
<Head>
<title>{METADATA.TITLE_SUFFIX}</title>
<meta
name="description"
content={METADATA.SITE_META_DESCRIPTION}
></meta>
<meta
property="og:title"
content="Oxen - Privacy should be simple."
key="title"
content={METADATA.TITLE_SUFFIX}
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
property="og:description"
content={NAVIGATION.SITE_META_DESCRIPTION}
content={METADATA.SITE_META_DESCRIPTION}
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>
{/* Only visible when no pages are open */}

View File

@ -1,9 +1,9 @@
import Head from 'next/head';
import React from 'react';
import { useMeasure } from 'react-use';
import { NAVIGATION } from '../constants';
import { NAVIGATION, METADATA } from '../constants';
import { SideMenuItem } from '../state/navigation';
import { generateTitle } from '../utils/metadata';
import { generateTitle, generateURL } from '../utils/metadata';
function Roadmap() {
const [ref, { width, height }] = useMeasure();
@ -18,14 +18,36 @@ function Roadmap() {
console.log('roadmap ➡️ width:', width);
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 (
<>
<Head>
<title>
{generateTitle(
NAVIGATION.SIDE_MENU_ITEMS[SideMenuItem.ROADMAP].label,
)}
</title>
<title>{pageTitle}</title>
<meta name="description" content={METADATA.ROADMAP.DESCRIPTION}></meta>
<meta property="og:title" content={pageTitle} key="ogtitle" />
<meta
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>
<div className="mx-4">
@ -46,7 +68,7 @@ function Roadmap() {
</h2>
<img
style={{ maxHeight: horizontal ? '90%' : 'auto' }}
src={`img/session-${horizontal ? 'x' : 'y'}.jpg`}
src={`img/session-${horizontal ? 'x' : 'y'}.png`}
className="w-full rounded-md"
/>
</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}`
: METADATA.TITLE_SUFFIX;
}
export function generateURL(prefix: string) {
return prefix ? `${METADATA.OXEN_HOST_URL}${prefix}` : METADATA.OXEN_HOST_URL;
}