move components to root, remove analytics and speed insights, cleanup on manifesto, update music link text and tilde icon on header, minor home page improvements/tweaks
This commit is contained in:
parent
1909a6d9fe
commit
1253a7e0a1
29 changed files with 65 additions and 59 deletions
|
@ -1,6 +1,6 @@
|
|||
import Header from '../components/Header'
|
||||
import AboutPg from '../components/pages/About'
|
||||
import Footer from '../components/Footer'
|
||||
import Header from '@/components/Header'
|
||||
import AboutPg from '@/components/pages/About'
|
||||
import Footer from '@/components/Footer'
|
||||
|
||||
export default function About() {
|
||||
return (
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faHeart } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className="bg-gray-800 py-6">
|
||||
<div className="container mx-auto px-4 text-center">
|
||||
<a href="https://git.pontusmail.org/aidan/aidxnCC" target="_blank" rel="noopener noreferrer" className="text-gray-400 hover:text-white transition-colors">
|
||||
<FontAwesomeIcon icon={faHeart} className="text-md mr-1" /> This website is free, open source and in the public domain.
|
||||
</a>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
"use client";
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { House, Link as LinkIcon, User, Phone, BookOpen, Music, SquareTerminal, X, Menu } from 'lucide-react';
|
||||
|
||||
interface NavItemProps {
|
||||
href: string;
|
||||
icon: React.ElementType;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const NavItem = ({ href, icon, children }: NavItemProps) => (
|
||||
<div className="nav-item">
|
||||
<Link href={href} className="flex items-center text-gray-300 hover:text-white hover:bg-gray-700 rounded-md px-3 py-2 transition-all duration-300">
|
||||
{React.createElement(icon, { className: "text-md mr-2", strokeWidth: 2.5, size: 20 })}
|
||||
{children}
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default function Header() {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const toggleMenu = () => setIsOpen(!isOpen);
|
||||
|
||||
return (
|
||||
<header className="bg-gray-800 shadow-lg">
|
||||
<nav className="container mx-auto px-4 py-4 flex justify-between items-center">
|
||||
<Link href="/" className="text-gray-300 hover:text-white text-2xl font-bold transition-all duration-300 hover:glow">
|
||||
aidxn.cc
|
||||
</Link>
|
||||
<button onClick={toggleMenu} className="md:hidden text-gray-300 focus:outline-none">
|
||||
{isOpen ? <X className="text-2xl" /> : <Menu className="text-2xl" />}
|
||||
</button>
|
||||
<ul className={`flex flex-col md:flex-row space-y-2 md:space-y-0 md:space-x-4 absolute md:static bg-gray-800 md:bg-transparent w-full md:w-auto left-0 md:left-auto top-16 md:top-auto p-4 md:p-0 transition-all duration-300 ease-in-out ${isOpen ? 'flex' : 'hidden md:flex'}`}>
|
||||
<NavItem href="/" icon={House}>Home</NavItem>
|
||||
<NavItem href="/about" icon={User}>About</NavItem>
|
||||
<NavItem href="/contact" icon={Phone}>Contact</NavItem>
|
||||
<NavItem href="/domains" icon={LinkIcon}>Domains</NavItem>
|
||||
<NavItem href="/manifesto" icon={BookOpen}>Manifesto</NavItem>
|
||||
<NavItem href="/music" icon={Music}>Music by Time</NavItem>
|
||||
<div className="flex items-center">
|
||||
<NavItem href="https://tilde.club/~lxu" icon={SquareTerminal}>Tilde</NavItem>
|
||||
<a href="https://tilde.wiki/Tildeverse" className="text-gray-300 hover:text-green-400 ml-1 text-sm" target="_blank" rel="noopener noreferrer">
|
||||
<sup>what?</sup>
|
||||
</a>
|
||||
</div>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faArrowLeft } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
interface BackButtonProps {
|
||||
href: string;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
const BackButton: React.FC<BackButtonProps> = ({ href, label = 'Back' }) => {
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
className="inline-flex items-center px-4 py-2 mt-4 text-white bg-gray-800 rounded shadow-md transition-all duration-300 ease-in-out hover:bg-gray-700 hover:shadow-lg hover:-translate-y-0.5 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500"
|
||||
aria-label={`Go back to ${label}`}
|
||||
>
|
||||
<FontAwesomeIcon icon={faArrowLeft} className="mr-2" />
|
||||
{label}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export default BackButton;
|
|
@ -1,20 +0,0 @@
|
|||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
|
||||
interface MusicInfoButtonProps {
|
||||
href: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
const MusicInfoButton: React.FC<MusicInfoButtonProps> = ({ href, label }) => {
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
className="inline-block bg-gray-800 text-white font-bold py-2 px-4 rounded shadow-md transition-all duration-300 ease-in-out hover:bg-gray-700 hover:shadow-lg hover:-translate-y-0.5 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500"
|
||||
>
|
||||
{label}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export default MusicInfoButton;
|
|
@ -1,26 +0,0 @@
|
|||
import { IconDefinition } from '@fortawesome/fontawesome-svg-core'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import Link from 'next/link';
|
||||
|
||||
interface ContactButtonProps {
|
||||
href: string;
|
||||
icon: IconDefinition;
|
||||
label: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
function ContactButton({ href, icon, label, className }: ContactButtonProps) {
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={`bg-gray-700 text-white px-4 py-2 rounded-full hover:bg-gray-600 transition-colors inline-flex items-center ${className}`}
|
||||
>
|
||||
<FontAwesomeIcon icon={icon} className="text-xl mr-2" />
|
||||
{label}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
export default ContactButton;
|
|
@ -1,12 +0,0 @@
|
|||
import { Loader2 } from 'lucide-react';
|
||||
|
||||
const LoadingSpinner: React.FC = () => {
|
||||
return (
|
||||
<div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 z-50">
|
||||
<Loader2 className="w-12 h-12 text-white animate-spin" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoadingSpinner;
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
import React from 'react';
|
||||
import Button from './Button';
|
||||
|
||||
interface TimePeriod {
|
||||
title: string;
|
||||
slug: string;
|
||||
}
|
||||
|
||||
const timePeriods: TimePeriod[] = [
|
||||
{ title: 'Late Summer 2024', slug: 'late-summer-2024' },
|
||||
{ title: 'Early Summer 2024', slug: 'early-summer-2024' },
|
||||
];
|
||||
|
||||
const MusicInfo: React.FC = () => {
|
||||
return (
|
||||
<div className="max-w-2xl mx-auto text-center text-gray-200">
|
||||
{timePeriods.map((period) => (
|
||||
<section key={period.slug} className="mb-12">
|
||||
<h2 className="text-2xl font-semibold mb-4">{period.title}</h2>
|
||||
<div className="flex justify-center">
|
||||
<Button
|
||||
href={`/time-periods/${period.slug}/what-was-going-on`}
|
||||
label="WHAT WAS GOING ON"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MusicInfo;
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
"use client"
|
||||
|
||||
import { User } from 'lucide-react'
|
||||
import FeaturedRepos from '../widgets/FeaturedRepos'
|
||||
import Image from 'next/image'
|
||||
import { useState } from 'react'
|
||||
import Link from 'next/link'
|
||||
|
||||
export default function About() {
|
||||
const [imageError, setImageError] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="max-w-2xl mx-auto text-center">
|
||||
<div className='mb-6 flex justify-center'>
|
||||
<User size={60} />
|
||||
</div>
|
||||
<h1 className="text-4xl font-bold my-2 text-center text-gray-200" style={{ textShadow: '0 0 10px rgba(255, 255, 255, 0.5)' }}>
|
||||
About Me
|
||||
</h1>
|
||||
<div className="px-6 pt-6">
|
||||
<p className="text-gray-300 mb-4">
|
||||
Hey there! I'm Aidan, a web developer and student, and this is my website. I'm passionate about web development (although I'm not great with design) and I love building things with Node.js and Express.
|
||||
</p>
|
||||
<h2 className="text-2xl font-semibold mb-4 mt-12 text-gray-200">Academics</h2>
|
||||
<p className="text-gray-300 mb-4">
|
||||
In terms of my academic background, I am currently pursuing a degree in computer science at SNHU. I really enjoy learning, though it depends on the subject. I am mostly self-taught when it comes to programming. I prefer this style of learning, especially with programming, as it lets me learn faster and apply creativity much more.
|
||||
</p>
|
||||
<h2 className="text-2xl font-semibold mb-4 mt-12 text-gray-200">Hobbies</h2>
|
||||
<p className="text-gray-300 mb-4">
|
||||
When I'm not programming, I can typically be found installing another Linux distro on my laptop or flashing a new ROM to my phone. I am also a passionate writer and I like to write creatively in my free time.
|
||||
</p>
|
||||
<p className="text-gray-300">
|
||||
I am almost always active on <Link href="https://git.pontusmail.org/" className="text-blue-400 hover:underline">my Gitea instance</Link> and GitHub and make daily contributions to several of my repositories. I am a big fan of open source software and public domain software (which most of my repos are licensed under). In fact, the website you're currently on is free and open source. It's even under the public domain!
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-12">
|
||||
<h2 className="text-2xl font-semibold mb-4 text-gray-200">My Gitea/GitHub Contributions</h2>
|
||||
<p className="text-gray-300 mb-4">Most of my repositories have migrated to <Link href="https://git.pontusmail.org/" className="text-blue-400 hover:underline">LibreCloud Git</Link>. My username is <Link href="https://git.pontusmail.org/aidan/" className="text-blue-400 hover:underline">aidan</Link>.</p>
|
||||
<p className="text-gray-300 mb-4">You can find me on GitHub as <Link href="https://github.com/ihatenodejs/" className="text-blue-400 hover:underline">ihatenodejs</Link>.</p>
|
||||
{!imageError && (
|
||||
<div className="flex flex-col md:flex-row justify-center gap-4">
|
||||
<Image
|
||||
src="https://github-readme-stats.vercel.app/api?username=ihatenodejs&theme=dark&show_icons=true&hide_border=true&count_private=true"
|
||||
alt="ihatenodejs's Stats"
|
||||
width={500}
|
||||
height={200}
|
||||
className="w-full md:w-1/2"
|
||||
onError={() => setImageError(true)}
|
||||
loading="eager"
|
||||
priority
|
||||
unoptimized
|
||||
/>
|
||||
<Image
|
||||
src="https://github-readme-stats.vercel.app/api/top-langs/?username=ihatenodejs&theme=dark&show_icons=true&hide_border=true&layout=compact"
|
||||
alt="ihatenodejs's Top Languages"
|
||||
width={500}
|
||||
height={200}
|
||||
className="w-full md:w-1/3"
|
||||
onError={() => setImageError(true)}
|
||||
loading="eager"
|
||||
priority
|
||||
unoptimized
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="mt-12">
|
||||
<h2 className="text-2xl font-semibold mb-4 text-gray-200">Featured Projects</h2>
|
||||
<p className="text-gray-300 mb-6">Here's just four of my top projects. Star and fork counts are manually updated and count both Gitea and GitHub.</p>
|
||||
<FeaturedRepos />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
import { faPhone, faEnvelope } from '@fortawesome/free-solid-svg-icons'
|
||||
import { faGithub, faTelegram } from '@fortawesome/free-brands-svg-icons'
|
||||
import { Phone } from 'lucide-react'
|
||||
import ContactButton from '../objects/ContactButton'
|
||||
|
||||
export default function Contact() {
|
||||
return (
|
||||
<div className="max-w-2xl mx-auto text-center">
|
||||
<div className='mb-6 flex justify-center'>
|
||||
<Phone size={60} />
|
||||
</div>
|
||||
<h1 className="text-4xl font-bold my-2 text-center text-gray-200" style={{ textShadow: '0 0 10px rgba(255, 255, 255, 0.5)' }}>
|
||||
Contact
|
||||
</h1>
|
||||
<div className="p-6 space-y-4">
|
||||
<ContactButton href="https://github.com/ihatenodejs" icon={faGithub} label="ihatenodejs" className="mr-3" />
|
||||
<ContactButton href="https://t.me/p0ntu5" icon={faTelegram} label="@p0ntu5" className="mr-3" />
|
||||
<ContactButton href="tel:+18024169516" icon={faPhone} label="(802) 416-9516" className="mr-3" />
|
||||
<ContactButton href="mailto:aidan@p0ntus.com" icon={faEnvelope} label="aidan@p0ntus.com" className="" />
|
||||
</div>
|
||||
<div className="p-6">
|
||||
<h2 className="text-2xl font-semibold mb-4 text-gray-200">I'm a busy person</h2>
|
||||
<p className="text-gray-300 mb-4">
|
||||
I do a lot of things during the day and I'm not always able to respond to messages right away. Please be patient and remember not to demand things from me... Somehow this is an issue for people :(
|
||||
</p>
|
||||
<p className="text-gray-300 mb-10">
|
||||
For the best chance of a response, please send me a message on Telegram. If you've made a pull request on one of my repos, I will most likely respond by the next day. If you've sent me an email, I will most likely respond within three days or less.
|
||||
</p>
|
||||
<h2 className="text-2xl font-semibold mb-4 text-gray-200">A note about calling and texting</h2>
|
||||
<p className="text-gray-300 mb-4">
|
||||
I have a phone number listed above. Please do not call or text me unless you absolutely need to. I will likely not respond, or use an automated recording system to handle your call. No, I haven't provided you my real phone number. I may be able to respond to your call/text, just know this is not checked/used often.
|
||||
</p>
|
||||
<p className="text-gray-300 mb-4">
|
||||
If you need to get in touch with me, please send me a message on Telegram or an email.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
import { Link } from 'lucide-react'
|
||||
import domains from '../../../public/data/domains.json'
|
||||
|
||||
export default function About() {
|
||||
return (
|
||||
<div className="max-w-2xl mx-auto text-center">
|
||||
<div className='mb-6 flex justify-center'>
|
||||
<Link size={60} />
|
||||
</div>
|
||||
<h1 className="text-4xl font-bold my-2 text-center text-gray-200" style={{ textShadow: '0 0 10px rgba(255, 255, 255, 0.5)' }}>
|
||||
My Domains
|
||||
</h1>
|
||||
<div className="p-6">
|
||||
{domains.map(domain => (
|
||||
<div key={domain.id} className="mb-4">
|
||||
<h2 className="text-2xl font-semibold text-gray-200">{domain.domain}</h2>
|
||||
<p className="text-gray-300">{domain.usage}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
import Image from 'next/image'
|
||||
import Button from '../objects/Button'
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="max-w-2xl mx-auto">
|
||||
<div className="mb-12 text-center">
|
||||
<Image
|
||||
src="/ihatenodejs.jpg"
|
||||
alt="My Profile Picture"
|
||||
width={150}
|
||||
height={150}
|
||||
className="rounded-full mx-auto mb-6 border-4 border-gray-700"
|
||||
/>
|
||||
<h1 className="text-4xl font-bold mb-2 text-gray-100 glow">Aidan</h1>
|
||||
<p className="text-gray-400 text-xl">Web Developer & Student</p>
|
||||
</div>
|
||||
|
||||
<section id="about" className="mb-12">
|
||||
<h2 className="text-2xl font-semibold mb-4 text-gray-200">Who I am</h2>
|
||||
<p className="text-gray-300 leading-relaxed">
|
||||
Hey there! I'm Aidan, a web developer and student from the US.
|
||||
</p>
|
||||
<p className="text-gray-300 leading-relaxed mt-2">
|
||||
I am most interested in backend development and have experience with Node.js, Express, and Tailwind CSS.
|
||||
</p>
|
||||
<p className="text-gray-300 leading-relaxed mt-2">
|
||||
When I'm not programming, I can be found re-flashing my phone with a new custom ROM and telling everyone I use Arch.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section id="about" className="mb-12">
|
||||
<h2 className="text-2xl font-semibold mb-4 text-gray-200">What I do</h2>
|
||||
<p className="text-gray-300 leading-relaxed">
|
||||
I am at my best when I am doing system administration, but I also enjoy working on web development projects.
|
||||
</p>
|
||||
<p className="text-gray-300 leading-relaxed mt-2">
|
||||
I host a few public services and websites on my VPS, most of which can be found on the "Domains" page with a short description.
|
||||
</p>
|
||||
<p className="text-gray-300 leading-relaxed mt-2">
|
||||
I'm most proud of LibreCloud/p0ntus mail, which is a cloud services provider that I self-host and maintain, free of charge.
|
||||
</p>
|
||||
<p className="text-gray-300 leading-relaxed mt-2">
|
||||
I frequently write and work on a website hosted on a public Linux server, called a "tilde." You can check it out by clicking the link "Tilde" in the header, or "what?" if you are still confused!
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section id="contact">
|
||||
<h2 className="text-2xl font-semibold mb-4 text-gray-200">Send me a message</h2>
|
||||
<p className="text-gray-300 mb-6">Feel free to reach out for collaborations or just a hello :)</p>
|
||||
<Button
|
||||
href={'/contact'}
|
||||
label="Contact Me"
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
import { BookOpen } from 'lucide-react'
|
||||
|
||||
export default function About() {
|
||||
return (
|
||||
<div className="max-w-2xl mx-auto text-center">
|
||||
<div className='mb-6 flex justify-center'>
|
||||
<BookOpen size={60} />
|
||||
</div>
|
||||
<h1 className="text-4xl font-bold my-2 text-center text-gray-200" style={{ textShadow: '0 0 10px rgba(255, 255, 255, 0.5)' }}>
|
||||
Manifesto
|
||||
</h1>
|
||||
<div className="px-6 pt-6">
|
||||
<h2 className="text-2xl font-semibold mb-4 text-gray-200">
|
||||
1. Empathy and Understanding
|
||||
</h2>
|
||||
<p className="text-gray-300 mb-4">
|
||||
We live in a distant world. People I meet are from all over, which can be hard to understand for others. I aim to utilize my ability to connect by understanding and getting interested in people's lives. I pledge to:
|
||||
</p>
|
||||
<ul className="list-disc list-inside text-left text-gray-300 mt-8 mb-4">
|
||||
<li>Listen deeply and genuinely</li>
|
||||
<li>Suspend judgment and seek to understand</li>
|
||||
<li>Recognize the humanity in every digital interaction</li>
|
||||
</ul>
|
||||
<h2 className="text-2xl font-semibold mb-4 mt-12 text-gray-200">
|
||||
2. Unconditional Sharing!
|
||||
</h2>
|
||||
<p className="text-gray-300 mb-4">
|
||||
Information should be free and accessible to all. I will:
|
||||
</p>
|
||||
<ul className="list-disc list-inside text-left text-gray-300 mt-8 mb-4">
|
||||
<li>Make all of my work free and accessible to all (e.g. public domain Wikipedia contributions)</li>
|
||||
<li>Creating and sharing content for others benefit</li>
|
||||
<li>Supporting open-source principles</li>
|
||||
<li>Creating extensive documentation on all of my projects</li>
|
||||
</ul>
|
||||
<h2 className="text-2xl font-semibold mb-4 mt-12 text-gray-200">
|
||||
3. Genuine Human Connection
|
||||
</h2>
|
||||
<p className="text-gray-300 mb-4">
|
||||
I aim to create a genuine human connection with all people I meet, regardless of who or where they are from.
|
||||
</p>
|
||||
<h2 className="text-2xl font-semibold mb-4 mt-12 text-gray-200">
|
||||
4. Privacy & Self-Hosted Services
|
||||
</h2>
|
||||
<p className="text-gray-300 mb-4">
|
||||
In terms of my personal (some public) services, I commit to never selling, viewing or share personal information with third parties or myself. I will:
|
||||
</p>
|
||||
<ul className="list-disc list-inside text-left text-gray-300 mt-8 mb-4">
|
||||
<li>Respect user data as a fundamental human right</li>
|
||||
<li>Not implement tracking and/or monetization in my services</li>
|
||||
<li>Focus my services to focus on being free and open</li>
|
||||
<li>Suggest/support technologies that help privacy</li>
|
||||
</ul>
|
||||
<h2 className="text-2xl font-semibold mb-4 mt-12 text-gray-200">
|
||||
I Commit
|
||||
</h2>
|
||||
<p className="text-gray-300 mb-4">
|
||||
I am not perfect, that's for sure, but I am committed. I promise to continuously learn, grow, and adapt to my environment, goals, purpose, and the people around me.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
import React from 'react';
|
||||
import BackButton from '../../../objects/BackButton';
|
||||
|
||||
const WhatWasGoingOnLateSummer2024: React.FC = () => {
|
||||
return (
|
||||
<div className="max-w-2xl mx-auto text-center">
|
||||
<h1 className="text-4xl font-bold my-2 text-center text-gray-200" style={{ textShadow: '0 0 10px rgba(255, 255, 255, 0.5)' }}>
|
||||
What was going on during the start of summer 2024?
|
||||
</h1>
|
||||
<div className="px-6 pt-6">
|
||||
<p className="text-gray-300 mb-4">
|
||||
During Early Summer 2024, I was walking a ton in towns all across Massachusetts. During this time, I would listen to a <i>lot</i> of music. I regret not finding out about LastFM for so long... During this time, I was always happy, especially when I had music or a YouTube video playing. I would also call my friends often during this time.
|
||||
</p>
|
||||
<h2 className="text-2xl font-semibold mb-4 mt-12 text-gray-200">Context</h2>
|
||||
<p className="text-gray-300 mb-4">
|
||||
This summer was the one where I came back from my abusive treatment center. I was finally free from the place that had been holding me back for so long. So as you can imagine, I felt free as a bird.
|
||||
</p>
|
||||
<p className="text-gray-300 mb-4">
|
||||
With this chance to explore, being in so many different towns, I really had a good time and made good memories, which I will not be writing about.
|
||||
</p>
|
||||
<BackButton href="/music" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default WhatWasGoingOnLateSummer2024;
|
|
@ -1,26 +0,0 @@
|
|||
import React from 'react';
|
||||
import BackButton from '../../../objects/BackButton';
|
||||
|
||||
const WhatWasGoingOnLateSummer2024: React.FC = () => {
|
||||
return (
|
||||
<div className="max-w-2xl mx-auto text-center">
|
||||
<h1 className="text-4xl font-bold my-2 text-center text-gray-200" style={{ textShadow: '0 0 10px rgba(255, 255, 255, 0.5)' }}>
|
||||
What was going on during the end of summer 2024?
|
||||
</h1>
|
||||
<div className="px-6 pt-6">
|
||||
<p className="text-gray-300 mb-4">
|
||||
During late summer 2024, my depression and the "after effects" of treatment really kicked in. I had quit going to my therapist as I didn't feel like they were doing much of anything for me. I am very happy to say that since I quit my therapist, I have been doing much better.
|
||||
</p>
|
||||
<p className="text-gray-300 mb-4">
|
||||
At this time, the baseball season was over, so I was walking around much less. I was still listening to a lot of music and I started getting into less depressed songs. I was also starting to get into more "normal" music, which was an interesting phase (which I believe I'm still in).
|
||||
</p>
|
||||
<p className="text-gray-300 mb-4">
|
||||
A highlight of late summer 2024 was a vacation I took. This vacation has entire albums which remind me of it and I will always cherish those memories deeply.
|
||||
</p>
|
||||
<BackButton href="/music" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default WhatWasGoingOnLateSummer2024;
|
|
@ -1,29 +0,0 @@
|
|||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faGitAlt, faGithub } from '@fortawesome/free-brands-svg-icons'
|
||||
import { faStar, faCodeBranch } from '@fortawesome/free-solid-svg-icons'
|
||||
import featuredProjects from '../../../public/data/featured.json'
|
||||
import Link from 'next/link'
|
||||
|
||||
export default function GitHubFeatured() {
|
||||
return (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
{featuredProjects.map((project) => (
|
||||
<div key={project.id} className="bg-gray-800 p-6 rounded-lg shadow-md min-h-[200px] flex flex-col">
|
||||
<div className="flex-1">
|
||||
<h3 className="text-xl font-bold text-gray-100 mb-3">
|
||||
<FontAwesomeIcon icon={project.github ? faGithub : faGitAlt} className="mr-2" /> {project.name}
|
||||
</h3>
|
||||
<p className="text-gray-300 flex-grow">{project.description}</p>
|
||||
</div>
|
||||
<div className="pt-4 border-t border-gray-700 flex justify-between items-center mt-auto">
|
||||
<Link href={project.url} className="text-blue-400 hover:underline">View Repo</Link>
|
||||
<div className="flex items-center text-gray-400">
|
||||
<FontAwesomeIcon icon={faStar} className="mr-1" /> {project.stars}
|
||||
<FontAwesomeIcon icon={faCodeBranch} className="ml-4 mr-1" /> {project.forks}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
"use client";
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import Image from 'next/image';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faLastfm } from '@fortawesome/free-brands-svg-icons'
|
||||
import { faCompactDisc, faUser } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
interface Track {
|
||||
name: string;
|
||||
artist: { '#text': string };
|
||||
album: { '#text': string };
|
||||
image: { '#text': string; size: string }[];
|
||||
url: string;
|
||||
'@attr'?: { nowplaying: string };
|
||||
}
|
||||
|
||||
const LastPlayed: React.FC = () => {
|
||||
const [track, setTrack] = useState<Track | null>(null);
|
||||
const apiUrl = process.env.LASTFM_API_URL || 'https://lastfm-last-played.biancarosa.com.br/aidxn_/latest-song';
|
||||
|
||||
useEffect(() => {
|
||||
fetch(apiUrl)
|
||||
.then(response => response.json())
|
||||
.then(data => setTrack(data.track))
|
||||
.catch(error => console.error('Error fetching now playing:', error));
|
||||
}, [apiUrl]);
|
||||
|
||||
if (!track) {
|
||||
return (
|
||||
<div className="max-w-2xl mx-auto mt-4">
|
||||
<h2 className="text-2xl font-bold mb-4 pt-10 text-gray-200">Last Played Song</h2>
|
||||
<div className="flex justify-center items-center border border-gray-300 rounded-lg p-4 max-w-md mt-8">
|
||||
<span className="spinner-border animate-spin inline-block w-8 h-8 border-4 rounded-full" role="status"></span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="max-w-2xl mx-auto mt-4">
|
||||
<h2 className="text-2xl font-bold mb-4 pt-10 text-gray-200">Last Played Song</h2>
|
||||
<div className="now-playing flex items-center border border-gray-300 rounded-lg p-4 max-w-md mt-8 bg-white bg-opacity-10 backdrop-filter backdrop-blur-lg">
|
||||
<Image
|
||||
src={track.image.find(img => img.size === 'large')?.['#text'] || '/placeholder.png'}
|
||||
alt={track.name}
|
||||
width={96}
|
||||
height={96}
|
||||
className="rounded-lg mr-4"
|
||||
/>
|
||||
<div>
|
||||
<p className="font-bold">{track.name}</p>
|
||||
<p><FontAwesomeIcon icon={faCompactDisc} className="mr-1" /> {track.album['#text']}</p>
|
||||
<i><FontAwesomeIcon icon={faUser} className="mr-1" /> {track.artist['#text']}</i>
|
||||
<a href={track.url} target="_blank" rel="noopener noreferrer" className="text-blue-500 flex items-center">
|
||||
<FontAwesomeIcon icon={faLastfm} className="mr-2" /> View on Last.fm
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LastPlayed;
|
|
@ -1,101 +0,0 @@
|
|||
"use client";
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import Image from 'next/image';
|
||||
import { Play, SkipBack, SkipForward } from 'lucide-react';
|
||||
import LoadingSpinner from '../objects/LoadingSpinner';
|
||||
|
||||
interface Song {
|
||||
albumArt: string;
|
||||
name: string;
|
||||
artist: string;
|
||||
duration: string;
|
||||
link?: string;
|
||||
}
|
||||
|
||||
interface Period {
|
||||
timePeriod: string;
|
||||
songs: Song[];
|
||||
}
|
||||
|
||||
export default function Home() {
|
||||
const [timePeriod, setTimePeriod] = useState('Early Summer 2024');
|
||||
const [songs, setSongs] = useState<Song[]>([]);
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
setIsLoading(true);
|
||||
fetch('/data/music.json')
|
||||
.then(response => response.json())
|
||||
.then((data: Period[]) => {
|
||||
const selectedPeriod = data.find((period) => period.timePeriod === timePeriod);
|
||||
const songsList = selectedPeriod ? selectedPeriod.songs : [];
|
||||
setSongs(songsList);
|
||||
setCurrentIndex(Math.floor(Math.random() * songsList.length));
|
||||
setIsLoading(false);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching music data:', error);
|
||||
setIsLoading(false);
|
||||
});
|
||||
}, [timePeriod]);
|
||||
|
||||
const handleNext = () => {
|
||||
setCurrentIndex((currentIndex + 1) % songs.length);
|
||||
};
|
||||
|
||||
const handlePrevious = () => {
|
||||
setCurrentIndex((currentIndex - 1 + songs.length) % songs.length);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="max-w-2xl mx-auto">
|
||||
<section id="music-carousel" className="mb-12">
|
||||
<h2 className="text-3xl font-semibold mb-4 text-gray-200">Music By Time Period</h2>
|
||||
<div className="mb-4 pb-4">
|
||||
<label htmlFor="timePeriod" className="text-gray-300">Time Period:</label>
|
||||
<select
|
||||
id="timePeriod"
|
||||
value={timePeriod}
|
||||
onChange={(e) => setTimePeriod(e.target.value)}
|
||||
className="ml-2 p-2 bg-gray-700 text-gray-300 rounded"
|
||||
>
|
||||
<option value="Early Summer 2024">Early Summer 2024</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{isLoading && <LoadingSpinner />}
|
||||
|
||||
{!isLoading && songs.length > 0 && (
|
||||
<div className="relative">
|
||||
<div className="text-center">
|
||||
<Image
|
||||
src={songs[currentIndex].albumArt}
|
||||
alt={songs[currentIndex].name}
|
||||
width={300}
|
||||
height={300}
|
||||
className="mx-auto mb-4 rounded-lg"
|
||||
/>
|
||||
<h3 className="text-2xl font-bold text-gray-100">{songs[currentIndex].name}</h3>
|
||||
<p className="text-gray-300">{songs[currentIndex].artist}</p>
|
||||
<p className="text-gray-300">{songs[currentIndex].duration}</p>
|
||||
<div className="mt-4">
|
||||
<button onClick={handlePrevious} className="mr-4 text-gray-300">
|
||||
<SkipBack className="w-8 h-8" />
|
||||
</button>
|
||||
<button className="mr-4 text-gray-300" onClick={() => window.open(songs[currentIndex]?.link, '_blank')}>
|
||||
<Play className="w-8 h-8" />
|
||||
</button>
|
||||
<button onClick={handleNext} className="text-gray-300">
|
||||
<SkipForward className="w-8 h-8" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import Header from '../components/Header'
|
||||
import ContactPg from '../components/pages/Contact'
|
||||
import Footer from '../components/Footer'
|
||||
import Header from '@/components/Header'
|
||||
import ContactPg from '@/components/pages/Contact'
|
||||
import Footer from '@/components/Footer'
|
||||
|
||||
export default function Contact() {
|
||||
return (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Header from '../components/Header'
|
||||
import DomainsPg from '../components/pages/Domains'
|
||||
import Footer from '../components/Footer'
|
||||
import Header from '@/components/Header'
|
||||
import DomainsPg from '@/components/pages/Domains'
|
||||
import Footer from '@/components/Footer'
|
||||
|
||||
export default function Domains() {
|
||||
return (
|
||||
|
|
|
@ -4,8 +4,6 @@ import React, { useEffect } from 'react';
|
|||
import './globals.css'
|
||||
import '@fortawesome/fontawesome-svg-core/styles.css'
|
||||
import { config } from '@fortawesome/fontawesome-svg-core'
|
||||
import { SpeedInsights } from "@vercel/speed-insights/next"
|
||||
import { Analytics } from "@vercel/analytics/react"
|
||||
import { GeistSans } from 'geist/font/sans';
|
||||
|
||||
config.autoAddCss = false
|
||||
|
@ -68,8 +66,6 @@ export default function RootLayout({
|
|||
</head>
|
||||
<body className={`${GeistSans.className} bg-gray-900 text-gray-100`}>
|
||||
{children}
|
||||
<Analytics />
|
||||
<SpeedInsights />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Header from '../components/Header'
|
||||
import ManifestoPg from '../components/pages/Manifesto'
|
||||
import Footer from '../components/Footer'
|
||||
import Header from '@/components/Header'
|
||||
import ManifestoPg from '@/components/pages/Manifesto'
|
||||
import Footer from '@/components/Footer'
|
||||
|
||||
export default function Manifesto() {
|
||||
return (
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Header from '../components/Header'
|
||||
import MusicWidget from '../components/widgets/Music'
|
||||
import MusicInfo from '../components/objects/MusicInfo'
|
||||
import Footer from '../components/Footer'
|
||||
import Header from '@/components/Header'
|
||||
import MusicWidget from '@/components/widgets/Music'
|
||||
import MusicInfo from '@/components/objects/MusicInfo'
|
||||
import Footer from '@/components/Footer'
|
||||
|
||||
export default function Music() {
|
||||
return (
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import Header from './components/Header';
|
||||
import HomePg from './components/pages/Home';
|
||||
import Footer from './components/Footer';
|
||||
import LastPlayed from './components/widgets/LastPlayed';
|
||||
import Header from '@/components/Header';
|
||||
import HomePg from '@/components/pages/Home';
|
||||
import Footer from '@/components/Footer';
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
|
@ -9,7 +8,6 @@ export default function Home() {
|
|||
<Header />
|
||||
<main className="flex-grow container mx-auto px-4 py-12">
|
||||
<HomePg />
|
||||
<LastPlayed />
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Header from '../../components/Header'
|
||||
import WhatWasGoingOn from '../../components/pages/time-periods/early-summer-2024/WhatWasGoingOn'
|
||||
import Footer from '../../components/Footer'
|
||||
import Header from '@/components/Header'
|
||||
import WhatWasGoingOn from '@/components/pages/time-periods/early-summer-2024/WhatWasGoingOn'
|
||||
import Footer from '@/components/Footer'
|
||||
|
||||
export default function EarlySummer2024() {
|
||||
return (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Header from '../../../components/Header'
|
||||
import WhatWasGoingOn from '../../../components/pages/time-periods/early-summer-2024/WhatWasGoingOn'
|
||||
import Footer from '../../../components/Footer'
|
||||
import Header from '@/components/Header'
|
||||
import WhatWasGoingOn from '@/components/pages/time-periods/early-summer-2024/WhatWasGoingOn'
|
||||
import Footer from '@/components/Footer'
|
||||
|
||||
export default function Music() {
|
||||
return (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Header from '../../components/Header'
|
||||
import WhatWasGoingOn from '../../components/pages/time-periods/late-summer-2024/WhatWasGoingOn'
|
||||
import Footer from '../../components/Footer'
|
||||
import Header from '@/components/Header'
|
||||
import WhatWasGoingOn from '@/components/pages/time-periods/late-summer-2024/WhatWasGoingOn'
|
||||
import Footer from '@/components/Footer'
|
||||
|
||||
export default function LateSummer2024() {
|
||||
return (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Header from '../../../components/Header'
|
||||
import WhatWasGoingOn from '../../../components/pages/time-periods/late-summer-2024/WhatWasGoingOn'
|
||||
import Footer from '../../../components/Footer'
|
||||
import Header from '@/components/Header'
|
||||
import WhatWasGoingOn from '@/components/pages/time-periods/late-summer-2024/WhatWasGoingOn'
|
||||
import Footer from '@/components/Footer'
|
||||
|
||||
export default function Music() {
|
||||
return (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue