me
/
ethanreece.com
Archived
1
0
Fork 0

Compare commits

..

42 Commits

Author SHA1 Message Date
Ethan Reece 491c7ba3c1
Add year to copyright 2023-08-19 15:12:58 -05:00
Ethan Reece d0af8aca8d
Update about 2023-08-19 15:10:36 -05:00
Ethan Reece d33dd70562
Open external links in new tab 2023-08-19 15:10:02 -05:00
Ethan Reece e7b89420a1
Improve link typography layout 2023-08-19 14:04:23 -05:00
Ethan Reece d13fbbcf43
Update Experience.mdx 2023-07-30 23:31:55 -05:00
Ethan Reece dc42a7d1d4
Fix eslint config 2023-07-30 23:24:43 -05:00
Ethan Reece 02916cc9e0
Add packages 2023-07-30 23:19:06 -05:00
Ethan Reece 8b5d217509
Add icons to socials 2023-07-07 01:42:28 -05:00
Ethan Reece 3fefdfe3f0
Fix icon not loading 2023-07-07 00:58:52 -05:00
Ethan Reece be0ccc4ea6
Update packages 2023-07-07 00:48:52 -05:00
Ethan Reece 8d9ab52626
Switch from asdf to rtx 2023-07-06 22:52:08 -05:00
Ethan Reece 8d039fa077
Update Projectx 2023-07-06 22:30:05 -05:00
Ethan Reece 2accb1b113
Add pnpm to asdf 2023-06-10 19:07:54 -05:00
Ethan Reece 2aead2c112
Add asdf version for nodejs 2023-06-10 19:01:32 -05:00
Ethan Reece fac67f112c
Make website more mobile friendly 2023-06-10 16:23:14 -05:00
Ethan Reece bcd69f2fe3
Fixed footer layout 2023-06-09 15:29:40 -05:00
Ethan Reece 33b2a01c9d
Add article page and credits 2023-06-09 15:11:28 -05:00
Ethan Reece 51df9d1cf2
Add article page and credits 2023-06-09 15:11:19 -05:00
Ethan Reece 9a5e796bb4
Add basic footer 2023-06-09 14:07:08 -05:00
Ethan Reece e5fc8994c1
Add contact links 2023-06-04 19:43:10 -05:00
Ethan Reece 1c7aa9b0a1
Add Contact Me section 2023-06-04 17:41:34 -05:00
Ethan Reece b10423fbdf
Add more body sections 2023-06-02 16:17:51 -05:00
Ethan Reece a8005943f5
Add projects section 2023-06-02 13:25:17 -05:00
Ethan Reece 7f90bc9445
Add about section 2023-05-31 23:28:04 -05:00
Ethan Reece b26b7f26ce
Add optimization plugins 2023-05-31 19:44:50 -05:00
Ethan Reece ce57be6f01
Complete basic hero 2023-05-31 19:17:53 -05:00
Ethan Reece 8f1b069cfa
Hide typescript error 2023-05-31 18:58:28 -05:00
Ethan Reece 9e14f90d92
Add basic content for hero 2023-05-31 00:45:49 -05:00
Ethan Reece 7c99b084a1
Add astro-seo 2023-05-30 18:48:54 -05:00
Ethan Reece 7b406fb8a1
Add components for home page 2023-05-30 18:38:31 -05:00
Ethan Reece c0a371b510
Add navbar 2023-05-30 17:37:11 -05:00
Ethan Reece 5b62942f44
Improve layout 2023-05-30 16:57:23 -05:00
Ethan Reece 89c6cd150a
Improve layout 2023-05-30 16:57:12 -05:00
Ethan Reece 5b53386027
Improve background 2023-05-30 16:29:47 -05:00
Ethan Reece 05331675fe
Add circuitboard background 2023-05-30 15:45:32 -05:00
Ethan Reece 075fd87ba4
Add basic styling 2023-05-30 14:52:17 -05:00
Ethan Reece 01700510e6
Add tailwind 2023-05-30 14:11:05 -05:00
Ethan Reece 74f4df9b5a
Update prettier and eslint 2023-05-30 13:55:57 -05:00
Ethan Reece 257c86601f
Switch from bun to pnpm 2023-05-30 13:54:07 -05:00
Ethan Reece 9a80307168
formatting fix 2023-05-24 15:38:14 -05:00
Ethan Reece 3b6dcd02c3
Add prettier and eslint 2023-05-24 15:37:45 -05:00
Ethan Reece 5eee44c205
Add prettier and eslint 2023-05-24 15:37:12 -05:00
39 changed files with 8519 additions and 220 deletions

