diff --git a/src/components/Layout/Header/index.tsx b/src/components/Layout/Header/index.tsx
new file mode 100644
index 0000000000..1cab3605d2
--- /dev/null
+++ b/src/components/Layout/Header/index.tsx
@@ -0,0 +1,160 @@
+import React from 'react'
+import {View} from 'react-native'
+import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+import {useNavigation} from '@react-navigation/native'
+
+import {NavigationProp} from '#/lib/routes/types'
+import {isIOS} from '#/platform/detection'
+import {useSetDrawerOpen} from '#/state/shell'
+import {
+ atoms as a,
+ useBreakpoints,
+ useGutterStyles,
+ useTheme,
+ ViewStyleProp,
+} from '#/alf'
+import {Button, ButtonIcon} from '#/components/Button'
+import {ArrowLeft_Stroke2_Corner0_Rounded as ArrowLeft} from '#/components/icons/Arrow'
+import {Menu_Stroke2_Corner0_Rounded as Menu} from '#/components/icons/Menu'
+import {Text} from '#/components/Typography'
+
+const BUTTON_VISUAL_ALIGNMENT_OFFSET = 3
+const BUTTON_SIZE = 34 // small button
+
+export function Outer({children}: {children: React.ReactNode}) {
+ const t = useTheme()
+ const gutter = useGutterStyles()
+
+ return (
+
+ {children}
+
+ )
+}
+
+export function Content({children}: {children: React.ReactNode}) {
+ return (
+
+ {children}
+
+ )
+}
+
+export function Slot({
+ children,
+ style,
+}: {children?: React.ReactNode} & ViewStyleProp) {
+ return (
+
+ {children}
+
+ )
+}
+
+export function BackButton() {
+ const {_} = useLingui()
+ const navigation = useNavigation()
+
+ const onPressBack = React.useCallback(() => {
+ if (navigation.canGoBack()) {
+ navigation.goBack()
+ } else {
+ navigation.navigate('Home')
+ }
+ }, [navigation])
+
+ return (
+
+
+
+ )
+}
+
+export function MenuButton() {
+ const {_} = useLingui()
+ const setDrawerOpen = useSetDrawerOpen()
+ const {gtMobile} = useBreakpoints()
+
+ const onPress = React.useCallback(() => {
+ setDrawerOpen(true)
+ }, [setDrawerOpen])
+
+ return gtMobile ? null : (
+
+
+
+ )
+}
+
+export function TitleText({children}: {children: React.ReactNode}) {
+ const {gtMobile} = useBreakpoints()
+ return (
+
+ {children}
+
+ )
+}
+
+export function SubtitleText({children}: {children: React.ReactNode}) {
+ const t = useTheme()
+ return (
+
+ {children}
+
+ )
+}
diff --git a/src/components/Layout/index.tsx b/src/components/Layout/index.tsx
new file mode 100644
index 0000000000..26308a54c0
--- /dev/null
+++ b/src/components/Layout/index.tsx
@@ -0,0 +1,183 @@
+import React, {useContext, useMemo} from 'react'
+import {StyleSheet, View, ViewProps, ViewStyle} from 'react-native'
+import {StyleProp} from 'react-native'
+import {
+ KeyboardAwareScrollView,
+ KeyboardAwareScrollViewProps,
+} from 'react-native-keyboard-controller'
+import Animated, {AnimatedScrollViewProps} from 'react-native-reanimated'
+import {useSafeAreaInsets} from 'react-native-safe-area-context'
+
+import {isWeb} from '#/platform/detection'
+import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
+
+export * as Header from '#/components/Layout/Header'
+
+// Every screen should have a Layout component wrapping it.
+// This component provides a default padding for the top of the screen.
+// This allows certain screens to avoid the top padding if they want to.
+
+const LayoutContext = React.createContext({
+ withinScreen: false,
+ topPaddingDisabled: false,
+ withinScrollView: false,
+})
+
+export type ScreenProps = React.ComponentProps & {
+ disableTopPadding?: boolean
+ style?: StyleProp
+}
+
+/**
+ * Every screen should have a Layout.Screen component wrapping it.
+ * This component provides a default padding for the top of the screen
+ * and height/minHeight
+ */
+export const Screen = React.memo(function Screen({
+ disableTopPadding = false,
+ style,
+ ...props
+}: ScreenProps) {
+ const {top} = useSafeAreaInsets()
+ const context = useMemo(
+ () => ({
+ withinScreen: true,
+ topPaddingDisabled: disableTopPadding,
+ withinScrollView: false,
+ }),
+ [disableTopPadding],
+ )
+ return (
+
+ {isWeb && }
+
+
+ )
+})
+
+export type ContentProps = AnimatedScrollViewProps & {
+ style?: StyleProp
+ contentContainerStyle?: StyleProp
+}
+
+export const Content = React.memo(function Content({
+ children,
+ style,
+ contentContainerStyle,
+ ...props
+}: ContentProps) {
+ const context = useContext(LayoutContext)
+ const newContext = useMemo(
+ () => ({...context, withinScrollView: true}),
+ [context],
+ )
+ return (
+
+
+ {isWeb ? (
+ // @ts-ignore web only -esb
+ {children}
+ ) : (
+ children
+ )}
+
+
+ )
+})
+
+export type KeyboardAwareContentProps = KeyboardAwareScrollViewProps & {
+ children: React.ReactNode
+ contentContainerStyle?: StyleProp
+}
+
+export const KeyboardAwareContent = React.forwardRef(function LayoutScrollView(
+ {children, style, contentContainerStyle, ...props}: KeyboardAwareContentProps,
+ _ref: React.Ref,
+) {
+ return (
+
+ {isWeb ? {children} : children}
+
+ )
+})
+
+export const WebCenterBorders = React.forwardRef(function LayoutContent() {
+ const t = useTheme()
+ const {gtMobile} = useBreakpoints()
+ return gtMobile ? (
+
+ ) : null
+})
+
+export const Center = React.forwardRef(function LayoutContent(
+ {children, style, ...props}: ViewProps,
+ ref: React.Ref,
+) {
+ const {gtMobile} = useBreakpoints()
+ return (
+
+ {children}
+
+ )
+})
+
+const styles = StyleSheet.create({
+ scrollViewCommonStyles: {
+ width: '100%',
+ },
+ scrollViewContentContainer: {
+ paddingBottom: 100,
+ },
+})