switch to go backend
All checks were successful
Build and Deploy Website / build (push) Successful in 2m26s

This commit is contained in:
2026-02-12 20:58:20 -08:00
parent 70ffdbe8d5
commit d093e4709f
45 changed files with 4298 additions and 865 deletions

24
Frontend/.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

7
Frontend/.prettierrc Normal file
View File

@@ -0,0 +1,7 @@
{
"semi": true,
"singleQuote": false,
"trailingComma": "all",
"tabWidth": 2,
"printWidth": 100
}

23
Frontend/eslint.config.js Normal file
View File

@@ -0,0 +1,23 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import { defineConfig, globalIgnores } from 'eslint/config'
export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs.flat.recommended,
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
},
])

16
Frontend/index.html Normal file
View File

@@ -0,0 +1,16 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Stephen Parkinson</title>
</head>
<body style="margin: 0">
<script>
document.body.style.backgroundColor = window.matchMedia("(prefers-color-scheme: dark)").matches ? "#161d26" : "#ffffff";
</script>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

3740
Frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

36
Frontend/package.json Normal file
View File

@@ -0,0 +1,36 @@
{
"name": "frontend",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "prettier --write src/ && tsc -b && vite build",
"lint": "eslint .",
"format": "prettier --write src/",
"format:check": "prettier --check src/",
"preview": "vite preview"
},
"dependencies": {
"@cloudscape-design/components": "^3.0.1200",
"@cloudscape-design/global-styles": "^1.0.50",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"react-router-dom": "^7.13.0"
},
"devDependencies": {
"@eslint/js": "^9.39.1",
"@types/node": "^24.10.1",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.1.1",
"eslint": "^9.39.1",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.4.24",
"globals": "^16.5.0",
"prettier": "^3.8.1",
"typescript": "~5.9.3",
"typescript-eslint": "^8.48.0",
"vite": "^7.3.1"
}
}

19
Frontend/src/App.css Normal file
View File

@@ -0,0 +1,19 @@
.page-header {
display: flex;
align-items: center;
gap: 16px;
}
.profile-image {
width: 80px;
height: 80px;
object-fit: cover;
border-radius: 50%;
flex-shrink: 0;
}
.hero-image {
width: 100%;
border-radius: 8px;
display: block;
}

48
Frontend/src/App.tsx Normal file
View File

@@ -0,0 +1,48 @@
import { BrowserRouter, Routes, Route, useNavigate, useLocation } from "react-router-dom";
import AppLayout from "@cloudscape-design/components/app-layout";
import SideNavigation from "@cloudscape-design/components/side-navigation";
import "@cloudscape-design/global-styles/index.css";
import "./App.css";
import Home from "./pages/Home";
import Resume from "./pages/Resume";
import NotFound from "./pages/NotFound";
function AppContent() {
const navigate = useNavigate();
const location = useLocation();
return (
<AppLayout
toolsHide
navigation={
<SideNavigation
header={{ text: "Stephen Parkinson", href: "/" }}
activeHref={location.pathname}
onFollow={(event) => {
event.preventDefault();
navigate(event.detail.href);
}}
items={[
{ type: "link", text: "Home", href: "/" },
{ type: "link", text: "Resume", href: "/resume" },
]}
/>
}
content={
<Routes>
<Route path="/" element={<Home />} />
<Route path="/resume" element={<Resume />} />
<Route path="*" element={<NotFound />} />
</Routes>
}
/>
);
}
export default function App() {
return (
<BrowserRouter>
<AppContent />
</BrowserRouter>
);
}

17
Frontend/src/main.tsx Normal file
View File

@@ -0,0 +1,17 @@
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { applyMode, Mode } from "@cloudscape-design/global-styles";
import App from "./App.tsx";
const darkQuery = window.matchMedia("(prefers-color-scheme: dark)");
applyMode(darkQuery.matches ? Mode.Dark : Mode.Light);
darkQuery.addEventListener("change", (e) => {
applyMode(e.matches ? Mode.Dark : Mode.Light);
});
createRoot(document.getElementById("root")!).render(
<StrictMode>
<App />
</StrictMode>,
);

View File

@@ -0,0 +1,42 @@
import ContentLayout from "@cloudscape-design/components/content-layout";
import Header from "@cloudscape-design/components/header";
import Container from "@cloudscape-design/components/container";
import SpaceBetween from "@cloudscape-design/components/space-between";
import Link from "@cloudscape-design/components/link";
import Box from "@cloudscape-design/components/box";
export default function Home() {
return (
<ContentLayout
header={
<div className="page-header">
<img src="/images/me.jpg" alt="Stephen Parkinson" className="profile-image" />
<Header variant="h1" description="Systems Development Engineer">
Stephen Parkinson
</Header>
</div>
}
>
<SpaceBetween size="l">
<Container header={<Header variant="h2">About Me</Header>}>
<Box variant="p">I'm doing a lot of stuff with computers right now.</Box>
</Container>
<Container>
<img src="/images/trees.jpg" alt="Trees" className="hero-image" />
</Container>
<Container header={<Header variant="h2">Contact</Header>}>
<SpaceBetween size="s" direction="horizontal">
<Link href="https://www.linkedin.com/in/stephen-parkinson" external>
LinkedIn
</Link>
<Link href="https://github.com/smparkin" external>
GitHub
</Link>
</SpaceBetween>
</Container>
</SpaceBetween>
</ContentLayout>
);
}

View File

