Compare commits
	
		
			5 Commits
		
	
	
		
			main
			...
			284bd1a034
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 284bd1a034 | |||
| 7b056454ab | |||
| d6dab34e11 | |||
| 3f1c8cb6aa | |||
| 52e4477422 | 
| @@ -8,13 +8,11 @@ name: Build and docker image | ||||
| jobs: | ||||
|   build: | ||||
|     name: Build | ||||
|     runs-on: k8s | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|     - name: Map docker socket | ||||
|       run: ln -s /var/run/user/1000/docker.sock /var/run/docker.sock | ||||
|  | ||||
|     - name: Install prerequisites | ||||
|       run: | | ||||
|         sudo apt-get update | ||||
|         sudo apt-get install -y xz-utils unzip | ||||
|  | ||||
|     - uses: https://gitea.com/actions/checkout@v4 | ||||
|  | ||||
| @@ -25,6 +23,8 @@ jobs: | ||||
|         username: ${{ secrets.docker_username }} | ||||
|         password: ${{ secrets.docker_password }} | ||||
|  | ||||
|     - name: Set up Docker Buildx | ||||
|       uses: https://github.com/docker/setup-buildx-action@v3 | ||||
|  | ||||
|     - name: Build | ||||
|       uses: https://github.com/docker/build-push-action@v2 | ||||
|   | ||||
| @@ -544,18 +544,214 @@ video { | ||||
|   --tw-backdrop-sepia:  ; | ||||
| } | ||||
|  | ||||
| .container { | ||||
|   width: 100%; | ||||
| } | ||||
|  | ||||
| @media (min-width: 640px) { | ||||
|   .container { | ||||
|     max-width: 640px; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @media (min-width: 768px) { | ||||
|   .container { | ||||
|     max-width: 768px; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @media (min-width: 1024px) { | ||||
|   .container { | ||||
|     max-width: 1024px; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @media (min-width: 1280px) { | ||||
|   .container { | ||||
|     max-width: 1280px; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @media (min-width: 1536px) { | ||||
|   .container { | ||||
|     max-width: 1536px; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .static { | ||||
|   position: static; | ||||
| } | ||||
|  | ||||
| .fixed { | ||||
|   position: fixed; | ||||
| } | ||||
|  | ||||
| .absolute { | ||||
|   position: absolute; | ||||
| } | ||||
|  | ||||
| .relative { | ||||
|   position: relative; | ||||
| } | ||||
|  | ||||
| .sticky { | ||||
|   position: sticky; | ||||
| } | ||||
|  | ||||
| .-start-3 { | ||||
|   inset-inline-start: -0.75rem; | ||||
| } | ||||
|  | ||||
| .my-4 { | ||||
|   margin-top: 1rem; | ||||
|   margin-bottom: 1rem; | ||||
| } | ||||
|  | ||||
| .mx-2 { | ||||
|   margin-left: 0.5rem; | ||||
|   margin-right: 0.5rem; | ||||
| } | ||||
|  | ||||
| .mb-1 { | ||||
|   margin-bottom: 0.25rem; | ||||
| } | ||||
|  | ||||
| .mb-10 { | ||||
|   margin-bottom: 2.5rem; | ||||
| } | ||||
|  | ||||
| .mb-2 { | ||||
|   margin-bottom: 0.5rem; | ||||
| } | ||||
|  | ||||
| .mb-4 { | ||||
|   margin-bottom: 1rem; | ||||
| } | ||||
|  | ||||
| .me-2 { | ||||
|   margin-inline-end: 0.5rem; | ||||
| } | ||||
|  | ||||
| .me-2\.5 { | ||||
|   margin-inline-end: 0.625rem; | ||||
| } | ||||
|  | ||||
| .ms-3 { | ||||
|   margin-inline-start: 0.75rem; | ||||
| } | ||||
|  | ||||
| .ms-6 { | ||||
|   margin-inline-start: 1.5rem; | ||||
| } | ||||
|  | ||||
| .mt-4 { | ||||
|   margin-top: 1rem; | ||||
| } | ||||
|  | ||||
| .mr-3 { | ||||
|   margin-right: 0.75rem; | ||||
| } | ||||
|  | ||||
| .block { | ||||
|   display: block; | ||||
| } | ||||
|  | ||||
| .inline-block { | ||||
|   display: inline-block; | ||||
| } | ||||
|  | ||||
| .flex { | ||||
|   display: flex; | ||||
| } | ||||
|  | ||||
| .inline-flex { | ||||
|   display: inline-flex; | ||||
| } | ||||
|  | ||||
| .h-2 { | ||||
|   height: 0.5rem; | ||||
| } | ||||
|  | ||||
| .h-2\.5 { | ||||
|   height: 0.625rem; | ||||
| } | ||||
|  | ||||
| .h-3 { | ||||
|   height: 0.75rem; | ||||
| } | ||||
|  | ||||
| .h-3\.5 { | ||||
|   height: 0.875rem; | ||||
| } | ||||
|  | ||||
| .h-6 { | ||||
|   height: 1.5rem; | ||||
| } | ||||
|  | ||||
| .h-full { | ||||
|   height: 100%; | ||||
| } | ||||
|  | ||||
| .h-screen { | ||||
|   height: 100vh; | ||||
| } | ||||
|  | ||||
| .h-32 { | ||||
|   height: 8rem; | ||||
| } | ||||
|  | ||||
| .w-2 { | ||||
|   width: 0.5rem; | ||||
| } | ||||
|  | ||||
| .w-2\.5 { | ||||
|   width: 0.625rem; | ||||
| } | ||||
|  | ||||
| .w-3 { | ||||
|   width: 0.75rem; | ||||
| } | ||||
|  | ||||
| .w-3\.5 { | ||||
|   width: 0.875rem; | ||||
| } | ||||
|  | ||||
| .w-6 { | ||||
|   width: 1.5rem; | ||||
| } | ||||
|  | ||||
| .w-screen { | ||||
|   width: 100vw; | ||||
| } | ||||
|  | ||||
| .w-full { | ||||
|   width: 100%; | ||||
| } | ||||
|  | ||||
| @keyframes bounce { | ||||
|   0%, 100% { | ||||
|     transform: translateY(-25%); | ||||
|     animation-timing-function: cubic-bezier(0.8,0,1,1); | ||||
|   } | ||||
|  | ||||
|   50% { | ||||
|     transform: none; | ||||
|     animation-timing-function: cubic-bezier(0,0,0.2,1); | ||||
|   } | ||||
| } | ||||
|  | ||||
| .animate-bounce { | ||||
|   animation: bounce 1s infinite; | ||||
| } | ||||
|  | ||||
| .cursor-not-allowed { | ||||
|   cursor: not-allowed; | ||||
| } | ||||
|  | ||||
| .flex-row { | ||||
|   flex-direction: row; | ||||
| } | ||||
|  | ||||
| .flex-col { | ||||
|   flex-direction: column; | ||||
| } | ||||
| @@ -572,35 +768,366 @@ video { | ||||
|   gap: 0.75rem; | ||||
| } | ||||
|  | ||||
| .gap-4 { | ||||
|   gap: 1rem; | ||||
| } | ||||
|  | ||||
| .rounded { | ||||
|   border-radius: 0.25rem; | ||||
| } | ||||
|  | ||||
| .rounded-full { | ||||
|   border-radius: 9999px; | ||||
| } | ||||
|  | ||||
| .rounded-lg { | ||||
|   border-radius: 0.5rem; | ||||
| } | ||||
|  | ||||
| .border { | ||||
|   border-width: 1px; | ||||
| } | ||||
|  | ||||
| .border-s { | ||||
|   border-inline-start-width: 1px; | ||||
| } | ||||
|  | ||||
| .border-gray-200 { | ||||
|   --tw-border-opacity: 1; | ||||
|   border-color: rgb(229 231 235 / var(--tw-border-opacity)); | ||||
| } | ||||
|  | ||||
| .border-blue-500 { | ||||
|   --tw-border-opacity: 1; | ||||
|   border-color: rgb(59 130 246 / var(--tw-border-opacity)); | ||||
| } | ||||
|  | ||||
| .border-white { | ||||
|   --tw-border-opacity: 1; | ||||
|   border-color: rgb(255 255 255 / var(--tw-border-opacity)); | ||||
| } | ||||
|  | ||||
| .bg-blue-100 { | ||||
|   --tw-bg-opacity: 1; | ||||
|   background-color: rgb(219 234 254 / var(--tw-bg-opacity)); | ||||
| } | ||||
|  | ||||
| .bg-blue-500 { | ||||
|   --tw-bg-opacity: 1; | ||||
|   background-color: rgb(59 130 246 / var(--tw-bg-opacity)); | ||||
| } | ||||
|  | ||||
| .bg-white { | ||||
|   --tw-bg-opacity: 1; | ||||
|   background-color: rgb(255 255 255 / var(--tw-bg-opacity)); | ||||
| } | ||||
|  | ||||
| .bg-gray-200 { | ||||
|   --tw-bg-opacity: 1; | ||||
|   background-color: rgb(229 231 235 / var(--tw-bg-opacity)); | ||||
| } | ||||
|  | ||||
| .bg-gray-800 { | ||||
|   --tw-bg-opacity: 1; | ||||
|   background-color: rgb(31 41 55 / var(--tw-bg-opacity)); | ||||
| } | ||||
|  | ||||
| .bg-gradient-to-r { | ||||
|   background-image: linear-gradient(to right, var(--tw-gradient-stops)); | ||||
| } | ||||
|  | ||||
| .from-purple-700 { | ||||
|   --tw-gradient-from: #7e22ce var(--tw-gradient-from-position); | ||||
|   --tw-gradient-to: rgb(126 34 206 / 0) var(--tw-gradient-to-position); | ||||
|   --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); | ||||
| } | ||||
|  | ||||
| .via-blue-900 { | ||||
|   --tw-gradient-to: rgb(30 58 138 / 0)  var(--tw-gradient-to-position); | ||||
|   --tw-gradient-stops: var(--tw-gradient-from), #1e3a8a var(--tw-gradient-via-position), var(--tw-gradient-to); | ||||
| } | ||||
|  | ||||
| .to-red-500 { | ||||
|   --tw-gradient-to: #ef4444 var(--tw-gradient-to-position); | ||||
| } | ||||
|  | ||||
| .p-4 { | ||||
|   padding: 1rem; | ||||
| } | ||||
|  | ||||
| .p-1 { | ||||
|   padding: 0.25rem; | ||||
| } | ||||
|  | ||||
| .p-5 { | ||||
|   padding: 1.25rem; | ||||
| } | ||||
|  | ||||
| .px-2 { | ||||
|   padding-left: 0.5rem; | ||||
|   padding-right: 0.5rem; | ||||
| } | ||||
|  | ||||
| .px-2\.5 { | ||||
|   padding-left: 0.625rem; | ||||
|   padding-right: 0.625rem; | ||||
| } | ||||
|  | ||||
| .px-4 { | ||||
|   padding-left: 1rem; | ||||
|   padding-right: 1rem; | ||||
| } | ||||
|  | ||||
| .py-0 { | ||||
|   padding-top: 0px; | ||||
|   padding-bottom: 0px; | ||||
| } | ||||
|  | ||||
| .py-0\.5 { | ||||
|   padding-top: 0.125rem; | ||||
|   padding-bottom: 0.125rem; | ||||
| } | ||||
|  | ||||
| .py-2 { | ||||
|   padding-top: 0.5rem; | ||||
|   padding-bottom: 0.5rem; | ||||
| } | ||||
|  | ||||
| .px-3 { | ||||
|   padding-left: 0.75rem; | ||||
|   padding-right: 0.75rem; | ||||
| } | ||||
|  | ||||
| .py-1 { | ||||
|   padding-top: 0.25rem; | ||||
|   padding-bottom: 0.25rem; | ||||
| } | ||||
|  | ||||
| .font-mono { | ||||
|   font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; | ||||
| } | ||||
|  | ||||
| .text-2xl { | ||||
|   font-size: 1.5rem; | ||||
|   line-height: 2rem; | ||||
| } | ||||
|  | ||||
| .text-6xl { | ||||
|   font-size: 3.75rem; | ||||
|   line-height: 1; | ||||
| } | ||||
|  | ||||
| .text-base { | ||||
|   font-size: 1rem; | ||||
|   line-height: 1.5rem; | ||||
| } | ||||
|  | ||||
| .text-lg { | ||||
|   font-size: 1.125rem; | ||||
|   line-height: 1.75rem; | ||||
| } | ||||
|  | ||||
| .text-sm { | ||||
|   font-size: 0.875rem; | ||||
|   line-height: 1.25rem; | ||||
| } | ||||
|  | ||||
| .font-bold { | ||||
|   font-weight: 700; | ||||
| } | ||||
|  | ||||
| .font-medium { | ||||
|   font-weight: 500; | ||||
| } | ||||
|  | ||||
| .font-normal { | ||||
|   font-weight: 400; | ||||
| } | ||||
|  | ||||
| .font-semibold { | ||||
|   font-weight: 600; | ||||
| } | ||||
|  | ||||
| .leading-none { | ||||
|   line-height: 1; | ||||
| } | ||||
|  | ||||
| .text-black { | ||||
|   --tw-text-opacity: 1; | ||||
|   color: rgb(0 0 0 / var(--tw-text-opacity)); | ||||
| } | ||||
|  | ||||
| .text-blue-800 { | ||||
|   --tw-text-opacity: 1; | ||||
|   color: rgb(30 64 175 / var(--tw-text-opacity)); | ||||
| } | ||||
|  | ||||
| .text-gray-400 { | ||||
|   --tw-text-opacity: 1; | ||||
|   color: rgb(156 163 175 / var(--tw-text-opacity)); | ||||
| } | ||||
|  | ||||
| .text-gray-500 { | ||||
|   --tw-text-opacity: 1; | ||||
|   color: rgb(107 114 128 / var(--tw-text-opacity)); | ||||
| } | ||||
|  | ||||
| .text-gray-900 { | ||||
|   --tw-text-opacity: 1; | ||||
|   color: rgb(17 24 39 / var(--tw-text-opacity)); | ||||
| } | ||||
|  | ||||
| .text-white { | ||||
|   --tw-text-opacity: 1; | ||||
|   color: rgb(255 255 255 / var(--tw-text-opacity)); | ||||
| } | ||||
|  | ||||
| .hover\:bg-blue-700:hover { | ||||
|   --tw-bg-opacity: 1; | ||||
|   background-color: rgb(29 78 216 / var(--tw-bg-opacity)); | ||||
| .text-blue-500 { | ||||
|   --tw-text-opacity: 1; | ||||
|   color: rgb(59 130 246 / var(--tw-text-opacity)); | ||||
| } | ||||
|  | ||||
| .shadow-md { | ||||
|   --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); | ||||
|   --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); | ||||
|   box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); | ||||
| } | ||||
|  | ||||
| .shadow-black\/5 { | ||||
|   --tw-shadow-color: rgb(0 0 0 / 0.05); | ||||
|   --tw-shadow: var(--tw-shadow-colored); | ||||
| } | ||||
|  | ||||
| .ring-8 { | ||||
|   --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); | ||||
|   --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(8px + var(--tw-ring-offset-width)) var(--tw-ring-color); | ||||
|   box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); | ||||
| } | ||||
|  | ||||
| .ring-white { | ||||
|   --tw-ring-opacity: 1; | ||||
|   --tw-ring-color: rgb(255 255 255 / var(--tw-ring-opacity)); | ||||
| } | ||||
|  | ||||
| .hover\:border-gray-200:hover { | ||||
|   --tw-border-opacity: 1; | ||||
|   border-color: rgb(229 231 235 / var(--tw-border-opacity)); | ||||
| } | ||||
|  | ||||
| .hover\:bg-blue-600:hover { | ||||
|   --tw-bg-opacity: 1; | ||||
|   background-color: rgb(37 99 235 / var(--tw-bg-opacity)); | ||||
| } | ||||
|  | ||||
| .hover\:bg-gray-100:hover { | ||||
|   --tw-bg-opacity: 1; | ||||
|   background-color: rgb(243 244 246 / var(--tw-bg-opacity)); | ||||
| } | ||||
|  | ||||
| .hover\:bg-gray-200:hover { | ||||
|   --tw-bg-opacity: 1; | ||||
|   background-color: rgb(229 231 235 / var(--tw-bg-opacity)); | ||||
| } | ||||
|  | ||||
| .hover\:text-blue-700:hover { | ||||
|   --tw-text-opacity: 1; | ||||
|   color: rgb(29 78 216 / var(--tw-text-opacity)); | ||||
| } | ||||
|  | ||||
| .hover\:text-gray-200:hover { | ||||
|   --tw-text-opacity: 1; | ||||
|   color: rgb(229 231 235 / var(--tw-text-opacity)); | ||||
| } | ||||
|  | ||||
| .focus\:z-10:focus { | ||||
|   z-index: 10; | ||||
| } | ||||
|  | ||||
| .focus\:text-blue-700:focus { | ||||
|   --tw-text-opacity: 1; | ||||
|   color: rgb(29 78 216 / var(--tw-text-opacity)); | ||||
| } | ||||
|  | ||||
| .focus\:outline-none:focus { | ||||
|   outline: 2px solid transparent; | ||||
|   outline-offset: 2px; | ||||
| } | ||||
|  | ||||
| .focus\:ring-4:focus { | ||||
|   --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); | ||||
|   --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color); | ||||
|   box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); | ||||
| } | ||||
|  | ||||
| .focus\:ring-gray-100:focus { | ||||
|   --tw-ring-opacity: 1; | ||||
|   --tw-ring-color: rgb(243 244 246 / var(--tw-ring-opacity)); | ||||
| } | ||||
|  | ||||
| @media (min-width: 768px) { | ||||
|   .md\:p-3 { | ||||
|     padding: 0.75rem; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @media (prefers-color-scheme: dark) { | ||||
|   .dark\:border-gray-600 { | ||||
|     --tw-border-opacity: 1; | ||||
|     border-color: rgb(75 85 99 / var(--tw-border-opacity)); | ||||
|   } | ||||
|  | ||||
|   .dark\:border-gray-700 { | ||||
|     --tw-border-opacity: 1; | ||||
|     border-color: rgb(55 65 81 / var(--tw-border-opacity)); | ||||
|   } | ||||
|  | ||||
|   .dark\:bg-blue-900 { | ||||
|     --tw-bg-opacity: 1; | ||||
|     background-color: rgb(30 58 138 / var(--tw-bg-opacity)); | ||||
|   } | ||||
|  | ||||
|   .dark\:bg-gray-800 { | ||||
|     --tw-bg-opacity: 1; | ||||
|     background-color: rgb(31 41 55 / var(--tw-bg-opacity)); | ||||
|   } | ||||
|  | ||||
|   .dark\:text-blue-300 { | ||||
|     --tw-text-opacity: 1; | ||||
|     color: rgb(147 197 253 / var(--tw-text-opacity)); | ||||
|   } | ||||
|  | ||||
|   .dark\:text-gray-400 { | ||||
|     --tw-text-opacity: 1; | ||||
|     color: rgb(156 163 175 / var(--tw-text-opacity)); | ||||
|   } | ||||
|  | ||||
|   .dark\:text-gray-500 { | ||||
|     --tw-text-opacity: 1; | ||||
|     color: rgb(107 114 128 / var(--tw-text-opacity)); | ||||
|   } | ||||
|  | ||||
|   .dark\:text-white { | ||||
|     --tw-text-opacity: 1; | ||||
|     color: rgb(255 255 255 / var(--tw-text-opacity)); | ||||
|   } | ||||
|  | ||||
|   .dark\:ring-gray-900 { | ||||
|     --tw-ring-opacity: 1; | ||||
|     --tw-ring-color: rgb(17 24 39 / var(--tw-ring-opacity)); | ||||
|   } | ||||
|  | ||||
|   .dark\:hover\:bg-gray-700:hover { | ||||
|     --tw-bg-opacity: 1; | ||||
|     background-color: rgb(55 65 81 / var(--tw-bg-opacity)); | ||||
|   } | ||||
|  | ||||
|   .dark\:hover\:text-white:hover { | ||||
|     --tw-text-opacity: 1; | ||||
|     color: rgb(255 255 255 / var(--tw-text-opacity)); | ||||
|   } | ||||
|  | ||||
|   .dark\:focus\:ring-gray-700:focus { | ||||
|     --tw-ring-opacity: 1; | ||||
|     --tw-ring-color: rgb(55 65 81 / var(--tw-ring-opacity)); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,15 +1,15 @@ | ||||
| import * as elements from "typed-html"; | ||||
| 
 | ||||
| const HomeLayout = ({ children }: elements.Children) => ` | ||||
| const BaseHTML = ({ children }: elements.Children) => ` | ||||
|     <head> | ||||
|         <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
|         <script src="https://unpkg.com/htmx.org@1.9.5"></script> | ||||
|         <link href="/public/style.css" rel="stylesheet" type="text/css" /> | ||||
|         <title>BETH STACK</title> | ||||
|         <title>Welcome!</title> | ||||
|     </head> | ||||
|     <body class="h-screen w-screen flex flex-col gap-3 items-center justify-center"> | ||||
|         ${children} | ||||
|     </body> | ||||
| `;
 | ||||
| 
 | ||||
| export { HomeLayout } | ||||
| export { BaseHTML } | ||||
							
								
								
									
										20
									
								
								frontend/src/components/footer.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								frontend/src/components/footer.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| import { FooterLink } from "../structs/footer_link"; | ||||
|  | ||||
| const Footer = ({ footer_links }: {footer_links: FooterLink[]}) => { | ||||
|     return ( | ||||
|         <footer class={'w-full h-32 bg-gray-800 flex items-center justify-center'}> | ||||
|             {footer_links.map((link) => { | ||||
|                 return ( | ||||
|                     <a href={link.url} class={'mx-2'}> | ||||
|                         <i class={`fas fa-${ | ||||
|                             link.icon_name | ||||
|                         } text-white`}></i> | ||||
|                     </a> | ||||
|                 ); | ||||
|             } | ||||
|             )} | ||||
|         </footer> | ||||
|     ); | ||||
| } | ||||
|  | ||||
| export { Footer } | ||||
							
								
								
									
										20
									
								
								frontend/src/components/hero.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								frontend/src/components/hero.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| const Hero = () => { | ||||
|     return ( | ||||
|         <div class="bg-gradient-to-r from-purple-700 via-blue-900 to-red-500 w-screen h-screen" id="hero"> | ||||
|             <div class="flex flex-col items-center justify-center h-full"> | ||||
|                 <div class="text-6xl font-bold text-white">Welcome to <span class="font-mono">moll.re</span></div> | ||||
|                 <div class="text-2xl text-white">An exciting journey!</div> | ||||
|                 <button class="px-4 py-2 my-4 text-lg font-semibold text-white bg-blue-500 rounded hover:bg-blue-600"> | ||||
|                     Explore | ||||
|                 </button> | ||||
|                 <div class="mt-4 animate-bounce"> | ||||
|                     <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-white animate-bounce" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | ||||
|                         <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path> | ||||
|                     </svg> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| export { Hero} | ||||
							
								
								
									
										20
									
								
								frontend/src/components/navigation.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								frontend/src/components/navigation.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
|  | ||||
| const Navigation = () => { | ||||
|     return( | ||||
|         <nav id={'header'} class={'flex-no-wrap sticky w-screen py-2 shadow-black/5'}> | ||||
|         <ul class="flex"> | ||||
|             <li class="mr-3"> | ||||
|                 <a class="inline-block border border-blue-500 rounded py-1 px-3 bg-blue-500 text-white" href="#">Active Pill</a> | ||||
|             </li> | ||||
|             <li class="mr-3"> | ||||
|                 <a class="inline-block border border-white rounded hover:border-gray-200 text-blue-500 hover:bg-gray-200 py-1 px-3" href="#">Pill</a> | ||||
|             </li> | ||||
|             <li class="mr-3"> | ||||
|                 <a class="inline-block py-1 px-3 text-gray-400 cursor-not-allowed" href="#">Disabled Pill</a> | ||||
|             </li> | ||||
|         </ul> | ||||
|         </nav> | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| export { Navigation } | ||||
							
								
								
									
										24
									
								
								frontend/src/components/timeline.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								frontend/src/components/timeline.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| import * as elements from "typed-html"; | ||||
| import { TimelineCard } from "./timeline_card"; | ||||
| import { TimelineItem } from "../structs/timeline_item"; | ||||
|  | ||||
| const Timeline = ({ timeline_items }: {timeline_items: TimelineItem[]}) => { | ||||
|     return ( | ||||
|         <div class={'container md:p-3'}> | ||||
|             <div class="flex flex-col items-center justify-center"> | ||||
|                 <div class="text-6xl font-bold text-black">Timeline</div> | ||||
|                 <div class="text-2xl text-black">A little about us</div> | ||||
|                 <ol class="relative border-s border-gray-200 dark:border-gray-700"> | ||||
|                     {timeline_items.map((item, index) => ( | ||||
|                         // <div class={`card ${index % 2 === 0 ? 'left' : 'right'}`}> | ||||
|                         <li class={`mb-10 ms-6 p-4 rounded-lg shadow-md ${index % 2 === 0 ? 'bg-white' : 'bg-gray-200'}`}> | ||||
|                             <TimelineCard {...item}/> | ||||
|                         </li> | ||||
|                     ))} | ||||
|                 </ol> | ||||
|             </div> | ||||
|         </div> | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| export { Timeline } | ||||
							
								
								
									
										22
									
								
								frontend/src/components/timeline_card.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								frontend/src/components/timeline_card.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| import * as elements from "typed-html"; | ||||
|  | ||||
| import { TimelineItem } from "../structs/timeline_item"; | ||||
|  | ||||
|  | ||||
|  | ||||
| const TimelineCard = ({ date_start, date_end, title, description, icon_name}: TimelineItem) => { | ||||
|     return ( | ||||
|         <div> | ||||
|             <span class="absolute flex items-center justify-center w-6 h-6 bg-blue-100 rounded-full -start-3 ring-8 ring-white dark:ring-gray-900 dark:bg-blue-900"> | ||||
|             <svg class="w-2.5 h-2.5 text-blue-800 dark:text-blue-300" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20"> | ||||
|                 <path d="M20 4a2 2 0 0 0-2-2h-2V1a1 1 0 0 0-2 0v1h-3V1a1 1 0 0 0-2 0v1H6V1a1 1 0 0 0-2 0v1H2a2 2 0 0 0-2 2v2h20V4ZM0 18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8H0v10Zm5-8h10a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2Z"/> | ||||
|             </svg> | ||||
|             </span> | ||||
|             <h3 class="mb-1 text-lg font-semibold text-gray-900">{ title }</h3> | ||||
|             <time class="block mb-2 text-sm font-normal leading-none text-gray-400 dark:text-gray-500">{ date_start.toLocaleDateString() } - { date_end.toLocaleDateString() }</time> | ||||
|             <p class="text-base font-normal text-gray-500 dark:text-gray-400">{ description }</p> | ||||
|         </div> | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| export { TimelineCard } | ||||
| @@ -2,26 +2,112 @@ import { Elysia } from "elysia"; | ||||
| import { html } from "@elysiajs/html"; | ||||
| import { staticPlugin } from "@elysiajs/static"; | ||||
|  | ||||
| // import { autoroutes } from "elysia-autoroutes"; | ||||
| // import { Store } from "./store"; | ||||
| // // @ts-ignore | ||||
| // import data from "../package.json"; | ||||
| import { BaseHTML } from "./base"; | ||||
| import { LandingPage } from "./pages/landing"; | ||||
|  | ||||
| import { HomeLayout } from "./layout"; | ||||
| import { Landing } from "./landing"; | ||||
| import { TimelineItem } from "./structs/timeline_item"; | ||||
| import { FooterLink } from "./structs/footer_link"; | ||||
|  | ||||
| const timeline_items: TimelineItem[] = [ | ||||
|   { | ||||
|     date_start: new Date(), | ||||
|     date_end: new Date(), | ||||
|     title: "First", | ||||
|     description: "Description number 1", | ||||
|     icon_name: "world", | ||||
|   }, | ||||
|   { | ||||
|     date_start: new Date(), | ||||
|     date_end: new Date(), | ||||
|     title: "Hello", | ||||
|     description: "Description number 2", | ||||
|     icon_name: "world", | ||||
|   }, | ||||
|   { | ||||
|     date_start: new Date(), | ||||
|     date_end: new Date(), | ||||
|     title: "Hello", | ||||
|     description: "Longer description number 3", | ||||
|     icon_name: "world", | ||||
|   }, | ||||
|   { | ||||
|     date_start: new Date(), | ||||
|     date_end: new Date(), | ||||
|     title: "Hello", | ||||
|     description: "Very looooooooooong description number 4", | ||||
|     icon_name: "world", | ||||
|   }, | ||||
|   { | ||||
|     date_start: new Date(), | ||||
|     date_end: new Date(), | ||||
|     title: "Hello", | ||||
|     description: "Description number 5", | ||||
|     icon_name: "world", | ||||
|   }, | ||||
|   { | ||||
|     date_start: new Date(), | ||||
|     date_end: new Date(), | ||||
|     title: "Hello", | ||||
|     description: "Description number 6", | ||||
|     icon_name: "world", | ||||
|   }, | ||||
|   { | ||||
|     date_start: new Date(), | ||||
|     date_end: new Date(), | ||||
|     title: "Hello", | ||||
|     description: "Description number 7", | ||||
|     icon_name: "world", | ||||
|   }, | ||||
|   { | ||||
|     date_start: new Date(), | ||||
|     date_end: new Date(), | ||||
|     title: "Hello", | ||||
|     description: "Description number 8", | ||||
|     icon_name: "world", | ||||
|   }, | ||||
| ]; | ||||
|  | ||||
|  | ||||
| const footer_links: FooterLink[] = [ | ||||
|   { | ||||
|     icon_name: "github", | ||||
|     title: "Github", | ||||
|     url: "https://github.com", | ||||
|   }, | ||||
|   { | ||||
|     icon_name: "twitter", | ||||
|     title: "Twitter", | ||||
|     url: "https://twitter.com", | ||||
|   }, | ||||
|   { | ||||
|     icon_name: "linkedin", | ||||
|     title: "LinkedIn", | ||||
|     url: "https://linkedin.com", | ||||
|   }, | ||||
|   { | ||||
|     icon_name: "instagram", | ||||
|     title: "Instagram", | ||||
|     url: "https://instagram.com", | ||||
|   }, | ||||
|   { | ||||
|     icon_name: "facebook", | ||||
|     title: "Facebook", | ||||
|     url: "https://facebook.com", | ||||
|   }, | ||||
| ]; | ||||
|  | ||||
| const content = { | ||||
|   'timeline_items': timeline_items, | ||||
|   'footer_links': footer_links, | ||||
| }; | ||||
|  | ||||
| export const server = new Elysia() | ||||
|   .use(html()) | ||||
|   .use(staticPlugin()) | ||||
|   // .get("/public/htmx.js", () => | ||||
|   //   Bun.file("node_modules/htmx.org/dist/htmx.min.js"), | ||||
|   // ) | ||||
|   // .state("store", new Store()) | ||||
|   // .state("version", data.version) | ||||
|   .onError(({ code, error }) => { | ||||
|     console.error(code, error); | ||||
|   }) | ||||
|   .get("/", ({html}) => html(<HomeLayout><Landing></Landing></HomeLayout>)) | ||||
|   .get("/", ({html}) => html(<BaseHTML><LandingPage{content}/></BaseHTML>)) | ||||
|   .post("/clicked", ()=> <div>Hello?</div>) | ||||
|  | ||||
|   .listen(Bun.env["PORT"] ?? 3000); | ||||
|   | ||||
| @@ -1,10 +0,0 @@ | ||||
| import * as elements from "typed-html"; | ||||
|  | ||||
| const Landing = ({ children }: elements.Children) => ` | ||||
|     <button hx-post="/clicked" hx-swap="outerHTML" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> | ||||
|         Click me | ||||
|     </button> | ||||
|     ${children} | ||||
| `; | ||||
|  | ||||
| export { Landing } | ||||
							
								
								
									
										20
									
								
								frontend/src/pages/landing.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								frontend/src/pages/landing.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| import * as elements from "typed-html"; | ||||
| import { Timeline } from "../components/timeline"; | ||||
| import { Navigation } from "../components/navigation"; | ||||
| import { Hero } from "../components/hero"; | ||||
| import { Footer } from "../components/footer"; | ||||
|  | ||||
|  | ||||
| const LandingPage = ({ content }: Dict) => { | ||||
|     return ( | ||||
|         <div class={'w-full h-full'}> | ||||
|             <Hero /> | ||||
|             <Navigation /> | ||||
|             <Timeline {content['timeline_items']}/> | ||||
|             <Footer {content['footer_links']}/> | ||||
|         </div> | ||||
|     ); | ||||
| }; | ||||
|  | ||||
|  | ||||
| export { LandingPage } | ||||
							
								
								
									
										0
									
								
								frontend/src/pages/portfolio.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								frontend/src/pages/portfolio.tsx
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										7
									
								
								frontend/src/structs/footer_link.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								frontend/src/structs/footer_link.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| type FooterLink = { | ||||
|     icon_name: string; | ||||
|     title: string; | ||||
|     url: string; | ||||
| } | ||||
|  | ||||
| export { FooterLink } | ||||
							
								
								
									
										9
									
								
								frontend/src/structs/timeline_item.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								frontend/src/structs/timeline_item.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| type TimelineItem = { | ||||
|     date_start: Date; | ||||
|     date_end: Date; | ||||
|     title: string; | ||||
|     description: string; | ||||
|     icon_name: string; | ||||
| } | ||||
|  | ||||
| export { TimelineItem } | ||||
		Reference in New Issue
	
	Block a user