├── .env.EXAMPLE ├── .github └── FUNDING.yml ├── .gitignore ├── .prettierrc ├── .vscode ├── extensions.json └── launch.json ├── LICENSE.md ├── README.md ├── astro.config.mjs ├── bun.lockb ├── package.json ├── public ├── cloud.webp ├── icons │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ └── site.webmanifest ├── inter │ ├── regular.woff2 │ ├── semibold.woff2 │ └── thin.woff2 ├── kmenu │ ├── 1.png │ ├── 1.webp │ ├── 2.png │ ├── 2.webp │ ├── 3.png │ └── 3.webp ├── map.webp ├── og.png ├── plane-shadow.webp ├── plane.webp └── robots.txt ├── src ├── components │ ├── Footer.astro │ ├── Header.astro │ ├── Layout.astro │ ├── Main.astro │ └── icons │ │ ├── Index.astro │ │ ├── Link.astro │ │ └── RightArrow.astro ├── env.d.ts ├── global.css └── pages │ ├── 404.astro │ ├── api │ ├── last-visitor.ts │ └── locate.ts │ └── index.astro ├── tailwind.config.mjs └── tsconfig.json /.env.EXAMPLE: -------------------------------------------------------------------------------- 1 | UPSTASH_REDIS_REST_URL="" 2 | UPSTASH_REDIS_REST_TOKEN="" 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: haaarshsingh 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | # generated types 4 | .astro/ 5 | 6 | # dependencies 7 | node_modules/ 8 | 9 | # logs 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | pnpm-debug.log* 14 | 15 | 16 | # environment variables 17 | .env 18 | .env.local 19 | .env.production 20 | 21 | # macOS-specific files 22 | .DS_Store 23 | 24 | # jetbrains setting folder 25 | .idea/ 26 | .vercel 27 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["prettier-plugin-astro", "prettier-plugin-tailwindcss"], 3 | "overrides": [ 4 | { 5 | "files": "**/*.astro", 6 | "options": { 7 | "parser": "astro" 8 | } 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["astro-build.astro-vscode"], 3 | "unwantedRecommendations": [] 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "command": "./node_modules/.bin/astro dev", 6 | "name": "Development server", 7 | "request": "launch", 8 | "type": "node-terminal" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2025 Harsh Singh 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | 12 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 13 | 14 | 0. You just DO WHAT THE FUCK YOU WANT TO. 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![image](https://harshsingh.me/og.png) 2 | 3 | ## Quickstart 4 | 5 | Clone the website locally: 6 | 7 | ``` 8 | git clone https://github.com/haaarshsingh/www.git 9 | ``` 10 | 11 | ### Setting up the project 12 | 13 | ```bash 14 | cd www 15 | 16 | # Install dependencies 17 | bun install 18 | ``` 19 | 20 | ### Starting server 21 | 22 | ```bash 23 | bun dev 24 | ``` 25 | 26 | Server should now be running on [localhost](https://localhost:3000). 27 | 28 | ### Database 29 | 30 | This website uses [Upstash](https://upstash.com) to store the location of the last visitor. Sign up for an account, and replace the following API keys in `.env.EXAMPLE` with your own: 31 | 32 | ``` 33 | UPSTASH_REDIS_REST_URL="" 34 | UPSTASH_REDIS_REST_TOKEN="" 35 | ``` 36 | 37 | ## Forking 38 | 39 | This project is licensed with the "[Do What The F\*ck You Want To Public License (wtfpl)](https://choosealicense.com/licenses/wtfpl/)" license, and the permissions/limitations are pretty self explanatory. Attribution isn't required, but I'd appreciate it. 40 | -------------------------------------------------------------------------------- /astro.config.mjs: -------------------------------------------------------------------------------- 1 | import sitemap from "@astrojs/sitemap"; 2 | import tailwind from "@astrojs/tailwind"; 3 | import vercel from "@astrojs/vercel/serverless"; 4 | import { defineConfig } from "astro/config"; 5 | 6 | // https://astro.build/config 7 | export default defineConfig({ 8 | site: "https://harshsingh.me", 9 | integrations: [tailwind(), sitemap()], 10 | output: "static", 11 | adapter: vercel(), 12 | }); 13 | -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/bun.lockb -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "www", 3 | "type": "module", 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "astro dev", 7 | "start": "astro dev", 8 | "build": "astro check && astro build", 9 | "preview": "astro preview", 10 | "astro": "astro" 11 | }, 12 | "dependencies": { 13 | "@astrojs/check": "0.9.4", 14 | "@astrojs/rss": "4.0.11", 15 | "@astrojs/sitemap": "3.2.1", 16 | "@astrojs/tailwind": "6.0.0", 17 | "@astrojs/vercel": "8.0.8", 18 | "astro": "5.3.1", 19 | "clsx": "^2.1.1", 20 | "tailwindcss": "^3.4.10", 21 | "typescript": "^5.5.4" 22 | }, 23 | "devDependencies": { 24 | "prettier": "^3.3.3", 25 | "prettier-plugin-astro": "^0.14.1", 26 | "prettier-plugin-tailwindcss": "^0.6.6" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /public/cloud.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/cloud.webp -------------------------------------------------------------------------------- /public/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/icons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/icons/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /public/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/icons/favicon-16x16.png -------------------------------------------------------------------------------- /public/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/icons/favicon-32x32.png -------------------------------------------------------------------------------- /public/icons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/icons/favicon.ico -------------------------------------------------------------------------------- /public/icons/site.webmanifest: -------------------------------------------------------------------------------- 1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} -------------------------------------------------------------------------------- /public/inter/regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/inter/regular.woff2 -------------------------------------------------------------------------------- /public/inter/semibold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/inter/semibold.woff2 -------------------------------------------------------------------------------- /public/inter/thin.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/inter/thin.woff2 -------------------------------------------------------------------------------- /public/kmenu/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/kmenu/1.png -------------------------------------------------------------------------------- /public/kmenu/1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/kmenu/1.webp -------------------------------------------------------------------------------- /public/kmenu/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/kmenu/2.png -------------------------------------------------------------------------------- /public/kmenu/2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/kmenu/2.webp -------------------------------------------------------------------------------- /public/kmenu/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/kmenu/3.png -------------------------------------------------------------------------------- /public/kmenu/3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/kmenu/3.webp -------------------------------------------------------------------------------- /public/map.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/map.webp -------------------------------------------------------------------------------- /public/og.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/og.png -------------------------------------------------------------------------------- /public/plane-shadow.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/plane-shadow.webp -------------------------------------------------------------------------------- /public/plane.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haaarshsingh/www/4fc7aed4c92ea3bdadbe2a669fa2a814c5a7a79c/public/plane.webp -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Allow: / 3 | 4 | Sitemap: https://harshsingh.me/sitemap-index.xml 5 | -------------------------------------------------------------------------------- /src/components/Footer.astro: -------------------------------------------------------------------------------- 1 | 23 | 24 | 46 | -------------------------------------------------------------------------------- /src/components/Header.astro: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | --- 4 | 5 |
6 |