73
.eslintrc.cjs 100644
View File

@ -0,0 +1,73 @@
module.exports = {
env: {
es2020: true,
node: true,
'astro/astro': true,
},
plugins: ['simple-import-sort', 'unused-imports'],
extends: [
'plugin:astro/recommended',
'prettier',
'eslint:recommended',
'plugin:json/recommended',
'plugin:tailwindcss/recommended',
],
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
rules: {
'simple-import-sort/imports': 'error',
'simple-import-sort/exports': 'error',
'no-unused-vars': 'off', // or "@typescript-eslint/no-unused-vars": "off",
'unused-imports/no-unused-imports': 'error',
'unused-imports/no-unused-vars': [
'warn',
{
vars: 'all',
varsIgnorePattern: '^_',
args: 'after-used',
argsIgnorePattern: '^_',
},
],
},
overrides: [
{
// Define the configuration for `.astro` file.
files: ['*.astro'],
// Allows Astro components to be parsed.
parser: 'astro-eslint-parser',
// Parse the script in `.astro` as TypeScript by adding the following configuration.
// It's the setting you need when using TypeScript.
parserOptions: {
parser: '@typescript-eslint/parser',
extraFileExtensions: ['.astro'],
sourceType: 'module',
},
rules: {
// override/add rules settings here, such as:
// "astro/no-set-html-directive": "error"
'astro/no-conflict-set-directives': 'error',
'astro/no-unused-define-vars-in-style': 'error',
},
},
{
files: ['**/*.astro/*.js', '*.astro/*.js'],
env: {
browser: true,
es2020: true,
},
parserOptions: {
sourceType: 'module',
},
rules: {
// override/add rules settings here, such as:
// "no-unused-vars": "error"
// If you are using "prettier/prettier" rule,
// you don't need to format inside <script> as it will be formatted as a `.astro` file.
'prettier/prettier': 'off',
},
},
],
}

24
.prettierrc.cjs 100644
View File

@ -0,0 +1,24 @@
module.exports = {
plugins: [
require.resolve('prettier-plugin-astro'),
require.resolve('prettier-plugin-sort-imports'),
require.resolve('prettier-plugin-tailwindcss'),
],
overrides: [
{
files: '*.astro',
options: {
parser: 'astro',
},
},
],
pluginSearchDirs: false,
trailingComma: 'es5',
tabWidth: 4,
semi: false,
singleQuote: true,
printWidth: 80,
importOrder: ['^@core/(.*)$', '^@server/(.*)$', '^@ui/(.*)$', '^[./]'],
importOrderSeparation: true,
importOrderSortSpecifiers: true,
}

3
.rtx.toml 100644
View File

@ -0,0 +1,3 @@
[tools]
node = 'lts'
pnpm = 'latest'

View File

@ -1,4 +1,4 @@
{
"recommendations": ["astro-build.astro-vscode"],
"unwantedRecommendations": []
"recommendations": ["astro-build.astro-vscode"],
"unwantedRecommendations": []
}

18
.vscode/launch.json vendored
View File

@ -1,11 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "./node_modules/.bin/astro dev",
"name": "Development server",
"request": "launch",
"type": "node-terminal"
}
]
"version": "0.2.0",
"configurations": [
{
"command": "./node_modules/.bin/astro dev",
"name": "Development server",
"request": "launch",
"type": "node-terminal"
}
]
}

7
.vscode/settings.json vendored 100644
View File

@ -0,0 +1,7 @@
{
"prettier.documentSelectors": ["**/*.astro"],
"editor.defaultFormatter": "esbenp.prettier-vscode",
"files.associations": {
"*.mdx": "markdown"
}
}

View File

