-
-
-
- {
- updatedDate && (
-
- Last updated on
-
- )
- }
-
-
{title}
-
+
+
+
+
+ {heroImage && }
+
+
+
+
+
+ {
+ updatedDate && (
+
+ Last updated on
+
+ )
+ }
-
+
{title}
+
-
-
-
-
-
+
+
+
+
+
diff --git a/src/pages/about.astro b/src/pages/about.astro
deleted file mode 100644
index 86c7499..0000000
--- a/src/pages/about.astro
+++ /dev/null
@@ -1,63 +0,0 @@
----
-import AboutHeroImage from '../assets/blog-placeholder-about.jpg';
-import Layout from '../layouts/BlogPost.astro';
----
-
-
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
- labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo
- viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam
- adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus
- et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus
- vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque
- sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet.
-
-
-
- Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non
- tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non
- blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna
- porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis
- massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc.
- Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis
- bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra
- massa massa ultricies mi.
-
-
-
- Mollis nunc sed id semper risus in. Convallis a cras semper auctor neque. Diam sit amet nisl
- suscipit. Lacus viverra vitae congue eu consequat ac felis donec. Egestas integer eget aliquet
- nibh praesent tristique magna sit amet. Eget magna fermentum iaculis eu non diam. In vitae
- turpis massa sed elementum. Tristique et egestas quis ipsum suspendisse ultrices. Eget lorem
- dolor sed viverra ipsum. Vel turpis nunc eget lorem dolor sed viverra. Posuere ac ut consequat
- semper viverra nam. Laoreet suspendisse interdum consectetur libero id faucibus. Diam phasellus
- vestibulum lorem sed risus ultricies tristique. Rhoncus dolor purus non enim praesent elementum
- facilisis. Ultrices tincidunt arcu non sodales neque. Tempus egestas sed sed risus pretium quam
- vulputate. Viverra suspendisse potenti nullam ac tortor vitae purus faucibus ornare. Fringilla
- urna porttitor rhoncus dolor purus non. Amet dictum sit amet justo donec enim.
-
-
-
- Mattis ullamcorper velit sed ullamcorper morbi tincidunt. Tortor posuere ac ut consequat semper
- viverra. Tellus mauris a diam maecenas sed enim ut sem viverra. Venenatis urna cursus eget nunc
- scelerisque viverra mauris in. Arcu ac tortor dignissim convallis aenean et tortor at. Curabitur
- gravida arcu ac tortor dignissim convallis aenean et tortor. Egestas tellus rutrum tellus
- pellentesque eu. Fusce ut placerat orci nulla pellentesque dignissim enim sit amet. Ut enim
- blandit volutpat maecenas volutpat blandit aliquam etiam. Id donec ultrices tincidunt arcu. Id
- cursus metus aliquam eleifend mi.
-
-
-
- Tempus quam pellentesque nec nam aliquam sem. Risus at ultrices mi tempus imperdiet. Id porta
- nibh venenatis cras sed felis eget velit. Ipsum a arcu cursus vitae. Facilisis magna etiam
- tempor orci eu lobortis elementum. Tincidunt dui ut ornare lectus sit. Quisque non tellus orci
- ac. Blandit libero volutpat sed cras. Nec tincidunt praesent semper feugiat nibh sed pulvinar
- proin gravida. Egestas integer eget aliquet nibh praesent tristique magna.
-
-
diff --git a/src/pages/blog/index.astro b/src/pages/blog/index.astro
index 5b08c9f..86cb79d 100644
--- a/src/pages/blog/index.astro
+++ b/src/pages/blog/index.astro
@@ -1,114 +1,52 @@
---
import { Image } from 'astro:assets';
import { getCollection } from 'astro:content';
-import BaseHead from '../../components/BaseHead.astro';
-import Footer from '../../components/Footer.astro';
+import BaseLayout from '../../layouts/BaseLayout.astro';
import FormattedDate from '../../components/FormattedDate.astro';
-import Header from '../../components/Header.astro';
-import { SITE_DESCRIPTION, SITE_TITLE } from '../../consts';
+import { SITE_TITLE, SITE_DESCRIPTION } from '../../consts';
const posts = (await getCollection('blog')).sort(
(a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf(),
);
---
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/src/pages/index.astro b/src/pages/index.astro
index 55caf7e..494f989 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -1,49 +1,19 @@
---
-import BaseHead from '../components/BaseHead.astro';
-import Footer from '../components/Footer.astro';
-import Header from '../components/Header.astro';
-import { SITE_DESCRIPTION, SITE_TITLE } from '../consts';
+import BaseLayout from '../layouts/BaseLayout.astro';
+import Hero from '../components/sections/Hero.astro';
+import Experience from '../components/sections/Experience.astro';
+import FeaturedProject from '../components/sections/FeaturedProject.astro';
+import Skills from '../components/sections/Skills.astro';
+import { SITE_TITLE, SITE_DESCRIPTION } from '../consts';
---
-
-
-
-
-
-
-
-
- 🧑🚀 Hello, Astronaut!
-
- Welcome to the official Astro blog starter template. This
- template serves as a lightweight, minimally-styled starting point for anyone looking to build
- a personal website, blog, or portfolio with Astro.
-
-
- This template comes with a few integrations already configured in your
- astro.config.mjs file. You can customize your setup with
- Astro Integrations to add tools like Tailwind,
- React, or Vue to your project.
-
- Here are a few ideas on how to get started with the template:
-
- - Edit this page in
src/pages/index.astro
- - Edit the site header items in
src/components/Header.astro
- - Add your name to the footer in
src/components/Footer.astro
- - Check out the included blog posts in
src/content/blog/
- - Customize the blog post page layout in
src/layouts/BlogPost.astro
-
-
- Have fun! If you get stuck, remember to
- read the docs
- or join us on Discord to ask questions.
-
-
- Looking for a blog template with a bit more personality? Check out
- astro-blog-template
- by Maxi Ferreira.
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/src/styles/global.css b/src/styles/global.css
index d6aa450..5ddbb6a 100644
--- a/src/styles/global.css
+++ b/src/styles/global.css
@@ -1,155 +1,147 @@
-/*
- The CSS in this style tag is based off of Bear Blog's default CSS.
- https://github.com/HermanMartinus/bearblog/blob/297026a877bc2ab2b3bdfbd6b9f7961c350917dd/templates/styles/blog/default.css
- License MIT: https://github.com/HermanMartinus/bearblog/blob/master/LICENSE.md
- */
+@import "tailwindcss";
-:root {
- --accent: #2337ff;
- --accent-dark: #000d8a;
- --black: 15, 18, 25;
- --gray: 96, 115, 159;
- --gray-light: 229, 233, 240;
- --gray-dark: 34, 41, 57;
- --gray-gradient: rgba(var(--gray-light), 50%), #fff;
- --box-shadow:
- 0 2px 6px rgba(var(--gray), 25%), 0 8px 24px rgba(var(--gray), 33%), 0 16px 32px
- rgba(var(--gray), 33%);
-}
-@font-face {
- font-family: "Atkinson";
- src: url("/fonts/atkinson-regular.woff") format("woff");
- font-weight: 400;
- font-style: normal;
- font-display: swap;
-}
-@font-face {
- font-family: "Atkinson";
- src: url("/fonts/atkinson-bold.woff") format("woff");
- font-weight: 700;
- font-style: normal;
- font-display: swap;
-}
-body {
- font-family: "Atkinson", sans-serif;
- margin: 0;
- padding: 0;
- text-align: left;
- background: linear-gradient(var(--gray-gradient)) no-repeat;
- background-size: 100% 600px;
- word-wrap: break-word;
- overflow-wrap: break-word;
- color: rgb(var(--gray-dark));
- font-size: 20px;
- line-height: 1.7;
-}
-main {
- width: 720px;
- max-width: calc(100% - 2em);
- margin: auto;
- padding: 3em 1em;
-}
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
- margin: 0 0 0.5rem 0;
- color: rgb(var(--black));
- line-height: 1.2;
-}
-h1 {
- font-size: 3.052em;
-}
-h2 {
- font-size: 2.441em;
-}
-h3 {
- font-size: 1.953em;
-}
-h4 {
- font-size: 1.563em;
-}
-h5 {
- font-size: 1.25em;
-}
-strong,
-b {
- font-weight: 700;
-}
-a {
- color: var(--accent);
-}
-a:hover {
- color: var(--accent);
-}
-p {
- margin-bottom: 1em;
-}
-.prose p {
- margin-bottom: 2em;
-}
-textarea {
- width: 100%;
- font-size: 16px;
-}
-input {
- font-size: 16px;
-}
-table {
- width: 100%;
-}
-img {
- max-width: 100%;
- height: auto;
- border-radius: 8px;
-}
-code {
- padding: 2px 5px;
- background-color: rgb(var(--gray-light));
- border-radius: 2px;
-}
-pre {
- padding: 1.5em;
- border-radius: 8px;
-}
-pre > code {
- all: unset;
-}
-blockquote {
- border-left: 4px solid var(--accent);
- padding: 0 0 0 20px;
- margin: 0;
- font-size: 1.333em;
-}
-hr {
- border: none;
- border-top: 1px solid rgb(var(--gray-light));
-}
-@media (max-width: 720px) {
- body {
- font-size: 18px;
- }
- main {
- padding: 1em;
- }
+@theme {
+ --color-brand-dark: #0B0D11;
+ --color-brand-panel: #151921;
+ --color-brand-accent: #FFB84C;
+ --color-brand-cyan: #22D3EE;
+ --color-brand-border: rgba(255, 255, 255, 0.1);
+ --color-brand-borderStrong: rgba(255, 255, 255, 0.2);
+
+ --font-sans: "Inter", sans-serif;
+ --font-mono: "Space Mono", monospace;
+
+ --spacing-128: 32rem;
+
+ --background-image-gradient-radial: radial-gradient(var(--tw-gradient-stops));
}
-.sr-only {
- border: 0;
- padding: 0;
- margin: 0;
- position: absolute !important;
- height: 1px;
- width: 1px;
- overflow: hidden;
- /* IE6, IE7 - a 0 height clip, off to the bottom right of the visible 1px box */
- clip: rect(1px 1px 1px 1px);
- /* maybe deprecated but we need to support legacy browsers */
- clip: rect(1px, 1px, 1px, 1px);
- /* modern browsers, clip-path works inwards from each corner */
- clip-path: inset(50%);
- /* added line to stop words getting smushed together (as they go onto separate lines and some screen readers do not understand line feeds as a space */
- white-space: nowrap;
+/* Custom Utilities */
+@layer utilities {
+ .text-massive {
+ line-height: 0.9;
+ letter-spacing: -0.04em;
+ }
+
+ .text-stroke {
+ -webkit-text-stroke: 1px rgba(255, 255, 255, 0.1);
+ color: transparent;
+ }
+
+ .grid-overlay {
+ background-size: 100px 100px;
+ background-image:
+ linear-gradient(to right, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
+ pointer-events: none;
+ z-index: 0;
+ }
+}
+
+/* Base Styles */
+@layer base {
+ html {
+ scroll-behavior: smooth;
+ }
+
+ body {
+ @apply bg-brand-dark text-white overflow-x-hidden cursor-none antialiased selection:bg-brand-accent selection:text-brand-dark;
+ }
+
+ ::-webkit-scrollbar {
+ width: 8px;
+ }
+
+ ::-webkit-scrollbar-track {
+ background: #0B0D11;
+ }
+
+ ::-webkit-scrollbar-thumb {
+ background: #334155;
+ }
+
+ ::-webkit-scrollbar-thumb:hover {
+ background: #FFB84C;
+ }
+
+ /* Custom Cursor Base Styles */
+ .cursor-dot,
+ .cursor-outline {
+ position: fixed;
+ top: 0;
+ left: 0;
+ transform: translate(-50%, -50%);
+ border-radius: 50%;
+ z-index: 9999;
+ pointer-events: none;
+ }
+
+ .cursor-dot {
+ width: 8px;
+ height: 8px;
+ background-color: #FFB84C;
+ }
+
+ .cursor-outline {
+ width: 40px;
+ height: 40px;
+ border: 1px solid rgba(255, 184, 76, 0.5);
+ transition: width 0.2s, height 0.2s, background-color 0.2s;
+ }
+
+ /* Interactive Elements for Cursor */
+ .hover-trigger:hover ~ .cursor-outline,
+ a:hover ~ .cursor-outline,
+ button:hover ~ .cursor-outline {
+ width: 60px;
+ height: 60px;
+ background-color: rgba(255, 184, 76, 0.05);
+ border-color: #FFB84C;
+ }
+}
+
+/* Component Styles */
+@layer components {
+ .skill-tag {
+ @apply text-[10px] font-mono font-bold uppercase tracking-wider px-2 py-2 border border-slate-700 text-slate-400 hover:border-brand-accent hover:text-white transition-colors cursor-default select-none;
+ }
+
+ .btn-primary {
+ @apply bg-brand-accent text-brand-dark px-8 py-4 text-xs font-bold uppercase tracking-widest hover:bg-white transition-colors inline-block;
+ }
+
+ .btn-ghost {
+ @apply border border-slate-600 text-white px-8 py-4 text-xs font-bold uppercase tracking-widest hover:border-brand-accent hover:bg-brand-accent/5 transition-colors inline-block;
+ }
+
+ .reveal-text {
+ opacity: 0;
+ transform: translateY(20px);
+ transition: all 0.8s cubic-bezier(0.16, 1, 0.3, 1);
+ }
+
+ .reveal-text.active {
+ opacity: 1;
+ transform: translateY(0);
+ }
+
+ /* Typography / Prose */
+ .prose {
+ @apply text-slate-300 leading-relaxed;
+ }
+ .prose h1, .prose h2, .prose h3, .prose h4, .prose h5, .prose h6 {
+ @apply text-white font-bold mt-12 mb-6;
+ }
+ .prose h1 { @apply text-4xl; }
+ .prose h2 { @apply text-3xl; }
+ .prose h3 { @apply text-2xl; }
+ .prose p { @apply mb-6; }
+ .prose ul { @apply list-disc list-inside mb-6 marker:text-brand-accent; }
+ .prose ol { @apply list-decimal list-inside mb-6 marker:text-brand-accent; }
+ .prose a { @apply text-brand-accent hover:underline; }
+ .prose strong { @apply text-white; }
+ .prose blockquote { @apply border-l-4 border-brand-accent pl-6 italic text-slate-400 my-8; }
+ .prose img { @apply rounded-lg border border-white/10 my-8 w-full; }
+ .prose code { @apply font-mono bg-white/10 px-1 py-0.5 rounded text-sm text-brand-cyan; }
+ .prose pre { @apply bg-brand-panel p-6 rounded-lg overflow-x-auto my-8 border border-white/5; }
+ .prose pre code { @apply bg-transparent text-inherit p-0; }
}