<>>
+const Footer = () => <>>;
-export default Footer;
\ No newline at end of file
+export default Footer;
diff --git a/src/components/PublicLayout/Header/HeaderButton/index.module.css b/src/components/PublicLayout/Header/HeaderButton/index.module.css
new file mode 100644
index 00000000..73c736dc
--- /dev/null
+++ b/src/components/PublicLayout/Header/HeaderButton/index.module.css
@@ -0,0 +1,20 @@
+.headerBtn {
+ border: none;
+ color: var(--gray-8);
+ padding: 4px 8px;
+ margin: 0 5px;
+}
+
+.headerBtn.active,
+.headerBtn.active:focus,
+.headerBtn:hover {
+ background-color: var(--gray-4);
+ border: none;
+ color: var(--gray-8);
+}
+
+.headerBtn:focus {
+ background-color: transparent;
+ border: none;
+ color: var(--gray-8);
+}
diff --git a/src/components/PublicLayout/Header/HeaderButton/index.tsx b/src/components/PublicLayout/Header/HeaderButton/index.tsx
new file mode 100644
index 00000000..1364cbd2
--- /dev/null
+++ b/src/components/PublicLayout/Header/HeaderButton/index.tsx
@@ -0,0 +1,36 @@
+import React from 'react';
+import { Button } from 'antd';
+import cx from 'classnames';
+
+import style from './index.module.css';
+
+interface OwnProps {
+ className?: string;
+ icon?: React.ReactElement;
+ isActive?: boolean;
+ onClick?: () => void;
+ title: string;
+}
+
+const HeaderButton = ({
+ className = '',
+ icon,
+ isActive = false,
+ onClick,
+ title,
+ ...props
+}: OwnProps) => (
+
+);
+
+export default HeaderButton;
diff --git a/src/components/PublicLayout/Header/index.module.css b/src/components/PublicLayout/Header/index.module.css
new file mode 100644
index 00000000..9cfba3a8
--- /dev/null
+++ b/src/components/PublicLayout/Header/index.module.css
@@ -0,0 +1,59 @@
+.mainHeader {
+ height: var(--main-header-height);
+ background-color: var(--gray-1);
+ padding: 12px 32px;
+ box-shadow: 0 0 8px 0 rgba(38, 67, 111, 0.25);
+ z-index: 1000;
+}
+.mainHeader * {
+ overflow: unset;
+}
+.mainHeader div[class$='-header-heading'],
+.mainHeader span[class$='-header-heading-title'],
+.mainHeader div[class$='-header-heading-left'] {
+ height: 100%;
+}
+.mainHeader span[class$='-header-heading-title'] {
+ margin-right: 28px;
+}
+.mainHeader div[class$='-header-heading-left'] {
+ margin: 0;
+}
+.mainHeader span[class$='-header-heading-extra'] {
+ display: flex;
+ align-items: center;
+}
+.mainHeader .logo {
+ height: 100%;
+ width: auto;
+}
+.mainHeader .resourcesMenuTrigger {
+ color: var(--gray-8);
+ margin: 5px 8px;
+}
+.mainHeader .resourcesMenuTrigger .resources {
+ margin-right: 8px;
+}
+
+.linkText {
+ padding-left: 8px;
+}
+
+.dropdown {
+ min-width: 120px !important;
+}
+
+.connectionWrapper {
+ border-left: 1px solid var(--gray-4);
+ display: flex;
+ margin-left: 8px;
+ gap: 8px;
+}
+
+.loginBtn {
+ padding: 5px 8px;
+}
+
+.signUpBtn {
+ padding: 5px 16px;
+}
diff --git a/src/components/PublicLayout/Header/index.tsx b/src/components/PublicLayout/Header/index.tsx
new file mode 100644
index 00000000..6d5e5228
--- /dev/null
+++ b/src/components/PublicLayout/Header/index.tsx
@@ -0,0 +1,182 @@
+import intl from 'react-intl-universal';
+import { useNavigate } from 'react-router';
+import {
+ DotChartOutlined,
+ DownOutlined,
+ FileSearchOutlined,
+ HomeOutlined,
+ LoginOutlined,
+ MailOutlined,
+ ReadOutlined,
+ TeamOutlined,
+} from '@ant-design/icons';
+import { Button, Dropdown, PageHeader, Typography } from 'antd';
+import { getFTEnvVarByKey } from 'helpers/EnvVariables';
+
+import ExternalLinkIcon from 'components/Icons/ExternalLinkIcon';
+import IncludeIcon from 'components/Icons/IncludeIcon';
+import LineStyleIcon from 'components/Icons/LineStyleIcon';
+import { trackVisitResources } from 'services/analytics';
+import { STATIC_ROUTES } from 'utils/routes';
+
+import HeaderButton from './HeaderButton';
+
+import style from './index.module.css';
+
+const iconSize = { width: 14, height: 14 };
+
+const { Text } = Typography;
+
+const Header = () => {
+ const navigate = useNavigate();
+ const ft_variant = getFTEnvVarByKey('VARIANT');
+ const ft_analyticsPage = getFTEnvVarByKey('ANALYTICS_PAGE');
+
+ return (
+ }
+ subTitle={
+
+ }
+ extra={[
+ }
+ title={intl.get('layout.main.menu.community')}
+ />,
+ {
+ trackVisitResources('website');
+ window.open('https://includedcc.org/', '_blank');
+ }}
+ >
+
+ {intl.get('layout.main.menu.website')}
+
+ ),
+ },
+ {
+ key: 'help',
+ label: (
+ {
+ trackVisitResources('help');
+ window.open('https://help.includedcc.org/docs/quick-start-guide', '_blank');
+ }}
+ >
+
+ {intl.get('layout.main.menu.help')}
+
+ ),
+ },
+ {
+ key: 'forum',
+ label: (
+ {
+ trackVisitResources('forum');
+ window.open('https://help.includedcc.org/discuss', '_blank');
+ }}
+ >
+
+ {intl.get('layout.main.menu.forum')}
+
+ ),
+ },
+ {
+ type: 'divider',
+ },
+ {
+ key: 'contact',
+ label: (
+ {
+ trackVisitResources('contact');
+ window.open(
+ 'https://app.smartsheet.com/b/form/514745159a004c2e987fff0aa16ceaac',
+ '_blank',
+ );
+ }}
+ >
+
+ {intl.get('layout.main.menu.contact')}
+
+ ),
+ },
+ ],
+ }}
+ >
+ e.preventDefault()} href="">
+ {intl.get('layout.main.menu.resources')}
+
+
+ ,
+
+ }
+ onClick={() => navigate(STATIC_ROUTES.LOGIN)}
+ title={intl.get('screen.loginPage.login')}
+ />
+
+
,
+ ]}
+ className={style.mainHeader}
+ />
+ );
+};
+
+export default Header;
diff --git a/src/components/PublicLayout/index.module.css b/src/components/PublicLayout/index.module.css
new file mode 100644
index 00000000..07f1d10c
--- /dev/null
+++ b/src/components/PublicLayout/index.module.css
@@ -0,0 +1,9 @@
+.mainLayout {
+ height: 100vh;
+}
+.mainLayout .mainContent {
+ flex: 1;
+ min-height: unset;
+ height: 100%;
+ overflow: auto;
+}
diff --git a/src/components/PublicLayout/index.tsx b/src/components/PublicLayout/index.tsx
new file mode 100644
index 00000000..9b08837c
--- /dev/null
+++ b/src/components/PublicLayout/index.tsx
@@ -0,0 +1,24 @@
+import React from 'react';
+import ScrollContent from '@ferlab/ui/core/layout/ScrollContent';
+import { Layout as AntLayout } from 'antd';
+
+import { MAIN_SCROLL_WRAPPER_ID } from 'common/constants';
+
+import Header from './Header';
+
+import styles from './index.module.css';
+
+interface OwnProps {
+ children: React.ReactElement;
+}
+
+const PublicLayout = ({ children }: OwnProps) => (
+
+
+
+ {children}
+
+
+);
+
+export default PublicLayout;
diff --git a/src/utils/routes.ts b/src/utils/routes.ts
index 5395ec9f..197864a2 100644
--- a/src/utils/routes.ts
+++ b/src/utils/routes.ts
@@ -4,6 +4,7 @@ export enum STATIC_ROUTES {
AUTH_REDIRECT = '/auth-redirect',
DASHBOARD = '/dashboard',
STUDIES = '/studies',
+ PUBLIC_STUDIES = '/public-studies',
PROFILE_SETTINGS = '/profile/settings',
COMMUNITY = '/community',
ERROR = '/error',
diff --git a/src/views/PublicStudies/index.tsx b/src/views/PublicStudies/index.tsx
new file mode 100644
index 00000000..7def7415
--- /dev/null
+++ b/src/views/PublicStudies/index.tsx
@@ -0,0 +1,9 @@
+import PublicLayout from 'components/PublicLayout';
+
+const PublicStudies = () => (
+
+
+
+);
+
+export default PublicStudies;