diff --git a/ui/src/components/albumGallery/AlbumBox.tsx b/ui/src/components/albumGallery/AlbumBox.tsx
index f0dd946..06fe567 100644
--- a/ui/src/components/albumGallery/AlbumBox.tsx
+++ b/ui/src/components/albumGallery/AlbumBox.tsx
@@ -25,7 +25,7 @@ const AlbumBoxImage = ({ src, ...props }: AlbumBoxImageProps) => {
   let placeholder = null
   if (!loaded) {
     placeholder = (
-      <div className="bg-gray-100 animate-pulse w-full h-full rounded-lg absolute top-0"></div>
+      <div className="bg-gray-100 dark:bg-[#191c1f] animate-pulse w-full h-full rounded-lg absolute top-0"></div>
     )
   }
 
@@ -44,7 +44,7 @@ type AlbumBoxProps = {
 
 export const AlbumBox = ({ album, customLink, ...props }: AlbumBoxProps) => {
   const wrapperClasses =
-    'inline-block text-center text-gray-900 mx-3 my-2 xs:h-60 xs:w-[220px]'
+    'inline-block text-center text-gray-900 dark:text-gray-200 mx-3 my-2 xs:h-60 xs:w-[220px]'
 
   if (album) {
     return (
diff --git a/ui/src/components/header/Header.tsx b/ui/src/components/header/Header.tsx
index e0d5362..5c8c11d 100644
--- a/ui/src/components/header/Header.tsx
+++ b/ui/src/components/header/Header.tsx
@@ -11,7 +11,7 @@ const Header = () => {
   return (
     <div
       className={classNames(
-        'sticky top-0 z-10 bg-white flex items-center justify-between py-3 px-4 lg:px-8 lg:pt-4 shadow-separator lg:shadow-none',
+        'sticky top-0 z-10 bg-white dark:bg-dark-bg flex items-center justify-between py-3 px-4 lg:px-8 lg:pt-4 shadow-separator lg:shadow-none',
         { 'mr-[404px]': pinned }
       )}
     >
diff --git a/ui/src/components/layout/MainMenu.tsx b/ui/src/components/layout/MainMenu.tsx
index 76681d8..035ffe0 100644
--- a/ui/src/components/layout/MainMenu.tsx
+++ b/ui/src/components/layout/MainMenu.tsx
@@ -63,7 +63,7 @@ const MenuButton = ({
 }
 
 const MenuSeparator = () => (
-  <hr className="hidden lg:block my-3 border-gray-200" />
+  <hr className="hidden lg:block my-3 border-gray-200 dark:border-[#3B3B3B]" />
 )
 
 export const MainMenu = () => {
@@ -81,15 +81,15 @@ export const MainMenu = () => {
     !!faceDetectionEnabledQuery?.data?.siteInfo?.faceDetectionEnabled
 
   return (
-    <div className="fixed w-full bottom-0 lg:bottom-auto lg:top-[84px] z-30 bg-white shadow-separator lg:shadow-none lg:w-[240px] lg:ml-8 lg:mr-5 flex-shrink-0">
+    <div className="fixed w-full bottom-0 lg:bottom-auto lg:top-[84px] z-30 bg-white dark:bg-dark-bg shadow-separator lg:shadow-none lg:w-[240px] lg:ml-8 lg:mr-5 flex-shrink-0">
       <ul className="flex justify-around py-2 px-2 max-w-lg mx-auto lg:flex-col lg:p-0">
         <MenuButton
           to="/timeline"
           exact
           label={t('sidemenu.photos', 'Timeline')}
           background="#8ac5f4"
-          activeClasses="ring-[#f1f8ff] bg-[#f1f8ff]"
-          className="outline-none focus:ring-2 focus:ring-blue-200 focus:ring-offset-2"
+          activeClasses="ring-[#f1f8ff] bg-[#f1f8ff] dark:bg-[#171f28] dark:ring-[#171f28]"
+          className="outline-none focus:ring-2 focus:ring-blue-200 dark:focus:ring-[#283849] focus:ring-offset-2"
           icon={
             <svg viewBox="0 0 24 24" fill="white">
               <path d="M5.62503136,14 L9.60031266,17.978 L5.38724257,24 L2.99995461,24 C1.45289603,24 0.179346174,22.8289699 0.0173498575,21.3249546 L5.62503136,14 Z M15.7557572,10 L24.0173027,21.526562 C23.7684095,22.9323278 22.5405695,24 21.0633614,24 L21.0633614,24 L5.88324257,24 L15.7557572,10 Z"></path>
@@ -101,7 +101,7 @@ export const MainMenu = () => {
           exact
           label={t('sidemenu.albums', 'Albums')}
           background="#ff797b"
-          activeClasses="ring-[#fff1f2] bg-[#fff1f2]"
+          activeClasses="ring-[#fff1f2] bg-[#fff1f2] dark:ring-[#1d1516] dark:bg-[#1d1516]"
           className="outline-none focus:ring-2 focus:ring-red-200 focus:ring-offset-2"
           icon={
             <svg viewBox="0 0 24 24" fill="white">
@@ -115,7 +115,7 @@ export const MainMenu = () => {
             exact
             label={t('sidemenu.places', 'Places')}
             background="#92e072"
-            activeClasses="ring-[#e3fee5] bg-[#e3fee5]"
+            activeClasses="ring-[#e3fee5] bg-[#e3fee5] dark:ring-[#0c1c0f] dark:bg-[#0c1c0f]"
             className="outline-none focus:ring-2 focus:ring-green-100 focus:ring-offset-2"
             icon={
               <svg viewBox="0 0 24 24" fill="white">
@@ -130,7 +130,7 @@ export const MainMenu = () => {
             exact
             label={t('sidemenu.people', 'People')}
             background="#fbcd78"
-            activeClasses="ring-[#fff7e4] bg-[#fff7e4]"
+            activeClasses="ring-[#fff7e4] bg-[#fff7e4] dark:ring-[#1a1b13] dark:bg-[#1a1b13]"
             className="outline-none focus:ring-2 focus:ring-yellow-100 focus:ring-offset-2"
             icon={
               <svg viewBox="0 0 24 24" fill="white">
@@ -145,7 +145,7 @@ export const MainMenu = () => {
           exact
           label={t('sidemenu.settings', 'Settings')}
           background="#aacbd0"
-          activeClasses="ring-[#e4f0f8] bg-[#e4f0f8]"
+          activeClasses="ring-[#e4f0f8] bg-[#e4f0f8] dark:ring-[#0f1f23] dark:bg-[#0f1f23]"
           className="outline-none focus:ring-2 focus:ring-gray-200 focus:ring-offset-2"
           icon={
             <svg viewBox="0 0 24 24" fill="white">
diff --git a/ui/src/components/sidebar/Sidebar.tsx b/ui/src/components/sidebar/Sidebar.tsx
index 2688ff9..090ce53 100644
--- a/ui/src/components/sidebar/Sidebar.tsx
+++ b/ui/src/components/sidebar/Sidebar.tsx
@@ -89,7 +89,7 @@ export const Sidebar = () => {
 
   return (
     <div
-      className={`fixed top-[72px] bg-white bottom-0 w-full overflow-y-auto transform transition-transform motion-reduce:transition-none ${
+      className={`fixed top-[72px] bg-white dark:bg-dark-bg2 bottom-0 w-full overflow-y-auto transform transition-transform motion-reduce:transition-none ${
         content == null && !pinned ? 'translate-x-full' : 'translate-x-0'
       } ${
         pinned ? 'lg:border-l' : 'lg:shadow-separator'
diff --git a/ui/src/index.css b/ui/src/index.css
index 37adde1..299943b 100644
--- a/ui/src/index.css
+++ b/ui/src/index.css
@@ -12,6 +12,10 @@ html {
   font-family: 'Source Sans Pro', sans-serif;
 }
 
+body.dark {
+  @apply bg-dark-bg text-dark-text;
+}
+
 @tailwind base;
 @tailwind components;
 @tailwind utilities;
diff --git a/ui/src/index.tsx b/ui/src/index.tsx
index c2ab514..8024eff 100644
--- a/ui/src/index.tsx
+++ b/ui/src/index.tsx
@@ -24,6 +24,8 @@ const Main = () => (
   </ApolloProvider>
 )
 
+document.getElementsByTagName('body')[0].classList.add('dark')
+
 ReactDOM.render(<Main />, document.getElementById('root'))
 
 serviceWorkerRegistration.register()
diff --git a/ui/src/primitives/form/Dropdown.tsx b/ui/src/primitives/form/Dropdown.tsx
index 81950a1..c68dc96 100644
--- a/ui/src/primitives/form/Dropdown.tsx
+++ b/ui/src/primitives/form/Dropdown.tsx
@@ -44,6 +44,7 @@ const Dropdown = ({
     <DropdownStyledSelect
       className={classNames(
         'bg-gray-50 px-2 py-0.5 pr-6 rounded border border-gray-200 focus:outline-none focus:border-blue-300 text-[#222] hover:bg-gray-100 disabled:hover:bg-gray-50 disabled:text-gray-500 disabled:cursor-default',
+        'dark:bg-dark-input-bg dark:border-dark-input-border dark:text-dark-input-text dark:focus:border-blue-300',
         className
       )}
       value={selected}
diff --git a/ui/src/primitives/form/Input.tsx b/ui/src/primitives/form/Input.tsx
index 6d9cd97..9b6613a 100644
--- a/ui/src/primitives/form/Input.tsx
+++ b/ui/src/primitives/form/Input.tsx
@@ -58,6 +58,7 @@ export const TextField = forwardRef(
         onKeyUp={keyUpEvent}
         className={classNames(
           'block border rounded-md focus:ring-2 focus:outline-none px-2',
+          'dark:bg-dark-input-bg dark:border-dark-input-border',
           variant,
           sizeVariant == 'big' ? 'py-2' : 'py-1',
           { 'w-full': fullWidth },
@@ -147,6 +148,7 @@ type ButtonProps = {
 const buttonStyles = ({ variant, background }: ButtonProps) =>
   classNames(
     'px-6 py-0.5 rounded border border-gray-200 focus:outline-none focus:border-blue-300 text-[#222] hover:bg-gray-100 whitespace-nowrap',
+    'dark:bg-dark-input-bg dark:border-dark-input-border dark:text-dark-input-text dark:focus:border-blue-300',
     variant == 'negative' &&
       'text-red-600 hover:bg-red-600 hover:border-red-700 hover:text-white transition-colors focus:border-red-600 focus:hover:border-red-700',
     variant == 'positive' &&
diff --git a/ui/tailwind.config.js b/ui/tailwind.config.js
index 36c0a1e..227ee40 100644
--- a/ui/tailwind.config.js
+++ b/ui/tailwind.config.js
@@ -1,7 +1,7 @@
 module.exports = {
   mode: 'jit',
   purge: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
-  darkMode: false, // or 'media' or 'class'
+  darkMode: 'class',
   theme: {
     extend: {
       screens: {
@@ -23,6 +23,16 @@ module.exports = {
           800: '#006624',
           900: '#00541d',
         },
+        dark: {
+          bg: '#24292e',
+          bg2: '#30363e',
+          text: '#fafafa',
+          input: {
+            bg: '#383e46',
+            border: '#4a515a',
+            text: '#ccdbe4',
+          },
+        },
       },
     },
   },