@ -12,7 +12,6 @@ npm create astro@latest -- --template basics
![basics](https://user-images.githubusercontent.com/4677417/186188965-73453154-fdec-4d6b-9c34-cb35c248ae5b.png)
## 🚀 Project Structure
Inside of your Astro project, you'll see the following folders and files:

View File

@ -0,0 +1,36 @@
import { defineConfig } from 'astro-imagetools/config'
export default defineConfig({
placeholder: 'blurred',
format: ['webp', 'jpg'],
fallbackFormat: 'png',
includeSourceFormat: false,
formatOptions: {
jpg: {
quality: 80,
},
png: {
quality: 80,
},
webp: {
quality: 50,
},
tracedSVG: {
function: 'trace',
options: {
background: '#fff',
color: '#000',
turnPolicy: 'black',
turdSize: 1,
alphaMax: 1,
optCurve: true,
threshold: 100,
blackOnWhite: false,
},
},
},
sizes: (breakpoints) => {
const maxWidth = breakpoints[breakpoints.length - 1]
return `(min-width: ${maxWidth}px) ${maxWidth}px, 100vw`
},
})

View File

@ -1,8 +1,45 @@
import { defineConfig } from 'astro/config';
import tailwind from "@astrojs/tailwind";
import mdx from '@astrojs/mdx'
import partytown from '@astrojs/partytown'
import prefetch from '@astrojs/prefetch'
import sitemap from '@astrojs/sitemap'
import tailwind from '@astrojs/tailwind'
import { defineConfig } from 'astro/config'
import compress from 'astro-compress'
import icon from 'astro-icon'
import { astroImageTools } from 'astro-imagetools'
import robotsTxt from 'astro-robots-txt'
import rehypeExternalLinks from 'rehype-external-links'
// https://astro.build/config
export default defineConfig({
integrations: [tailwind()]
});
site: 'https://ethanreece.com',
integrations: [
tailwind(),
astroImageTools,
robotsTxt(),
sitemap(),
prefetch(),
partytown(),
mdx({
syntaxHighlight: 'shiki',
shikiConfig: { theme: 'dracula' },
rehypePlugins: [
[
rehypeExternalLinks,
{
target: '_blank',
rel: ['noopener', 'noreferrer'],
},
],
],
}),
icon({
include: {
heroicons: ['*'],
'fa-brands': ['*'],
'simple-icons': ['*'],
},
}),
compress(),
],
})

BIN
bun.lockb

Binary file not shown.

View File

@ -1,25 +1,57 @@
{
"name": "ethanreece.com",
"type": "module",
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"@astrojs/tailwind": "^3.1.3",
"astro": "^2.5.0",
"tailwindcss": "^3.0.24eslint-plugin-jsx-a11y"
},
"devDependencies": {
"@typescript-eslint/parser": "^5.59.7",
"eslint": "^8.41.0",
"eslint-plugin-astro": "^0.27.0",
"eslint-plugin-jsx-a11y": "^6.7.1",
"prettier": "^2.8.8",
"prettier-plugin-astro": "^0.9.0"
}
}
"name": "ethanreece.com",
"type": "module",
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"@astrojs/mdx": "^0.19.7",
"@astrojs/partytown": "^1.2.3",
"@astrojs/prefetch": "^0.2.3",
"@astrojs/sitemap": "^1.3.3",
"@astrojs/tailwind": "^4.0.0",
"@fontsource-variable/jetbrains-mono": "^5.0.5",
"@tailwindcss/typography": "^0.5.9",
"astro": "^2.8.0",
"astro-auto-import": "^0.3.0",
"astro-compress": "^1.1.50",
"astro-imagetools": "^0.8.1",
"astro-navbar": "^2.0.1",
"astro-robots-txt": "^0.5.0",
"astro-seo": "^0.7.4",
"rehype-external-links": "^2.1.0",
"sharp": "^0.32.1",
"tailwind-bootstrap-grid": "^5.0.1",
"tailwindcss-hero-patterns": "^0.1.2"
},
"devDependencies": {
"@iconify-json/fa-brands": "^1.1.4",
"@iconify-json/heroicons": "^1.1.11",
"@iconify-json/simple-icons": "^1.1.59",
"@typescript-eslint/parser": "^5.61.0",
"astro-icon": "1.0.0-next.2",
"autoprefixer": "^10.4.14",
"concurrently": "^8.2.0",
"cssnano": "^6.0.1",
"eslint": "^8.44.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-astro": "^0.27.2",
"eslint-plugin-json": "^3.1.0",
"eslint-plugin-jsonc": "^2.9.0",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-simple-import-sort": "^10.0.0",
"eslint-plugin-tailwindcss": "^3.13.0",
"eslint-plugin-unused-imports": "^3.0.0",
"find-up": "^6.3.0",
"prettier": "^2.8.8",
"prettier-plugin-astro": "^0.10.0",
"prettier-plugin-sort-imports": "^1.7.2",
"prettier-plugin-tailwindcss": "^0.3.0",
"tailwindcss": "^3.3.2"
}
}