Harsh Singh

7 |
8 |

11 | I'm a founding engineer at a (currently) stealth startup. This is my lil 12 | corner of the web where I share my work with y'all. 13 |

14 |
17 | Availability 18 | Limited 22 |
23 |

24 | In my free time, I spend time outdoors, work on open source, and tinker 25 | around with all sorts of random computer stuff. 26 |

27 |
28 |
29 | -------------------------------------------------------------------------------- /src/components/Layout.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import '../global.css' 3 | import Footer from './Footer.astro' 4 | --- 5 | 6 | 7 | 8 | 9 | 10 | 11 | Harsh Singh 12 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 91 | 92 | 93 |
94 |
97 | 98 |
99 |
100 |
101 | 106 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /src/components/Main.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Link from './icons/Link.astro' 3 | 4 | const projects = [ 5 | { 6 | label: 'Vaayu', 7 | href: 'github.com/haaarshsingh/vaayu', 8 | description: 9 | '2024 · Tiny HTTP server in C for serving static files.', 10 | }, 11 | { 12 | label: 'kmenu', 13 | href: 'kmenu.dev', 14 | description: 15 | '2022 · A versatile, accessible and animated ⌘K component for React. Combines elements of the greatest command menu implementations to provide the most intuitive, streamlined, and robust application navigation experience for users.', 16 | }, 17 | { 18 | label: 'Qursor', 19 | href: 'qursor.harshsingh.me', 20 | description: '2021 · Plug n\' play cursors for React.', 21 | }, 22 | { 23 | label: 'snip', 24 | href: 'snip.tf', 25 | description: '2020 · Modern Pastebin written in Rust.', 26 | }, 27 | { 28 | label: 'dots', 29 | href: 'github.com/haaarshsingh/dots', 30 | description: '2020 · Pastel-themed i3wm and Arch Linux rice.', 31 | }, 32 | ] 33 | 34 | const socials = [ 35 | { 36 | label: 'h@harshsingh.me', 37 | href: 'mailto:h@harshsingh.me', 38 | }, 39 | { 40 | label: 'X', 41 | href: 'https://x.com/haaarshsingh', 42 | }, 43 | { 44 | label: 'GitHub', 45 | href: 'https://github.com/haaarshsingh', 46 | }, 47 | { 48 | label: 'Linkedin', 49 | href: 'https://www.linkedin.com/in/haaarshsingh', 50 | }, 51 | ] 52 | --- 53 | 54 |
55 |
56 |

