+
@@ -44,53 +55,10 @@ export default function Index() {
-
-
- {[
- {
- src: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAwIiBoZWlnaHQ9IjgwMCIgdmlld0JveD0iMCAwIDgwMCA4MDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSI4MDAiIGhlaWdodD0iODAwIiBmaWxsPSIjMjEyMTIxIi8+CjxnIGZpbHRlcj0idXJsKCNmaWx0ZXIwX2RkXzEyNl81MykiPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTU4Ny45NDcgNTI3Ljc2OEM1OTIuMjAxIDU4Mi40MTggNTkyLjIwMSA2MDguMDM2IDU5Mi4yMDEgNjM2SDQ2NS43NTZDNDY1Ljc1NiA2MjkuOTA5IDQ2NS44NjUgNjI0LjMzNyA0NjUuOTc1IDYxOC42ODdDNDY2LjMxNyA2MDEuMTIzIDQ2Ni42NzQgNTgyLjgwNyA0NjMuODI4IDU0NS44MTlDNDYwLjA2NyA0OTEuNjY3IDQzNi43NDggNDc5LjYzNCAzOTMuODcxIDQ3OS42MzRIMzU1Ljg4M0gxOTVWMzgxLjEwOUgzOTkuODg5QzQ1NC4wNDkgMzgxLjEwOSA0ODEuMTMgMzY0LjYzMyA0ODEuMTMgMzIxLjAxMUM0ODEuMTMgMjgyLjY1NCA0NTQuMDQ5IDI1OS40MSAzOTkuODg5IDI1OS40MUgxOTVWMTYzSDQyMi40NTZDNTQ1LjA2OSAxNjMgNjA2IDIyMC45MTIgNjA2IDMxMy40MkM2MDYgMzgyLjYxMyA1NjMuMTIzIDQyNy43MzkgNTA1LjIwMSA0MzUuMjZDNTU0LjA5NiA0NDUuMDM3IDU4Mi42ODEgNDcyLjg2NSA1ODcuOTQ3IDUyNy43NjhaIiBmaWxsPSIjRThGMkZGIi8+CjxwYXRoIGQ9Ik0xOTUgNjM2VjU2Mi41NTNIMzI4LjY5N0MzNTEuMDI5IDU2Mi41NTMgMzU1Ljg3OCA1NzkuMTE2IDM1NS44NzggNTg4Ljk5NFY2MzZIMTk1WiIgZmlsbD0iI0U4RjJGRiIvPgo8L2c+CjxkZWZzPgo8ZmlsdGVyIGlkPSJmaWx0ZXIwX2RkXzEyNl81MyIgeD0iMTMxIiB5PSI5OSIgd2lkdGg9IjUzOSIgaGVpZ2h0PSI2MDEiIGZpbHRlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY29sb3ItaW50ZXJwb2xhdGlvbi1maWx0ZXJzPSJzUkdCIj4KPGZlRmxvb2QgZmxvb2Qtb3BhY2l0eT0iMCIgcmVzdWx0PSJCYWNrZ3JvdW5kSW1hZ2VGaXgiLz4KPGZlQ29sb3JNYXRyaXggaW49IlNvdXJjZUFscGhhIiB0eXBlPSJtYXRyaXgiIHZhbHVlcz0iMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMTI3IDAiIHJlc3VsdD0iaGFyZEFscGhhIi8+CjxmZU9mZnNldC8+CjxmZUdhdXNzaWFuQmx1ciBzdGREZXZpYXRpb249IjI4Ii8+CjxmZUNvbXBvc2l0ZSBpbjI9ImhhcmRBbHBoYSIgb3BlcmF0b3I9Im91dCIvPgo8ZmVDb2xvck1hdHJpeCB0eXBlPSJtYXRyaXgiIHZhbHVlcz0iMCAwIDAgMCAwLjIyMzUyOSAwIDAgMCAwIDAuNTcyNTQ5IDAgMCAwIDAgMSAwIDAgMCAxIDAiLz4KPGZlQmxlbmQgbW9kZT0ibm9ybWFsIiBpbjI9IkJhY2tncm91bmRJbWFnZUZpeCIgcmVzdWx0PSJlZmZlY3QxX2Ryb3BTaGFkb3dfMTI2XzUzIi8+CjxmZUNvbG9yTWF0cml4IGluPSJTb3VyY2VBbHBoYSIgdHlwZT0ibWF0cml4IiB2YWx1ZXM9IjAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDEyNyAwIiByZXN1bHQ9ImhhcmRBbHBoYSIvPgo8ZmVPZmZzZXQvPgo8ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSIzMiIvPgo8ZmVDb21wb3NpdGUgaW4yPSJoYXJkQWxwaGEiIG9wZXJhdG9yPSJvdXQiLz4KPGZlQ29sb3JNYXRyaXggdHlwZT0ibWF0cml4IiB2YWx1ZXM9IjAgMCAwIDAgMC4yMjM1MjkgMCAwIDAgMCAwLjU3MjU0OSAwIDAgMCAwIDEgMCAwIDAgMC45IDAiLz4KPGZlQmxlbmQgbW9kZT0ibm9ybWFsIiBpbjI9ImVmZmVjdDFfZHJvcFNoYWRvd18xMjZfNTMiIHJlc3VsdD0iZWZmZWN0Ml9kcm9wU2hhZG93XzEyNl81MyIvPgo8ZmVCbGVuZCBtb2RlPSJub3JtYWwiIGluPSJTb3VyY2VHcmFwaGljIiBpbjI9ImVmZmVjdDJfZHJvcFNoYWRvd18xMjZfNTMiIHJlc3VsdD0ic2hhcGUiLz4KPC9maWx0ZXI+CjwvZGVmcz4KPC9zdmc+Cg==",
- alt: "Remix.run",
- href: "https://remix.run/",
- },
- {
- src: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDEwIiBoZWlnaHQ9IjQwNCIgdmlld0JveD0iMCAwIDQxMCA0MDQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0zOTkuNjQxIDU5LjUyNDZMMjE1LjY0MyAzODguNTQ1QzIxMS44NDQgMzk1LjMzOCAyMDIuMDg0IDM5NS4zNzggMTk4LjIyOCAzODguNjE4TDEwLjU4MTcgNTkuNTU2M0M2LjM4MDg3IDUyLjE4OTYgMTIuNjgwMiA0My4yNjY1IDIxLjAyODEgNDQuNzU4NkwyMDUuMjIzIDc3LjY4MjRDMjA2LjM5OCA3Ny44OTI0IDIwNy42MDEgNzcuODkwNCAyMDguNzc2IDc3LjY3NjNMMzg5LjExOSA0NC44MDU4QzM5Ny40MzkgNDMuMjg5NCA0MDMuNzY4IDUyLjE0MzQgMzk5LjY0MSA1OS41MjQ2WiIgZmlsbD0idXJsKCNwYWludDBfbGluZWFyKSIvPgo8cGF0aCBkPSJNMjkyLjk2NSAxLjU3NDRMMTU2LjgwMSAyOC4yNTUyQzE1NC41NjMgMjguNjkzNyAxNTIuOTA2IDMwLjU5MDMgMTUyLjc3MSAzMi44NjY0TDE0NC4zOTUgMTc0LjMzQzE0NC4xOTggMTc3LjY2MiAxNDcuMjU4IDE4MC4yNDggMTUwLjUxIDE3OS40OThMMTg4LjQyIDE3MC43NDlDMTkxLjk2NyAxNjkuOTMxIDE5NS4xNzIgMTczLjA1NSAxOTQuNDQzIDE3Ni42MjJMMTgzLjE4IDIzMS43NzVDMTgyLjQyMiAyMzUuNDg3IDE4NS45MDcgMjM4LjY2MSAxODkuNTMyIDIzNy41NkwyMTIuOTQ3IDIzMC40NDZDMjE2LjU3NyAyMjkuMzQ0IDIyMC4wNjUgMjMyLjUyNyAyMTkuMjk3IDIzNi4yNDJMMjAxLjM5OCAzMjIuODc1QzIwMC4yNzggMzI4LjI5NCAyMDcuNDg2IDMzMS4yNDkgMjEwLjQ5MiAzMjYuNjAzTDIxMi41IDMyMy41TDMyMy40NTQgMTAyLjA3MkMzMjUuMzEyIDk4LjM2NDUgMzIyLjEwOCA5NC4xMzcgMzE4LjAzNiA5NC45MjI4TDI3OS4wMTQgMTAyLjQ1NEMyNzUuMzQ3IDEwMy4xNjEgMjcyLjIyNyA5OS43NDYgMjczLjI2MiA5Ni4xNTgzTDI5OC43MzEgNy44NjY4OUMyOTkuNzY3IDQuMjczMTQgMjk2LjYzNiAwLjg1NTE4MSAyOTIuOTY1IDEuNTc0NFoiIGZpbGw9InVybCgjcGFpbnQxX2xpbmVhcikiLz4KPGRlZnM+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQwX2xpbmVhciIgeDE9IjYuMDAwMTciIHkxPSIzMi45OTk5IiB4Mj0iMjM1IiB5Mj0iMzQ0IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CjxzdG9wIHN0b3AtY29sb3I9IiM0MUQxRkYiLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjQkQzNEZFIi8+CjwvbGluZWFyR3JhZGllbnQ+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQxX2xpbmVhciIgeDE9IjE5NC42NTEiIHkxPSI4LjgxODE4IiB4Mj0iMjM2LjA3NiIgeTI9IjI5Mi45ODkiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0ZGRUE4MyIvPgo8c3RvcCBvZmZzZXQ9IjAuMDgzMzMzMyIgc3RvcC1jb2xvcj0iI0ZGREQzNSIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNGRkE4MDAiLz4KPC9saW5lYXJHcmFkaWVudD4KPC9kZWZzPgo8L3N2Zz4K",
- alt: "Vite",
- href: "https://vitejs.dev/",
- },
-
- {
- src: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCAyNjIgMzMiPjxnIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1wYXRoPSJ1cmwoI3ByZWZpeF9fY2xpcDApIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGZpbGw9IiMzOGJkZjgiIGQ9Ik0yNyAwYy03LjIgMC0xMS43IDMuNi0xMy41IDEwLjggMi43LTMuNiA1Ljg1LTQuOTUgOS40NS00LjA1IDIuMDU0LjUxMyAzLjUyMiAyLjAwNCA1LjE0NyAzLjY1M0MzMC43NDQgMTMuMDkgMzMuODA4IDE2LjIgNDAuNSAxNi4yYzcuMiAwIDExLjctMy42IDEzLjUtMTAuOC0yLjcgMy42LTUuODUgNC45NS05LjQ1IDQuMDUtMi4wNTQtLjUxMy0zLjUyMi0yLjAwNC01LjE0Ny0zLjY1M0MzNi43NTYgMy4xMSAzMy42OTIgMCAyNyAwek0xMy41IDE2LjJDNi4zIDE2LjIgMS44IDE5LjggMCAyN2MyLjctMy42IDUuODUtNC45NSA5LjQ1LTQuMDUgMi4wNTQuNTE0IDMuNTIyIDIuMDA0IDUuMTQ3IDMuNjUzQzE3LjI0NCAyOS4yOSAyMC4zMDggMzIuNCAyNyAzMi40YzcuMiAwIDExLjctMy42IDEzLjUtMTAuOC0yLjcgMy42LTUuODUgNC45NS05LjQ1IDQuMDUtMi4wNTQtLjUxMy0zLjUyMi0yLjAwNC01LjE0Ny0zLjY1M0MyMy4yNTYgMTkuMzEgMjAuMTkyIDE2LjIgMTMuNSAxNi4yeiIvPjxwYXRoIGZpbGw9IiMwZjE3MmEiIGQ9Ik04MC45OTYgMTMuNjUyaC00LjcxMnY5LjEyYzAgMi40MzIgMS41OTYgMi4zOTQgNC43MTIgMi4yNDJWMjguN2MtNi4zMDguNzYtOC44MTYtLjk4OC04LjgxNi01LjkyOHYtOS4xMmgtMy40OTZWOS43aDMuNDk2VjQuNTk2bDQuMTA0LTEuMjE2VjkuN2g0LjcxMnYzLjk1MnpNOTguOTU4IDkuN2g0LjEwNHYxOWgtNC4xMDR2LTIuNzM2Yy0xLjQ0NCAyLjAxNC0zLjY4NiAzLjIzLTYuNjUgMy4yMy01LjE2OCAwLTkuNDYyLTQuMzctOS40NjItOS45OTQgMC01LjY2MiA0LjI5NC05Ljk5NCA5LjQ2Mi05Ljk5NCAyLjk2NCAwIDUuMjA2IDEuMjE2IDYuNjUgMy4xOTJWOS43em0tNi4wMDQgMTUuNThjMy40MiAwIDYuMDA0LTIuNTQ2IDYuMDA0LTYuMDggMC0zLjUzNC0yLjU4NC02LjA4LTYuMDA0LTYuMDgtMy40MiAwLTYuMDA0IDIuNTQ2LTYuMDA0IDYuMDggMCAzLjUzNCAyLjU4NCA2LjA4IDYuMDA0IDYuMDh6bTE2Ljk0OC0xOC40M2MtMS40NDQgMC0yLjYyMi0xLjIxNi0yLjYyMi0yLjYyMmEyLjYyNyAyLjYyNyAwIDAxMi42MjItMi42MjIgMi42MjcgMi42MjcgMCAwMTIuNjIyIDIuNjIyYzAgMS40MDYtMS4xNzggMi42MjItMi42MjIgMi42MjJ6TTEwNy44NSAyOC43di0xOWg0LjEwNHYxOWgtNC4xMDR6bTguODU0IDBWLjk2aDQuMTA0VjI4LjdoLTQuMTA0em0zMC43NDItMTloNC4zMzJsLTUuOTY2IDE5aC00LjAyOGwtMy45NTItMTIuODA2LTMuOTkgMTIuODA2aC00LjAyOGwtNS45NjYtMTloNC4zMzJsMy42ODYgMTMuMTEgMy45OS0xMy4xMWgzLjkxNGwzLjk1MiAxMy4xMSAzLjcyNC0xMy4xMXptOS40MjQtMi44NWMtMS40NDQgMC0yLjYyMi0xLjIxNi0yLjYyMi0yLjYyMmEyLjYyNyAyLjYyNyAwIDAxMi42MjItMi42MjIgMi42MjcgMi42MjcgMCAwMTIuNjIyIDIuNjIyYzAgMS40MDYtMS4xNzggMi42MjItMi42MjIgMi42MjJ6bS0yLjA1MiAyMS44NXYtMTloNC4xMDR2MTloLTQuMTA0em0xOC44NDgtMTkuNDk0YzQuMjU2IDAgNy4yOTYgMi44ODggNy4yOTYgNy44MjhWMjguN2gtNC4xMDRWMTcuNDUyYzAtMi44ODgtMS42NzItNC40MDgtNC4yNTYtNC40MDgtMi42OTggMC00LjgyNiAxLjU5Ni00LjgyNiA1LjQ3MlYyOC43aC00LjEwNHYtMTloNC4xMDR2Mi40MzJjMS4yNTQtMS45NzYgMy4zMDYtMi45MjYgNS44OS0yLjkyNnpNMjAwLjQxOCAyLjFoNC4xMDR2MjYuNmgtNC4xMDR2LTIuNzM2Yy0xLjQ0NCAyLjAxNC0zLjY4NiAzLjIzLTYuNjUgMy4yMy01LjE2OCAwLTkuNDYyLTQuMzctOS40NjItOS45OTQgMC01LjY2MiA0LjI5NC05Ljk5NCA5LjQ2Mi05Ljk5NCAyLjk2NCAwIDUuMjA2IDEuMjE2IDYuNjUgMy4xOTJWMi4xem0tNi4wMDQgMjMuMThjMy40MiAwIDYuMDA0LTIuNTQ2IDYuMDA0LTYuMDggMC0zLjUzNC0yLjU4NC02LjA4LTYuMDA0LTYuMDgtMy40MiAwLTYuMDA0IDIuNTQ2LTYuMDA0IDYuMDggMCAzLjUzNCAyLjU4NCA2LjA4IDYuMDA0IDYuMDh6bTIzLjg2NCAzLjkxNGMtNS43MzggMC0xMC4wMzItNC4zNy0xMC4wMzItOS45OTQgMC01LjY2MiA0LjI5NC05Ljk5NCAxMC4wMzItOS45OTQgMy43MjQgMCA2Ljk1NCAxLjkzOCA4LjQ3NCA0LjkwMmwtMy41MzQgMi4wNTJjLS44MzYtMS43ODYtMi42OTgtMi45MjYtNC45NzgtMi45MjYtMy4zNDQgMC01Ljg5IDIuNTQ2LTUuODkgNS45NjYgMCAzLjQyIDIuNTQ2IDUuOTY2IDUuODkgNS45NjYgMi4yOCAwIDQuMTQyLTEuMTc4IDUuMDU0LTIuOTI2bDMuNTM0IDIuMDE0Yy0xLjU5NiAzLjAwMi00LjgyNiA0Ljk0LTguNTUgNC45NHptMTUuMzE0LTE0LjI1YzAgMy40NTggMTAuMjIyIDEuMzY4IDEwLjIyMiA4LjM5OCAwIDMuOC0zLjMwNiA1Ljg1Mi03LjQxIDUuODUyLTMuOCAwLTYuNTM2LTEuNzEtNy43NTItNC40NDZsMy41MzQtMi4wNTJjLjYwOCAxLjcxIDIuMTI4IDIuNzM2IDQuMjE4IDIuNzM2IDEuODI0IDAgMy4yMy0uNjA4IDMuMjMtMi4xMjggMC0zLjM4Mi0xMC4yMjItMS40ODItMTAuMjIyLTguMjg0IDAtMy41NzIgMy4wNzgtNS44MTQgNi45NTQtNS44MTQgMy4xMTYgMCA1LjcgMS40NDQgNy4wMyAzLjk1MmwtMy40NTggMS45MzhjLS42ODQtMS40ODItMi4wMTQtMi4xNjYtMy41NzItMi4xNjYtMS40ODIgMC0yLjc3NC42NDYtMi43NzQgMi4wMTR6bTE3LjUxOCAwYzAgMy40NTggMTAuMjIyIDEuMzY4IDEwLjIyMiA4LjM5OCAwIDMuOC0zLjMwNiA1Ljg1Mi03LjQxIDUuODUyLTMuOCAwLTYuNTM2LTEuNzEtNy43NTItNC40NDZsMy41MzQtMi4wNTJjLjYwOCAxLjcxIDIuMTI4IDIuNzM2IDQuMjE4IDIuNzM2IDEuODI0IDAgMy4yMy0uNjA4IDMuMjMtMi4xMjggMC0zLjM4Mi0xMC4yMjItMS40ODItMTAuMjIyLTguMjg0IDAtMy41NzIgMy4wNzgtNS44MTQgNi45NTQtNS44MTQgMy4xMTYgMCA1LjcgMS40NDQgNy4wMyAzLjk1MmwtMy40NTggMS45MzhjLS42ODQtMS40ODItMi4wMTQtMi4xNjYtMy41NzItMi4xNjYtMS40ODIgMC0yLjc3NC42NDYtMi43NzQgMi4wMTR6Ii8+PC9nPjxkZWZzPjxjbGlwUGF0aCBpZD0icHJlZml4X19jbGlwMCI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTAgMGgyNjJ2MzIuNEgweiIvPjwvY2xpcFBhdGg+PC9kZWZzPjwvc3ZnPg==",
- alt: "Tailwind",
- href: "https://tailwindcss.com",
- },
- {
- src: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTY1IiBoZWlnaHQ9IjE2NSIgdmlld0JveD0iMCAwIDE2NSAxNjUiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0xMjAuODMxIDU3LjI1NDNMODQuNjkzIDEwOS41MDVDODQuMzA5OSAxMTAuMDU5IDgzLjc1NTggMTEwLjQ3NCA4My4xMTQ4IDExMC42ODdDODIuNDczOCAxMTAuOSA4MS43ODA5IDExMC44OTggODEuMTQxMiAxMTAuNjg0QzgwLjUwMTUgMTEwLjQ2OSA3OS45NSAxMTAuMDUyIDc5LjU3MDIgMTA5LjQ5N0M3OS4xOTA1IDEwOC45NDEgNzkuMDAzMiAxMDguMjc3IDc5LjAzNyAxMDcuNjA2TDgwLjQ4MzMgNzguNzU4Mkw1Ny4xMzQzIDczLjgwNjRDNTYuNjM1MyA3My43MDA3IDU2LjE3MDQgNzMuNDc0IDU1Ljc4MDcgNzMuMTQ2NUM1NS4zOTEgNzIuODE5MSA1NS4wODg1IDcyLjQwMDkgNTQuOTAwMSA3MS45MjlDNTQuNzExNyA3MS40NTcxIDU0LjY0MzIgNzAuOTQ2MSA1NC43MDA2IDcwLjQ0MTJDNTQuNzU4IDY5LjkzNjQgNTQuOTM5NSA2OS40NTMyIDU1LjIyOTEgNjkuMDM0NUw5MS4zNjc1IDE2Ljc4MzdDOTEuNzUwNyAxNi4yMjk0IDkyLjMwNDggMTUuODE0NSA5Mi45NDU4IDE1LjYwMThDOTMuNTg2OSAxNS4zODkxIDk0LjI3OTggMTUuMzkwMiA5NC45MTk2IDE1LjYwNTFDOTUuNTU5MyAxNS44MTk5IDk2LjExMDkgMTYuMjM2NyA5Ni40OTA2IDE2Ljc5MjNDOTYuODcwMyAxNy4zNDc4IDk3LjA1NzUgMTguMDExNyA5Ny4wMjM2IDE4LjY4MzNMOTUuNTc3MyA0Ny41MzE0TDExOC45MjYgNTIuNDgyOEMxMTkuNDI1IDUyLjU4ODUgMTE5Ljg5IDUyLjgxNTIgMTIwLjI4IDUzLjE0MjZDMTIwLjY3IDUzLjQ3MDEgMTIwLjk3MiA1My44ODgzIDEyMS4xNiA1NC4zNjAyQzEyMS4zNDkgNTQuODMyMSAxMjEuNDE3IDU1LjM0MzEgMTIxLjM2IDU1Ljg0NzlDMTIxLjMwMyA1Ni4zNTI4IDEyMS4xMjEgNTYuODM2IDEyMC44MzEgNTcuMjU0N0wxMjAuODMxIDU3LjI1NDNaIiBmaWxsPSIjRkNDNzJCIi8+CjxwYXRoIGQ9Ik04Mi45ODY2IDE1My4zNDNDODIuMDI1NCAxNTMuMzQ0IDgxLjA3MzUgMTUzLjE1NiA4MC4xODU1IDE1Mi43ODhDNzkuMjk3NSAxNTIuNDIgNzguNDkwOSAxNTEuODggNzcuODEyMiAxNTEuMkw0My42NjU4IDExNy4wNTZDNDIuMjk5OCAxMTUuNjgzIDQxLjUzNDEgMTEzLjgyNCA0MS41MzY2IDExMS44ODdDNDEuNTM5MiAxMDkuOTUgNDIuMzA5OCAxMDguMDkyIDQzLjY3OTYgMTA2LjcyM0M0NS4wNDkzIDEwNS4zNTMgNDYuOTA2NCAxMDQuNTgyIDQ4Ljg0MzUgMTA0LjU3OUM1MC43ODA3IDEwNC41NzcgNTIuNjM5OSAxMDUuMzQyIDU0LjAxMzQgMTA2LjcwOEw4Mi45ODY2IDEzNS42NzhMMTQ2LjEwNSA3Mi41NjI2QzE0Ny40ODEgNzEuMjA4OCAxNDkuMzM2IDcwLjQ1MzYgMTUxLjI2NiA3MC40NjE1QzE1My4xOTcgNzAuNDY5MyAxNTUuMDQ2IDcxLjIzOTYgMTU2LjQxIDcyLjYwNDVDMTU3Ljc3NSA3My45Njk1IDE1OC41NDYgNzUuODE4NCAxNTguNTU0IDc3Ljc0ODdDMTU4LjU2MSA3OS42NzkgMTU3LjgwNiA4MS41MzQyIDE1Ni40NTIgODIuOTEwMUw4OC4xNTk3IDE1MS4yQzg3LjQ4MTEgMTUxLjg4MSA4Ni42NzQ3IDE1Mi40MiA4NS43ODY5IDE1Mi43ODhDODQuODk5MiAxNTMuMTU2IDgzLjk0NzUgMTUzLjM0NCA4Mi45ODY2IDE1My4zNDNaIiBmaWxsPSIjNzI5QjFCIi8+CjxwYXRoIGQ9Ik04Mi45NTcyIDE1My4zNDNDODMuOTE4NCAxNTMuMzQ0IDg0Ljg3MDMgMTUzLjE1NiA4NS43NTgzIDE1Mi43ODhDODYuNjQ2MyAxNTIuNDIgODcuNDUyOCAxNTEuODggODguMTMxNiAxNTEuMkwxMjIuMjc4IDExNy4wNTZDMTIzLjY0NCAxMTUuNjgzIDEyNC40MSAxMTMuODI0IDEyNC40MDcgMTExLjg4N0MxMjQuNDA1IDEwOS45NSAxMjMuNjM0IDEwOC4wOTIgMTIyLjI2NCAxMDYuNzIzQzEyMC44OTQgMTA1LjM1MyAxMTkuMDM3IDEwNC41ODIgMTE3LjEgMTA0LjU3OUMxMTUuMTYzIDEwNC41NzcgMTEzLjMwNCAxMDUuMzQyIDExMS45MyAxMDYuNzA4TDgyLjk1NzIgMTM1LjY3OEwxOS44Mzg5IDcyLjU2MjZDMTguNDYyOSA3MS4yMDg4IDE2LjYwNzcgNzAuNDUzNiAxNC42Nzc1IDcwLjQ2MTVDMTIuNzQ3MiA3MC40NjkzIDEwLjg5ODIgNzEuMjM5NiA5LjUzMzMxIDcyLjYwNDVDOC4xNjgzOSA3My45Njk1IDcuMzk4MTEgNzUuODE4NCA3LjM5MDI1IDc3Ljc0ODdDNy4zODIzOSA3OS42NzkgOC4xMzc1OSA4MS41MzQyIDkuNDkxMzUgODIuOTEwMUw3Ny43ODQgMTUxLjJDNzguNDYyNyAxNTEuODgxIDc5LjI2OTEgMTUyLjQyIDgwLjE1NjggMTUyLjc4OEM4MS4wNDQ2IDE1My4xNTYgODEuOTk2MyAxNTMuMzQ0IDgyLjk1NzIgMTUzLjM0M1oiIGZpbGw9IiM3MjlCMUIiIGZpbGwtb3BhY2l0eT0iMC41Ii8+Cjwvc3ZnPgo=",
- alt: "Vitest",
- href: "https://vitest.dev",
- },
-
- {
- src: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgZmlsbD0ibm9uZSIgdmVyc2lvbj0iMS4xIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+Cjx0aXRsZT5UeXBlU2NyaXB0IGxvZ288L3RpdGxlPgogPHJlY3Qgd2lkdGg9IjUxMiIgaGVpZ2h0PSI1MTIiIHJ4PSI1MCIgZmlsbD0iIzMxNzhjNiIvPgogPHBhdGggZD0ibTMxNyA0MDd2NTBjOC4xIDQuMiAxOCA3LjMgMjkgOS40czIzIDMuMSAzNSAzLjFjMTIgMCAyMy0xLjEgMzQtMy40IDExLTIuMyAyMC02LjEgMjgtMTEgOC4xLTUuMyAxNS0xMiAxOS0yMXM3LjEtMTkgNy4xLTMyYzAtOS4xLTEuNC0xNy00LjEtMjRzLTYuNi0xMy0xMi0xOGMtNS4xLTUuMy0xMS0xMC0xOC0xNHMtMTUtOC4yLTI0LTEyYy02LjYtMi43LTEyLTUuMy0xOC03LjktNS4yLTIuNi05LjctNS4yLTEzLTcuOC0zLjctMi43LTYuNS01LjUtOC41LTguNC0yLTMtMy02LjMtMy0xMCAwLTMuNCAwLjg5LTYuNSAyLjctOS4zczQuMy01LjEgNy41LTcuMWMzLjItMiA3LjItMy41IDEyLTQuNiA0LjctMS4xIDkuOS0xLjYgMTYtMS42IDQuMiAwIDguNiAwLjMxIDEzIDAuOTQgNC42IDAuNjMgOS4zIDEuNiAxNCAyLjkgNC43IDEuMyA5LjMgMi45IDE0IDQuOSA0LjQgMiA4LjUgNC4zIDEyIDYuOXYtNDdjLTcuNi0yLjktMTYtNS4xLTI1LTYuNXMtMTktMi4xLTMxLTIuMWMtMTIgMC0yMyAxLjMtMzQgMy44cy0yMCA2LjUtMjggMTJjLTguMSA1LjQtMTQgMTItMTkgMjEtNC43IDguNC03IDE4LTcgMzAgMCAxNSA0LjMgMjggMTMgMzggOC42IDExIDIyIDE5IDM5IDI3IDYuOSAyLjggMTMgNS42IDE5IDguM3MxMSA1LjUgMTUgOC40YzQuMyAyLjkgNy43IDYuMSAxMCA5LjUgMi41IDMuNCAzLjggNy40IDMuOCAxMiAwIDMuMi0wLjc4IDYuMi0yLjMgOXMtMy45IDUuMi03LjEgNy4yLTcuMSAzLjYtMTIgNC44Yy00LjcgMS4xLTEwIDEuNy0xNyAxLjctMTEgMC0yMi0xLjktMzItNS43LTExLTMuOC0yMS05LjUtMzAtMTd6bS04NC0xMjNoNjR2LTQxaC0xNzl2NDFoNjR2MTgzaDUxeiIgY2xpcC1ydWxlPSJldmVub2RkIiBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHN0eWxlPSJmaWxsOiNmZmYiLz4KPC9zdmc+Cg==",
- alt: "TypeScript",
- href: "https://typescriptlang.org",
- },
- ].map((img) => (
-
-
-
- ))}
-
-
{t("hi")}
- Crafted with ❤️
+ Crafted with ❤️ / Time without timezone mismatch {timezoneDate}
)
diff --git a/app/utils/dates.test.ts b/app/utils/dates.test.ts
new file mode 100644
index 000000000..1f0a0b497
--- /dev/null
+++ b/app/utils/dates.test.ts
@@ -0,0 +1,57 @@
+import { convertDateToUserTz, convertTz } from "app/utils/dates"
+
+describe("convertTz Test suite", () => {
+ it("should convert date to user tz if there is a difference (1h)", () => {
+ const date = new Date()
+ const serverTz = "Europe/London"
+ const convertedServerDate = convertTz(date, serverTz)
+ const userTz = "Europe/Berlin"
+ const convertedClientDate = convertTz(date, userTz)
+ const differenceInMinutes = Math.round(
+ Math.abs(convertedClientDate.getTime() - convertedServerDate.getTime()) / 60000
+ )
+ expect(differenceInMinutes).toBe(60)
+ })
+
+ it("should stay the same if no difference", () => {
+ const date = new Date()
+ const serverTz = "Europe/London"
+ const convertedServerDate = convertTz(date, serverTz)
+ const userTz = "Europe/London"
+ const convertedClientDate = convertTz(date, userTz)
+ const differenceInMinutes = Math.round(
+ Math.abs(convertedClientDate.getTime() - convertedServerDate.getTime()) / 60000
+ )
+ expect(differenceInMinutes).toBe(0)
+ })
+})
+
+describe("convertDateToUserTz Test suite", () => {
+ it("should convert date to user tz if there is a difference", () => {
+ const request = new Request("http://localhost:3000", {
+ headers: {
+ "CH-time-zone": "Europe/London",
+ },
+ method: "GET",
+ })
+ const date = new Date()
+ const serverDate = convertTz(date, "Europe/Berlin")
+ const clientDate = convertDateToUserTz(date, request)
+ const differenceInMinutes = Math.round(Math.abs(clientDate.getTime() - serverDate.getTime()) / 60000)
+ expect(differenceInMinutes).toBe(60)
+ })
+
+ it("should convert date to user tz if there is a difference", () => {
+ const request = new Request("http://localhost:3000", {
+ headers: {
+ "CH-time-zone": "Europe/London",
+ },
+ method: "GET",
+ })
+ const date = new Date()
+ const serverDate = convertTz(date, "Europe/London")
+ const clientDate = convertDateToUserTz(date, request)
+ const differenceInMinutes = Math.round(Math.abs(clientDate.getTime() - serverDate.getTime()) / 60000)
+ expect(differenceInMinutes).toBe(0)
+ })
+})
diff --git a/app/utils/dates.ts b/app/utils/dates.ts
new file mode 100644
index 000000000..e8905772f
--- /dev/null
+++ b/app/utils/dates.ts
@@ -0,0 +1,14 @@
+import { getTimeZone } from "../services/client-hints"
+
+export function convertTz(date: string | Date, tzString: string) {
+ const dateToConvert = typeof date === "string" ? new Date(date) : date
+ // Convert to the target timezone
+ const convertedDate = new Date(dateToConvert.toLocaleString("en-US", { timeZone: tzString }))
+ return convertedDate
+}
+
+export function convertDateToUserTz(date: Date | string, request?: Request) {
+ const tz = getTimeZone(request)
+ const dates = convertTz(date, tz)
+ return dates
+}