7629
pnpm-lock.yaml 100644

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
module.exports = {
plugins: {
autoprefixer: {},
cssnano: {},
},
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 MiB

View File

@ -0,0 +1,22 @@
---
import { Icon } from 'astro-icon/components'
export interface Props {
link: string
icon?: string
external?: boolean
}
const { link, icon, external } = Astro.props
const buttonPaddingX = 'md:px-[.75rem] px-[.5rem] md:gap-[.5rem] gap-[.5rem]'
const buttonPaddingY = 'py-[.5rem]'
---
<a
href={link}
target={external ? '_blank' : '_self'}
rel={external ? 'noopener noreferrer' : ''}
class={`flex flex-row items-center rounded hover:bg-background-hover hover:text-font-hover focus-visible:bg-background-hover focus-visible:text-font-hover focus-visible:outline-none ${buttonPaddingX} ${buttonPaddingY}`}
>
{icon && <Icon name={icon} />}
<slot />
</a>

View File

@ -1,63 +0,0 @@
---
export interface Props {
title: string;
body: string;
href: string;
}
const { href, title, body } = Astro.props;
---
<li class="link-card">
<a href={href}>
<h2>
{title}
<span>&rarr;</span>
</h2>
<p>
{body}
</p>
</a>
</li>
<style>
.link-card {
list-style: none;
display: flex;
padding: 0.25rem;
background-color: white;
background-image: none;
background-size: 400%;
border-radius: 0.6rem;
background-position: 100%;
transition: background-position 0.6s cubic-bezier(0.22, 1, 0.36, 1);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
}
.link-card > a {
width: 100%;
text-decoration: none;
line-height: 1.4;
padding: 1rem 1.3rem;
border-radius: 0.35rem;
color: #111;
background-color: white;
opacity: 0.8;
}
h2 {
margin: 0;
font-size: 1.25rem;
transition: color 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
p {
margin-top: 0.5rem;
margin-bottom: 0;
color: #444;
}
.link-card:is(:hover, :focus-within) {
background-position: 0;
background-image: var(--accent-gradient);
}
.link-card:is(:hover, :focus-within) h2 {
color: rgb(var(--accent));
}
</style>

View File

@ -0,0 +1,30 @@
---
const paddingX = 'px-[.75rem]'
const paddingY = 'py-[.5rem]'
interface NavItem {
text: string
link: string
}
const links: NavItem[] = [{ text: 'site credits', link: '/credits' }]
const year = new Date().getFullYear()
---
<section>
<footer class={`flex bg-background-light ${paddingX} ${paddingY}`}>
<span class="mr-auto">Copyright Ethan Reece {year}</span>
<nav>
{
links.map((link) => (
<a
href={link.link}
class="hover:underline focus-visible:underline focus-visible:outline-none"
>
{link.text}
</a>
))
}
</nav>
</footer>
</section>

View File

@ -0,0 +1,4 @@
export interface NavItem {
text: string
link: string
}

View File

@ -0,0 +1,50 @@
---
import ButtonSecondary from '../../ButtonSecondary.astro'
interface NavItem {
text: string
link: string
}
const homeText = 'Ethan Reece'
const links: NavItem[] = [
{ text: 'About Me', link: '/#about' },
{ text: 'Projects', link: '/#projects' },
{ text: 'Experience', link: '/#experience' },
{ text: 'Hobbies', link: '/#hobbies' },
{ text: 'Contact Me', link: '/#contact' },
]
const paddingX = 'px-[.75rem]'
const paddingY = 'py-[.25rem]'
const spacing = 'space-x-[.25rem]'
const mainButtonPaddingX = 'px-[.75rem]'
const mainButtonPaddingY = 'py-[.5rem]'
---
<section class="fixed z-navbar w-full backdrop-blur-sm">
<div
class={`max-h-navbar-h bg-background-light ${paddingX} ${paddingY} opacity-80`}
>
<nav
class={`flex w-full items-center whitespace-nowrap font-normal ${spacing}`}
>
<a
href="/"
rel="prefetch"
class=`mr-auto text-[1.25rem] font-bold hover:underline focus-visible:underline focus-visible:outline-none ${mainButtonPaddingX} ${mainButtonPaddingY}`
>{homeText}</a
>
<div class={`sm:flex items-center hidden ${spacing}`}>
{
links.map((link) => (
<ButtonSecondary link={link.link}>
{link.text}
</ButtonSecondary>
))
}
</div>
</nav>
</div>
</section>

View File

@ -0,0 +1,8 @@
---
layout: './Section.astro'
title: 'About Me'
slug: 'about'
background: true
---
I am a sophomore at the University of Texas at Dallas who loves programming and tech in general. Although web development and web hosting are my main interests, I enjoy branching out and exploring other ways to work with technology and create things.

View File

@ -0,0 +1,14 @@
---
layout: './Section.astro'
title: 'Contact Me'
slug: 'contact'
background: true
---
import Socials from './Socials.astro'
Are you looking for help on a web project, or interested in learning more about myself or my projects?
Feel free to contact or follow me at any time using these links:
<Socials />

View File

@ -0,0 +1,34 @@
---
layout: './Section.astro'
title: 'Experience & Skills'
slug: 'experience'
background: true
---
import Subsection from './Subsection.astro'
Although I am most familiar with JavaScript and C#, I have used several other programming languages [i.e. Java, Python, C++, Kotlin] and can quickly learn new ones.
I have also used multiple web frameworks. I am most familiar with Express.js and React, but I have also used ASP.NET, Astro, and a bit of Django and Next.js. I plan to become more familiar with Django, Rails, and Laravel for backend along with Svelte and SolidJS for frontend.
I am also familiar with Linux since I use Arch Linux on my laptop and work with Linux Debian VMs on my server. Along with that, I have worked with PostgreSQL and MS SQL in my projects and at work, and I have also touched Google Cloud and Azure, using them for my self-hosted cloud, a cybersecurity course, and for work-related tasks.
Although I have learned most of these skills in my spare time, I have also used them in my internships:
<Subsection title="Scrumfish" subtitle="Nampa, ID" url="https://scrumfish.com/">
Worked on backend and frontend for multiple projects using ASP.NET, MS SQL,
and React to create APIs, a login system with MFA, and functional frontend
components. Rewrote part of a web app to open EPUB documents, enable users
to highlight text and comment, and position those comments relative to the
highlighted text.
</Subsection>
<Subsection
title="R-Technics"
subtitle="Boise, ID"
url="https://www.rtechnics.com/"
>
Performed Windows server maintenance tasks and created a prototype in C# to
pull song data using the SongSelect API, which was later integrated into the
company's main product.
</Subsection>

View File

@ -0,0 +1,48 @@
---
// @ts-ignore
import { Picture } from 'astro-imagetools/components'
const viewHeight = 'md:h-[30rem] sm:h-[15rem] h-[17rem]'
const padding = 'p-[1rem] pb-[3.5rem] md:p-[2rem] sm:pb-[2rem]'
const textMainSize = 'text-[2rem]'
const textEmphasisSize = 'md:text-[4rem] text-[3rem]'
const textEmphasisLineHeight = 'leading-[3.5rem]'
const text = ['Hello', ', I am', 'Ethan Reece', 'and I do ', 'web stuff', '.']
const image = '../public/images/index/myself.png'
const imageAlt = 'black and white portrait of myself'
---
<section class={`w-full ${viewHeight} ${padding}`}>
<header
class="mx-auto flex h-full max-w-page-w items-center text-center sm:max-w-[32rem] sm:text-left md:max-w-page-w"
>
<h1 class={`font-medium ${textMainSize} w-full sm:w-auto`}>
<i
><b><u>{text[0]}</u></b><span class="text-font-light"
>{text[1]}</span
></i
>
<br />
<b
class={`font-extrabold ${textEmphasisSize} ${textEmphasisLineHeight}`}
>{text[2]}</b
>
<br />
<i
><span class="text-font-light">{text[3]}</span>
<b class="font-extrabold"><u>{text[4]}</u></b></i
><span class="text-font-light">{text[5]}</span>
</h1>
<div class="ml-auto hidden h-full sm:flex">
<Picture
src={image}
alt={imageAlt}
fit="cover"
layout="fill"
placeholder="none"
/>
</div>
</header>
</section>

View File

@ -0,0 +1,8 @@
---
layout: './Section.astro'
title: 'Hobbies'
slug: 'hobbies'
background: false
---
Besides programming and working with technology, I enjoy biking and playing Minecraft modpacks. Biking gives me a way to explore the outdoors while traveling to where I need to go, and it is also less costly and more environmentally sustainable than travelling via car.

View File

@ -0,0 +1,57 @@
---
layout: './Section.astro'
title: 'Projects'
slug: 'projects'
background: false
---
import Subsection from './Subsection.astro'
My biggest personal project so far is building a server to self-host my cloud ecosystem. My server uses a Proxmox hypervisor along with Linux Debian VMs and Docker containers running services such as TrueNAS, Syncthing, Nextcloud, Plex, Forejo, Pterodactyl, GoToSocial, Lemmy, and others. To get around carrier-grade NAT limitations, I host a VPN using Google Cloud and use nftables to route traffic so I can make services publicly accessible.
I also have other projects viewable on multiple git platforms, most of which came from hackathons, game jams, and school projects. Of these, the most interesting are:
<Subsection
title="FFmpeg automated build system"
subtitle="R-Technics 2023"
url="https://github.com/rtechnics/ffmpeg"
>
GitHub Actions workflow that automatically checks for the latest FFmpeg
release tag, cross-compiles it for Windows using automatically compiled
OpenSSL libraries from another workflow, and generates a WiX installer and
NuGet package for internal business use.
</Subsection>
<Subsection
title="GroceRead"
subtitle="HackAI, UTD 2023"
url="https://devpost.com/software/groceread"
>
Android app intended to help visually-impaired people navigate grocery
stores by telling the user the product the phone camera is pointed at. Uses
Chooch API for object detection.
</Subsection>
<Subsection
title="Med-Terms"
subtitle="Axxess Hackathon, UTD 2023"
url="https://devpost.com/software/med-terms"
>
Educational chatbot that teaches anatomical terminology and suggests others
for the user to learn about. Wrote the API layer of the backend using
Django, and created most of the frontend using React.
</Subsection>
<Subsection
title="Score Tracker"
subtitle="HS senior project"
url="https://git.sudoer.ch/sudoer777/score-tracker"
>
Web app that allows coaches of HS sports teams to submit game scores. Scores
would then be publicly viewable on the app's homepage and could be managed
through an admin interface. Created with Express.js, PostgreSQL, and vanilla
JavaScript for frontend. This was my first personal web project developed
from scratch.
</Subsection>
Some other projects and activities I have worked on include [Med Check [MetroHacks 2022]](https://devpost.com/software/medcheck-sopt84), [WitchBlade [UTD SGDA 2023 Spring Jam]](https://itch.io/jam/spring23-jam/rate/1968464), [Dungeons & Debuffs [UTD SGDA 2022 Thanksgiving Jam]](https://itch.io/jam/sgda-thanksgiving-jam/rate/1810971), [ZipVersionControl [FLL #1790, yrs 2017-2019]](https://github.com/TheEthan8or/ZipVersionControl), FIRST Tech Challenge robotics [2021-2022], and FIRST Lego League robotics [2013-2019, #1790].

View File

@ -0,0 +1,32 @@
---
import type { MDXLayoutProps } from 'astro'
type Props = MDXLayoutProps<{
title: string
slug: string
background: boolean
}>
const { title, slug, background } = Astro.props.frontmatter
const fontSize = 'text-[1rem]'
const fontSizeH2 = 'text-[1.5rem]'
const paddingT = 'pt-[1.5rem]'
const paddingB = 'pb-[2.5rem]'
const anchorDistance = 'mt-[-5rem] pt-[5rem]'
---
<section
class={`px-screen-x ${paddingT} ${paddingB} ${fontSize} ${
background ? 'bg-background-dark' : ''
}`}
>
<div class={anchorDistance} id={slug}>
<div class={`mx-auto max-w-page-w space-y-paragraph prose`}>
<h2 class={`font-bold ${fontSizeH2}`}>
{title}
</h2>
<slot />
</div>
</div>
</section>

View File

@ -0,0 +1,91 @@
---
import ButtonSecondary from '../../ButtonSecondary.astro'
interface SocialExtra {
name: string
url: string
external?: boolean
}
interface Social {
name?: string
profile: string
url: string
extra?: SocialExtra[]
icon?: string
}
const socials: Social[] = [
{
name: 'Email',
profile: 'contact@ethanreece.com',
url: 'mailto:contact@ethanreece.com',
icon: 'heroicons:envelope-solid',
extra: [
{
name: 'PGP key',
url: '',
},
],
},
{
name: 'GitHub (Personal)',
profile: 'Sudoer777',
url: 'https://gh.sudoer.ch/sudoer777',
icon: 'fa-brands:github',
},
{
name: 'GitHub (R-Technics)',
profile: 'ethanreece-rtechnics',
url: 'https://gh.sudoer.ch/ethanreece-rtechnics',
icon: 'heroicons:briefcase-solid',
},
{
name: 'GitHub (Scrumfish)',
profile: 'ethanreece-scrumfish',
url: 'https://gh.sudoer.ch/ethanreece-scrumfish',
icon: 'heroicons:briefcase-solid',
},
{
name: 'Forgejo',
profile: 'me@git.sudoer.ch',
url: 'https://git.sudoer.ch/me',
icon: 'simple-icons:forgejo',
},
{
name: 'Mastodon (GoToSocial)',
profile: '@me@gts.sudoer.ch',
url: 'https://elk.sudoer.ch/@me@gts.sudoer.ch',
icon: 'fa-brands:mastodon',
},
{
name: 'Devpost',
profile: 'sudoer777',
url: 'https://devpost.com/sudoer777',
icon: 'simple-icons:devpost',
},
{
name: 'LinkedIn',
profile: '-ethanreece-',
url: 'https://www.linkedin.com/in/-ethanreece-/',
icon: 'fa-brands:linkedin',
},
]
---
<div class="not-prose flex flex-col">
{
socials.map((s) => (
<div class="flex">
<ButtonSecondary link={s.url} external={true} icon={s.icon}>
<b class="font-extrabold">{s.name}:</b>
{s.profile}
</ButtonSecondary>
{s.extra &&
s.extra.map((e) => (
<ButtonSecondary link={e.url} external={e.external}>
[{e.name}]
</ButtonSecondary>
))}
</div>
))
}
</div>

View File

@ -0,0 +1,40 @@
---
export interface Props {
title: string
subtitle: string
url: string | null
}
const { title, subtitle, url } = Astro.props
const fontSize = 'text-[.9rem]'
const fontSizeH3 = 'text-[1.4rem]'
const fontSpacing = 'leading-[1.5rem]'
const margin = 'm-[-1rem] p-[1rem]'
const background = 'bg-[#00000020]'
---
<a
href={url}
target="_blank"
rel="noopener noreferrer"
class={`block md:rounded ${
url &&
`hover:bg-background-hover hover:text-font-hover focus-visible:bg-background-hover focus-visible:text-font-hover focus-visible:outline-none not-prose no-underline font-extralight`
} ${fontSize} ${margin} ${background}`}
>
<div class={`mx-auto w-full md:w-auto max-w-page-w space-y-paragraph`}>
<span class={`flex flex-col`}>
<h3 class={`font-bold ${fontSizeH3}`}>{title}</h3>
{
subtitle && (
<span class={`font-thin italic ${fontSpacing}`}>
{subtitle}
</span>
)
}
</span>
<slot />
</div>
</a>

2
src/env.d.ts vendored
View File

@ -1 +1,3 @@
/// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" />
/// <reference types="astro-imagetools" />

View File

@ -0,0 +1,28 @@
---
import type { MDXLayoutProps } from 'astro'
import Base from './Base.astro'
type Props = MDXLayoutProps<{
title: string
description: string
}>
const { title, description } = Astro.props.frontmatter
---
<Base title={`${title} - Ethan Reece`} description={description}>
<article class="prose mx-auto px-screen-x">
<div class="mx-auto max-w-page-w">
<section>
<header>
<h1>
{title}
</h1>
</header>
</section>
<section>
<slot />
</section>
</div>
</article>
</Base>

View File

@ -0,0 +1,33 @@
---
import { SEO } from 'astro-seo'
import Footer from '../components/content/global/Footer.astro'
import Navbar from '../components/content/global/Navbar.astro'
import Background from './properties/Background.astro'
import Head from './properties/Head.astro'
export interface Props {
title: string
description: string
}
const { title, description } = Astro.props
import '@fontsource-variable/jetbrains-mono'
---
<!DOCTYPE html>
<html lang="en">
<Head title={title} description={description}>
<SEO title={title} description={description} />
</Head>
<body class="min-h-screen w-screen font-main font-light text-font">
<Background>
<Navbar />
<main class="mb-auto pt-navbar-h">
<slot />
</main>
<Footer class="mb-auto" />
</Background>
</body>
</html>

View File

@ -1,36 +0,0 @@
---
export interface Props {
title: string;
}
const { title } = Astro.props;
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="description" content="Astro description">
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} />
<title>{title}</title>
</head>
<body>
<slot />
</body>
</html>
<style is:global>
:root {
--accent: 124, 58, 237;
--accent-gradient: linear-gradient(45deg, rgb(var(--accent)), #da62c4 30%, white 60%);
}
html {
font-family: system-ui, sans-serif;
background-color: #F6F6F6;
}
code {
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
Bitstream Vera Sans Mono, Courier New, monospace;
}
</style>

View File

@ -0,0 +1,11 @@
---
const pattern = 'heropattern-circuitboard-pattern'
---
<div class="min-h-screen bg-background">
<div
class={`flex min-h-screen w-full bg-circuitboard bg-repeat flex-col ${pattern}`}
>
<slot />
</div>
</div>

View File

@ -0,0 +1,7 @@
<head>
<slot />
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} />
</head>

View File

@ -0,0 +1,22 @@
---
layout: '../layouts/Article.astro'
title: 'Site Credits'
---
This site was built using the following tools:
| | |
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| **Framework:** | Astro with TypeScript and MDX |
| **Runtime:** | Node.js |
| **Version management:** | rtx |
| **Package management:** | pnpm |
| **Layout:** | Tailwind CSS (with Astro extension) |
| **Font:** | JetBrains Mono (using Fontsource) |
| **Icons:** | Hero Icons, Font Awesome Brands, Simple Icons (using Astro Icon) |
| **Circuitboard Pattern:** | Hero Patterns |
| **IDE:** | VSCodium |
| **Code formatting:** | Prettier, ESLint, Astro MDX |
| **Optimization:** | Astro Prefetch, Astro Sitemap, Astro Imagetools (using Sharp), Astro Robots.txt, Astro SEO, Astro Compress, Autoprefixer, CSSNano |
| **Contact Frontends** | Elk (Mastodon/GoToSocial), GotHub (GitHub) |
| **Source code:** | [On Forgejo](https://git.sudoer.ch/me/ethanreece.com) |

View File

@ -1,81 +1,24 @@
---
import Layout from '../layouts/Layout.astro';
import Card from '../components/Card.astro';
import Hero from '../components/content/index/Hero.astro'
import About from '../components/content/index/About.mdx'
import Projects from '../components/content/index/Projects.mdx'
import Experience from '../components/content/index/Experience.mdx'
import Hobbies from '../components/content/index/Hobbies.mdx'
import Contact from '../components/content/index/Contact.mdx'
import Base from '../layouts/Base.astro'
const title = 'Ethan Reece'
const description = ''
---
<Layout title="Welcome to Astro.">
<main>
<h1>Welcome to <span class="text-gradient">Astro</span></h1>
<p class="instructions">
To get started, open the directory <code>src/pages</code> in your project.<br />
<strong>Code Challenge:</strong> Tweak the "Welcome to Astro" message above.
</p>
<ul role="list" class="link-card-grid">
<Card
href="https://docs.astro.build/"
title="Documentation"
body="Learn how Astro works and explore the official API docs."
/>
<Card
href="https://astro.build/integrations/"
title="Integrations"
body="Supercharge your project with new frameworks and libraries."
/>
<Card
href="https://astro.build/themes/"
title="Themes"
body="Explore a galaxy of community-built starter themes."
/>
<Card
href="https://astro.build/chat/"
title="Community"
body="Come say hi to our amazing Discord community. ❤️"
/>
</ul>
</main>
</Layout>
<style>
main {
margin: auto;
padding: 1.5rem;
max-width: 60ch;
}
h1 {
font-size: 3rem;
font-weight: 800;
margin: 0;
}
.text-gradient {
background-image: var(--accent-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-size: 400%;
background-position: 0%;
}
.instructions {
line-height: 1.6;
margin: 1rem 0;
border: 1px solid rgba(var(--accent), 25%);
background-color: white;
padding: 1rem;
border-radius: 0.4rem;
}
.instructions code {
font-size: 0.875em;
font-weight: bold;
background: rgba(var(--accent), 12%);
color: rgb(var(--accent));
border-radius: 4px;
padding: 0.3em 0.45em;
}
.instructions strong {
color: rgb(var(--accent));
}
.link-card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(24ch, 1fr));
gap: 1rem;
padding: 0;
}
</style>
<Base title={title} description={description}>
<article>
<Hero />
<About />
<Projects />
<Experience />
<Hobbies />
<Contact />
</article>
</Base>

View File

@ -0,0 +1,68 @@
/** @type {import('tailwindcss').Config} */
const heropatterns = require('tailwindcss-hero-patterns/src/patterns')
module.exports = {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
theme: {
extend: {
typography: {
DEFAULT: {
css: {
color: 'black',
fontWeight: '200',
h1: {
paddingTop: '1rem',
},
'a:hover': {
background: 'black',
color: 'white',
textDecoration: 'none',
},
},
},
},
},
heroPatterns: {
circuitboard: heropatterns.circuitboard,
},
heroPatternsOpacities: ['100'],
heroPatternColors: ['font'],
colors: {
background: '#dbf6db',
'background-dark': '#bbd8bb',
'background-light': '#ffffff',
'background-hover': '#000000cc',
font: '#000000',
'font-light': '#004f07',
'font-hover': '#ffffff',
pattern: 'rgba(0,0,0,.02)',
},
fontFamily: {
main: ['JetBrains Mono Variable', 'monospace'],
},
backgroundSize: {
contain: 'contain',
circuitboard: '40rem',
},
spacing: {
'screen-x': '1rem',
'screen-y': '1.5rem',
'navbar-h': '4rem',
paragraph: '1rem',
},
maxWidth: {
'page-w': '45rem',
},
zIndex: {
navbar: '100',
},
screens: {
sm: '640px',
md: '768px',
},
},
plugins: [
require('tailwindcss-hero-patterns'),
require('@tailwindcss/typography'),
],
}

View File

@ -1,3 +1,3 @@
{
"extends": "astro/tsconfigs/strict"
}
"extends": "astro/tsconfigs/strict"
}