59 | Where 60 |

61 |
64 | 72 | 80 | 88 | Map with marker east of Washington, DC 97 | Washington, DC 104 |
105 |
108 |
109 |
112 |
113 |
114 |
115 |
116 |
117 |

118 | Projects 119 |

120 |
    123 | { 124 | projects.map((project) => ( 125 |
  • 126 | 132 | {project.label} 133 | 134 | 135 |

    136 | {project.description} 137 |

    138 | {project.label === 'kmenu' && ( 139 |
    140 | {[1, 2, 3].map((num) => ( 141 | 147 | ))} 148 |
    149 | )} 150 |
  • 151 | )) 152 | } 153 |
154 |
155 |

Connect

156 |
157 | { 158 | socials.map((social) => ( 159 | 165 | {social.label} 166 | 167 | 168 | )) 169 | } 170 |
171 |
172 |
173 |
174 | -------------------------------------------------------------------------------- /src/components/icons/Index.astro: -------------------------------------------------------------------------------- 1 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /src/components/icons/Link.astro: -------------------------------------------------------------------------------- 1 | 9 | 14 | 15 | -------------------------------------------------------------------------------- /src/components/icons/RightArrow.astro: -------------------------------------------------------------------------------- 1 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/global.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @font-face { 6 | font-family: "Inter"; 7 | src: url("/inter/thin.woff2") format("woff2"); 8 | font-weight: normal; 9 | font-style: normal; 10 | font-display: swap; 11 | } 12 | 13 | @font-face { 14 | font-family: "Inter"; 15 | src: url("/inter/regular.woff2") format("woff2"); 16 | font-weight: normal; 17 | font-style: normal; 18 | font-display: swap; 19 | } 20 | 21 | @font-face { 22 | font-family: "Inter"; 23 | src: url("/inter/semibold.woff2") format("woff2"); 24 | font-weight: normal; 25 | font-style: normal; 26 | font-display: swap; 27 | } 28 | 29 | * { 30 | box-sizing: border-box; 31 | margin: 0; 32 | padding: 0; 33 | } 34 | 35 | body { 36 | font-family: 37 | system-ui, 38 | -apple-system, 39 | "Inter", 40 | sans-serif; 41 | letter-spacing: -2%; 42 | @apply bg-neutral-100; 43 | } 44 | 45 | ::selection { 46 | @apply bg-neutral-950 text-neutral-50; 47 | } 48 | 49 | img { 50 | @apply select-none; 51 | } 52 | 53 | a:not(.exclude) { 54 | text-decoration-style: wavy; 55 | @apply underline decoration-neutral-300; 56 | } 57 | 58 | .clock { 59 | --seconds-deg: calc((var(--now-s) / 60) * 360); 60 | --minutes-deg: calc(((var(--now-m) / 60) * 360) + ((var(--now-s) / 60) * 6)); 61 | --hours-deg: calc(((var(--now-h) / 12) * 360) + ((var(--now-m) / 60) * 30)); 62 | @apply relative m-0 flex h-5 w-5 rotate-180 items-center justify-center rounded-full border border-neutral-400; 63 | } 64 | 65 | .clock > * { 66 | @apply absolute left-1/2 top-1/2 rounded-full bg-neutral-500 [transform-origin:center_0]; 67 | } 68 | 69 | .seconds { 70 | @apply h-2 w-px; 71 | transform: rotate(calc(var(--seconds-deg) * 1deg)); 72 | } 73 | 74 | .minutes { 75 | @apply h-1.5 w-px; 76 | transform: rotate(calc(var(--minutes-deg) * 1deg)); 77 | } 78 | 79 | .hours { 80 | transform: rotate(calc(var(--hours-deg) * 1deg)); 81 | @apply h-1 w-px; 82 | } 83 | -------------------------------------------------------------------------------- /src/pages/404.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Layout from '../components/Layout.astro' 3 | import Index from '../components/icons/Index.astro' 4 | --- 5 | 6 | 7 |
8 |
9 | 10 | 11 | Index 12 | 13 |

404—not found

14 |
15 |

16 | All UI components have now been archived. Contact me if you'd like the code for any of them. 19 |