@@ -0,0 +1,14 @@
import ContentLayout from "@cloudscape-design/components/content-layout";
import Header from "@cloudscape-design/components/header";
import Box from "@cloudscape-design/components/box";
import Link from "@cloudscape-design/components/link";
export default function NotFound() {
return (
<ContentLayout header={<Header variant="h1">404</Header>}>
<Box variant="p">
The page you're looking for doesn't exist. <Link href="/">Go home</Link>
</Box>
</ContentLayout>
);
}

View File

@@ -0,0 +1,137 @@
import ContentLayout from "@cloudscape-design/components/content-layout";
import Header from "@cloudscape-design/components/header";
import Container from "@cloudscape-design/components/container";
import SpaceBetween from "@cloudscape-design/components/space-between";
import Box from "@cloudscape-design/components/box";
import ColumnLayout from "@cloudscape-design/components/column-layout";
export default function Resume() {
return (
<ContentLayout header={<Header variant="h1">Resume</Header>}>
<SpaceBetween size="l">
<Container header={<Header variant="h2">Employment</Header>}>
<SpaceBetween size="l">
<SpaceBetween size="xxs">
<Header variant="h3">Systems Development Engineer, Amazon Security</Header>
<Box variant="small" color="text-body-secondary">
San Luis Obispo, CA &middot; April 2020 &ndash; Present (Promoted to full-time July
2022)
</Box>
<Box variant="p">
<ul>
<li>
Create and deploy serverless applications to collect and enrich data for
analysis.
</li>
<li>
Add monitoring and alarming to existing services to allow for easier diagnosing
of potential issues.
</li>
<li>
Work with customers to understand requirements and deliver results quickly.
</li>
</ul>
</Box>
</SpaceBetween>
<SpaceBetween size="xxs">
<Header variant="h3">Student Assistant, On-Site Support Cal Poly ITS</Header>
<Box variant="small" color="text-body-secondary">
San Luis Obispo, CA &middot; May 2019 &ndash; February 2020
</Box>
<Box variant="p">
<ul>
<li>
Responsible for support of computer services and equipment across multiple
departments.
</li>
<li>Troubleshooting, detecting, and solving of technical problems.</li>
<li>
Managing macOS and Windows based computers using Active Directory, SCCM, and
Jamf.
</li>
</ul>
</Box>
</SpaceBetween>
</SpaceBetween>
</Container>
<Container header={<Header variant="h2">Education</Header>}>
<SpaceBetween size="l">
<SpaceBetween size="xxs">
<Header variant="h3">California Polytechnic State University</Header>
<Box variant="small" color="text-body-secondary">
2017 &ndash; 2022
</Box>
<Box variant="p">
<strong>Software Engineering</strong>
<br />
Relevant Coursework: Introduction to Computing, Fundamentals of Computer Science,
Data Structures, Project-Based Object-Oriented Programming &amp; Design,
Introduction to Computer Organization, Systems Programming, and Introduction to
Operating Systems.
</Box>
</SpaceBetween>
<SpaceBetween size="xxs">
<Header variant="h3">Cal Poly Security Education Club &mdash; President</Header>
<Box variant="small" color="text-body-secondary">
Spring 2020 &ndash; Spring 2021
</Box>
<Box variant="p">
<ul>
<li>
Responsible for planning and logistics of events including iFixit Triathlon and
Security Career Fair.
</li>
<li>
Manage a team of student officers to introduce students to security topics at
all skill levels.
</li>
<li>Coordinate with companies for presentations and special events.</li>
<li>
Presented technical talks such as "iOS Security and Jailbreaking", "machswap, a
vulnerability in XNU IPC", "Intro to SSH", "Nintendo Switch Security", "macOS
Security", and "Mac File Systems and APFS Security".
</li>
</ul>
</Box>
</SpaceBetween>
</SpaceBetween>
</Container>
<Container header={<Header variant="h2">Skills</Header>}>
<ColumnLayout columns={3} variant="text-grid">
<SpaceBetween size="xxs">
<Box variant="h3">Languages &amp; Tools</Box>
<Box variant="p">
Python, TypeScript, React, JavaScript, C, Swift, git, zsh, Burp Suite
</Box>
</SpaceBetween>
<SpaceBetween size="xxs">
<Box variant="h3">AWS</Box>
<Box variant="p">Lambda, S3, DynamoDB, CloudWatch, KMS, SSM, SES, SQS, SNS, CDK</Box>
</SpaceBetween>
<SpaceBetween size="xxs">
<Box variant="h3">Operating Systems</Box>
<Box variant="p">macOS, Windows, Linux</Box>
</SpaceBetween>
</ColumnLayout>
</Container>
<Container header={<Header variant="h2">Projects</Header>}>
<ul>
<li>
Developed a watchOS app to show the status of the White Hat lab on an Apple Watch.
</li>
<li>Created a Python script to control Spotify's API from the command line.</li>
<li>
Upgraded White Hat's network infrastructure to take advantage of the 1Gbps connection
to the internet.
</li>
</ul>
</Container>
</SpaceBetween>
</ContentLayout>
);
}

View File

@@ -0,0 +1,28 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2022",
"useDefineForClassFields": true,
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "ESNext",
"types": ["vite/client"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["src"]
}

7
Frontend/tsconfig.json Normal file
View File

@@ -0,0 +1,7 @@
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}

View File

@@ -0,0 +1,26 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2023",
"lib": ["ES2023"],
"module": "ESNext",
"types": ["node"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"noEmit": true,
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["vite.config.ts"]
}

20
Frontend/vite.config.ts Normal file
View File

@@ -0,0 +1,20 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
base: '/app/',
build: {
outDir: '../Backend/public/app',
emptyOutDir: true,
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
cloudscape: ['@cloudscape-design/components', '@cloudscape-design/global-styles'],
},
},
},
},
})