20 |
21 |
22 | -------------------------------------------------------------------------------- /src/pages/api/last-visitor.ts: -------------------------------------------------------------------------------- 1 | import type { APIRoute } from "astro"; 2 | 3 | export const prerender = false; 4 | 5 | const locate = async () => { 6 | try { 7 | const response = await fetch( 8 | `${import.meta.env.UPSTASH_REDIS_REST_URL}/get/visitor/`, 9 | { 10 | headers: { 11 | Authorization: `Bearer ${import.meta.env.UPSTASH_REDIS_REST_TOKEN}`, 12 | }, 13 | }, 14 | ); 15 | 16 | const data = await response.json(); 17 | 18 | if (data.result.includes("undefined")) 19 | return new Response(JSON.stringify({ result: "null" }), { status: 400 }); 20 | 21 | return data; 22 | } catch (error) { 23 | return console.error("Error saving to Upstash:", error); 24 | } 25 | }; 26 | 27 | export const GET: APIRoute = async () => 28 | new Response(JSON.stringify({ ...(await locate()) })); 29 | -------------------------------------------------------------------------------- /src/pages/api/locate.ts: -------------------------------------------------------------------------------- 1 | import type { APIRoute } from "astro"; 2 | 3 | export const prerender = false; 4 | 5 | const locate = async (ip: string) => { 6 | try { 7 | const location = await fetch(`http://ip-api.com/json/${ip}`); 8 | const data = await location.json(); 9 | 10 | const response = await fetch( 11 | `${import.meta.env.UPSTASH_REDIS_REST_URL}/set/visitor/${encodeURI(`${data.city}, ${data.countryCode === "US" ? data.region : data.countryCode}`)}`, 12 | { 13 | headers: { 14 | Authorization: `Bearer ${import.meta.env.UPSTASH_REDIS_REST_TOKEN}`, 15 | }, 16 | }, 17 | ); 18 | 19 | return response.status; 20 | } catch (error) { 21 | return console.error("Error fetching IP details:", error); 22 | } 23 | }; 24 | 25 | export const GET: APIRoute = async (props) => { 26 | const status = await locate(props.clientAddress); 27 | 28 | return new Response(JSON.stringify({ status: status })); 29 | }; 30 | -------------------------------------------------------------------------------- /src/pages/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import Header from "../components/Header.astro"; 3 | import Main from "../components/Main.astro"; 4 | import Layout from "../components/Layout.astro"; 5 | --- 6 | 7 | 8 |
9 |
10 | 11 | 12 | 21 | -------------------------------------------------------------------------------- /tailwind.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"], 4 | theme: { 5 | extend: { 6 | screens: { 7 | xs: "500px", 8 | }, 9 | boxShadow: { 10 | marker: "0px 3px 7.5px rgba(0, 0, 0, 0.25)", 11 | }, 12 | animation: { 13 | intro: "intro 0.3s forwards ease-in-out", 14 | cloud: "cloud 120s linear infinite", 15 | marker: "marker 4s ease-out infinite", 16 | plane: "plane 30s linear infinite", 17 | "plane-shadow": "plane-shadow 30s linear infinite", 18 | }, 19 | keyframes: { 20 | intro: { 21 | "0%": { 22 | transform: "translateY(10px)", 23 | opacity: "0", 24 | }, 25 | "100%": { 26 | transform: "translateY(0px)", 27 | opacity: "1", 28 | }, 29 | }, 30 | cloud: { 31 | "0%": { 32 | transform: "translate(-350px, -350px)", 33 | }, 34 | "25%": { 35 | transform: "translate(350px, 350px)", 36 | }, 37 | "50%": { 38 | transform: "translate(600px, -350px)", 39 | }, 40 | "75%": { 41 | transform: "translate(-400px, 350px)", 42 | }, 43 | "100%": { 44 | transform: "translate(-350px, -350px)", 45 | }, 46 | }, 47 | marker: { 48 | "0%": { 49 | transform: "translate(-50%, -50%) scale(1)", 50 | opacity: "1", 51 | }, 52 | "35%": { 53 | transform: "translate(-50%, -50%) scale(6)", 54 | opacity: "0", 55 | }, 56 | "100%": { 57 | transform: "translate(-50%, -50%) scale(6)", 58 | opacity: "0", 59 | }, 60 | }, 61 | plane: { 62 | "0%": { 63 | transform: "translate(50px, 350px) rotate(30deg)", 64 | }, 65 | "40%": { 66 | transform: "translate(300px, -60px) rotate(30deg)", 67 | }, 68 | "100%": { 69 | transform: "translate(300px, -60px) rotate(30deg)", 70 | }, 71 | }, 72 | "plane-shadow": { 73 | "0%": { 74 | transform: "translate(50px, 410px) rotate(30deg)", 75 | }, 76 | "40%": { 77 | transform: "translate(300px, -20px) rotate(30deg)", 78 | }, 79 | "100%": { 80 | transform: "translate(300px, -20px) rotate(30deg)", 81 | }, 82 | }, 83 | }, 84 | }, 85 | }, 86 | plugins: [], 87 | }; 88 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/strictest", 3 | "compilerOptions": { 4 | "jsx": "react-jsx", 5 | "jsxImportSource": "react" 6 | } 7 | } --------------------------------------------------------------------------------