Using markdown for portfolio entries. Still need to optimize design.

This commit is contained in:
Bradley Shellnut 2023-02-28 15:42:00 -08:00
parent 4d6a98df74
commit 1cc01cf932
15 changed files with 376 additions and 422 deletions

14
mdsvex.config.js Normal file
View file

@ -0,0 +1,14 @@
import { defineMDSveXConfig as defineConfig } from 'mdsvex';
import relativeImages from 'mdsvex-relative-images';
const config = defineConfig({
extensions: ['.svelte.md', '.md', '.svx'],
smartypants: {
dashes: 'oldschool'
},
remarkPlugins: [relativeImages],
rehypePlugins: []
});
export default config;

View file

@ -25,10 +25,10 @@
"@sveltejs/adapter-auto": "^1.0.3",
"@sveltejs/adapter-static": "^2.0.1",
"@sveltejs/adapter-vercel": "^1.0.6",
"@sveltejs/kit": "^1.8.5",
"@sveltejs/kit": "^1.8.7",
"@types/postcss-preset-env": "^8.0.0",
"@typescript-eslint/eslint-plugin": "^5.53.0",
"@typescript-eslint/parser": "^5.53.0",
"@typescript-eslint/eslint-plugin": "^5.54.0",
"@typescript-eslint/parser": "^5.54.0",
"autoprefixer": "^10.4.7",
"eslint": "^8.35.0",
"eslint-config-prettier": "^8.5.0",

View file

@ -12,10 +12,10 @@ specifiers:
'@sveltejs/adapter-auto': ^1.0.3
'@sveltejs/adapter-static': ^2.0.1
'@sveltejs/adapter-vercel': ^1.0.6
'@sveltejs/kit': ^1.8.5
'@sveltejs/kit': ^1.8.7
'@types/postcss-preset-env': ^8.0.0
'@typescript-eslint/eslint-plugin': ^5.53.0
'@typescript-eslint/parser': ^5.53.0
'@typescript-eslint/eslint-plugin': ^5.54.0
'@typescript-eslint/parser': ^5.54.0
autoprefixer: ^10.4.7
eslint: ^8.35.0
eslint-config-prettier: ^8.5.0
@ -56,13 +56,13 @@ devDependencies:
'@leveluptuts/svelte-toy': 2.0.3
'@playwright/test': 1.31.1
'@rgossiaux/svelte-headlessui': 1.0.2_svelte@3.55.1
'@sveltejs/adapter-auto': 1.0.3_@sveltejs+kit@1.8.5
'@sveltejs/adapter-static': 2.0.1_@sveltejs+kit@1.8.5
'@sveltejs/adapter-vercel': 1.0.6_@sveltejs+kit@1.8.5
'@sveltejs/kit': 1.8.5_svelte@3.55.1+vite@4.1.4
'@sveltejs/adapter-auto': 1.0.3_@sveltejs+kit@1.8.7
'@sveltejs/adapter-static': 2.0.1_@sveltejs+kit@1.8.7
'@sveltejs/adapter-vercel': 1.0.6_@sveltejs+kit@1.8.7
'@sveltejs/kit': 1.8.7_svelte@3.55.1+vite@4.1.4
'@types/postcss-preset-env': 8.0.0_postcss@8.4.21
'@typescript-eslint/eslint-plugin': 5.53.0_cjo54hduev4bqhpjw5znwiokqu
'@typescript-eslint/parser': 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu
'@typescript-eslint/eslint-plugin': 5.54.0_6mj2wypvdnknez7kws2nfdgupi
'@typescript-eslint/parser': 5.54.0_ycpbpc6yetojsgtrx3mwntkhsu
autoprefixer: 10.4.13_postcss@8.4.21
eslint: 8.35.0
eslint-config-prettier: 8.6.0_eslint@8.35.0
@ -716,29 +716,29 @@ packages:
picomatch: 2.3.1
dev: true
/@sveltejs/adapter-auto/1.0.3_@sveltejs+kit@1.8.5:
/@sveltejs/adapter-auto/1.0.3_@sveltejs+kit@1.8.7:
resolution: {integrity: sha512-hc7O12YQqvZ1CD4fo1gMJuPzBZvuoG5kwxb2RRoz4fVoB8B2vuPO2cY751Ln0G6T/HMrAf8kCqw6Pg+wbxcstw==}
peerDependencies:
'@sveltejs/kit': ^1.0.0
dependencies:
'@sveltejs/kit': 1.8.5_svelte@3.55.1+vite@4.1.4
'@sveltejs/kit': 1.8.7_svelte@3.55.1+vite@4.1.4
import-meta-resolve: 2.2.1
dev: true
/@sveltejs/adapter-static/2.0.1_@sveltejs+kit@1.8.5:
/@sveltejs/adapter-static/2.0.1_@sveltejs+kit@1.8.7:
resolution: {integrity: sha512-o5/q3YwD/ErxYCFlK1v3ydvldyNKk1lh3oeyxn4mhz+Pkbx/uuxhzmbOpytTlp5aVqNHDVsb04xadUzOFCDDzw==}
peerDependencies:
'@sveltejs/kit': ^1.5.0
dependencies:
'@sveltejs/kit': 1.8.5_svelte@3.55.1+vite@4.1.4
'@sveltejs/kit': 1.8.7_svelte@3.55.1+vite@4.1.4
dev: true
/@sveltejs/adapter-vercel/1.0.6_@sveltejs+kit@1.8.5:
/@sveltejs/adapter-vercel/1.0.6_@sveltejs+kit@1.8.7:
resolution: {integrity: sha512-fo6aaEygPd/6B5Jms4Ff7R4jbADnppuLvKOWBNTGe5MGB7ZRUkl+gxHWMQx2av2knyEZkA6V8y5M6R3ML5yN4g==}
peerDependencies:
'@sveltejs/kit': ^1.0.0
dependencies:
'@sveltejs/kit': 1.8.5_svelte@3.55.1+vite@4.1.4
'@sveltejs/kit': 1.8.7_svelte@3.55.1+vite@4.1.4
'@vercel/nft': 0.22.6
esbuild: 0.16.17
transitivePeerDependencies:
@ -746,8 +746,8 @@ packages:
- supports-color
dev: true
/@sveltejs/kit/1.8.5_svelte@3.55.1+vite@4.1.4:
resolution: {integrity: sha512-b6kbjVAivoPd3oL9IVBaZBWiuHeI0qBKfszSDXcqsPfiSMyUK7ilHDFVSWNn+2EMPO48+87iuho71yTCOXZE3w==}
/@sveltejs/kit/1.8.7_svelte@3.55.1+vite@4.1.4:
resolution: {integrity: sha512-DQ2JpuL4iFdA4wQw4f0W6yAxWov4xN9JOxbmt0VOHNcWeqIiEzw4GY8g4Ve5gF4f4cwjSlcxvUmS+mEGCLduLA==}
engines: {node: ^16.14 || >=18}
hasBin: true
requiresBuild: true
@ -852,8 +852,8 @@ packages:
resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==}
dev: true
/@typescript-eslint/eslint-plugin/5.53.0_cjo54hduev4bqhpjw5znwiokqu:
resolution: {integrity: sha512-alFpFWNucPLdUOySmXCJpzr6HKC3bu7XooShWM+3w/EL6J2HIoB2PFxpLnq4JauWVk6DiVeNKzQlFEaE+X9sGw==}
/@typescript-eslint/eslint-plugin/5.54.0_6mj2wypvdnknez7kws2nfdgupi:
resolution: {integrity: sha512-+hSN9BdSr629RF02d7mMtXhAJvDTyCbprNYJKrXETlul/Aml6YZwd90XioVbjejQeHbb3R8Dg0CkRgoJDxo8aw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
'@typescript-eslint/parser': ^5.0.0
@ -863,10 +863,10 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/parser': 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu
'@typescript-eslint/scope-manager': 5.53.0
'@typescript-eslint/type-utils': 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu
'@typescript-eslint/utils': 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu
'@typescript-eslint/parser': 5.54.0_ycpbpc6yetojsgtrx3mwntkhsu
'@typescript-eslint/scope-manager': 5.54.0
'@typescript-eslint/type-utils': 5.54.0_ycpbpc6yetojsgtrx3mwntkhsu
'@typescript-eslint/utils': 5.54.0_ycpbpc6yetojsgtrx3mwntkhsu
debug: 4.3.4
eslint: 8.35.0
grapheme-splitter: 1.0.4
@ -880,8 +880,8 @@ packages:
- supports-color
dev: true
/@typescript-eslint/parser/5.53.0_ycpbpc6yetojsgtrx3mwntkhsu:
resolution: {integrity: sha512-MKBw9i0DLYlmdOb3Oq/526+al20AJZpANdT6Ct9ffxcV8nKCHz63t/S0IhlTFNsBIHJv+GY5SFJ0XfqVeydQrQ==}
/@typescript-eslint/parser/5.54.0_ycpbpc6yetojsgtrx3mwntkhsu:
resolution: {integrity: sha512-aAVL3Mu2qTi+h/r04WI/5PfNWvO6pdhpeMRWk9R7rEV4mwJNzoWf5CCU5vDKBsPIFQFjEq1xg7XBI2rjiMXQbQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
@ -890,9 +890,9 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/scope-manager': 5.53.0
'@typescript-eslint/types': 5.53.0
'@typescript-eslint/typescript-estree': 5.53.0_typescript@4.9.5
'@typescript-eslint/scope-manager': 5.54.0
'@typescript-eslint/types': 5.54.0
'@typescript-eslint/typescript-estree': 5.54.0_typescript@4.9.5
debug: 4.3.4
eslint: 8.35.0
typescript: 4.9.5
@ -900,16 +900,16 @@ packages:
- supports-color
dev: true
/@typescript-eslint/scope-manager/5.53.0:
resolution: {integrity: sha512-Opy3dqNsp/9kBBeCPhkCNR7fmdSQqA+47r21hr9a14Bx0xnkElEQmhoHga+VoaoQ6uDHjDKmQPIYcUcKJifS7w==}
/@typescript-eslint/scope-manager/5.54.0:
resolution: {integrity: sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
'@typescript-eslint/types': 5.53.0
'@typescript-eslint/visitor-keys': 5.53.0
'@typescript-eslint/types': 5.54.0
'@typescript-eslint/visitor-keys': 5.54.0
dev: true
/@typescript-eslint/type-utils/5.53.0_ycpbpc6yetojsgtrx3mwntkhsu:
resolution: {integrity: sha512-HO2hh0fmtqNLzTAme/KnND5uFNwbsdYhCZghK2SoxGp3Ifn2emv+hi0PBUjzzSh0dstUIFqOj3bp0AwQlK4OWw==}
/@typescript-eslint/type-utils/5.54.0_ycpbpc6yetojsgtrx3mwntkhsu:
resolution: {integrity: sha512-WI+WMJ8+oS+LyflqsD4nlXMsVdzTMYTxl16myXPaCXnSgc7LWwMsjxQFZCK/rVmTZ3FN71Ct78ehO9bRC7erYQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: '*'
@ -918,8 +918,8 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/typescript-estree': 5.53.0_typescript@4.9.5
'@typescript-eslint/utils': 5.53.0_ycpbpc6yetojsgtrx3mwntkhsu
'@typescript-eslint/typescript-estree': 5.54.0_typescript@4.9.5
'@typescript-eslint/utils': 5.54.0_ycpbpc6yetojsgtrx3mwntkhsu
debug: 4.3.4
eslint: 8.35.0
tsutils: 3.21.0_typescript@4.9.5
@ -928,13 +928,13 @@ packages:
- supports-color
dev: true
/@typescript-eslint/types/5.53.0:
resolution: {integrity: sha512-5kcDL9ZUIP756K6+QOAfPkigJmCPHcLN7Zjdz76lQWWDdzfOhZDTj1irs6gPBKiXx5/6O3L0+AvupAut3z7D2A==}
/@typescript-eslint/types/5.54.0:
resolution: {integrity: sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
/@typescript-eslint/typescript-estree/5.53.0_typescript@4.9.5:
resolution: {integrity: sha512-eKmipH7QyScpHSkhbptBBYh9v8FxtngLquq292YTEQ1pxVs39yFBlLC1xeIZcPPz1RWGqb7YgERJRGkjw8ZV7w==}
/@typescript-eslint/typescript-estree/5.54.0_typescript@4.9.5:
resolution: {integrity: sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
typescript: '*'
@ -942,8 +942,8 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/types': 5.53.0
'@typescript-eslint/visitor-keys': 5.53.0
'@typescript-eslint/types': 5.54.0
'@typescript-eslint/visitor-keys': 5.54.0
debug: 4.3.4
globby: 11.1.0
is-glob: 4.0.3
@ -954,17 +954,17 @@ packages:
- supports-color
dev: true
/@typescript-eslint/utils/5.53.0_ycpbpc6yetojsgtrx3mwntkhsu:
resolution: {integrity: sha512-VUOOtPv27UNWLxFwQK/8+7kvxVC+hPHNsJjzlJyotlaHjLSIgOCKj9I0DBUjwOOA64qjBwx5afAPjksqOxMO0g==}
/@typescript-eslint/utils/5.54.0_ycpbpc6yetojsgtrx3mwntkhsu:
resolution: {integrity: sha512-cuwm8D/Z/7AuyAeJ+T0r4WZmlnlxQ8wt7C7fLpFlKMR+dY6QO79Cq1WpJhvZbMA4ZeZGHiRWnht7ZJ8qkdAunw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
dependencies:
'@types/json-schema': 7.0.11
'@types/semver': 7.3.13
'@typescript-eslint/scope-manager': 5.53.0
'@typescript-eslint/types': 5.53.0
'@typescript-eslint/typescript-estree': 5.53.0_typescript@4.9.5
'@typescript-eslint/scope-manager': 5.54.0
'@typescript-eslint/types': 5.54.0
'@typescript-eslint/typescript-estree': 5.54.0_typescript@4.9.5
eslint: 8.35.0
eslint-scope: 5.1.1
eslint-utils: 3.0.0_eslint@8.35.0
@ -974,11 +974,11 @@ packages:
- typescript
dev: true
/@typescript-eslint/visitor-keys/5.53.0:
resolution: {integrity: sha512-JqNLnX3leaHFZEN0gCh81sIvgrp/2GOACZNgO4+Tkf64u51kTpAyWFOY8XHx8XuXr3N2C9zgPPHtcpMg6z1g0w==}
/@typescript-eslint/visitor-keys/5.54.0:
resolution: {integrity: sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
'@typescript-eslint/types': 5.53.0
'@typescript-eslint/types': 5.54.0
eslint-visitor-keys: 3.3.0
dev: true

View file

@ -1,10 +1,12 @@
<script lang="ts">
import OpenInNew from '@iconify-icons/mdi/open-in-new';
import type { IconifyIcon } from 'iconify-icon';
export let rel = 'noreferrer';
export let target = '_blank';
export let href: string;
export let ariaLabel: string;
export let showIcon: boolean = false;
export let icon: IconifyIcon = OpenInNew;
</script>
<span class:show-icon={showIcon}>
@ -12,15 +14,14 @@
<slot />
</a>
{#if showIcon}
<iconify-icon icon={OpenInNew} width="24" height="24" role="img" title={`Open ${ariaLabel} Externally`} />
<iconify-icon {icon} width="24" height="24" role="img" title={`Open ${ariaLabel} Externally`} />
{/if}
</span>
<style lang="postcss">
.show-icon {
display: flex;
display: inline-flex;
gap: 0.5rem;
place-items: center;
&:hover {
color: var(--shellYellow);

View file

@ -1,5 +1,4 @@
<script lang="ts">
import type { SvelteComponent } from "svelte";
import { Picture } from "svelte-lazy-loader";
type ImageMeta = {
@ -18,41 +17,51 @@
export let formats: ImageMeta[];
</script>
<div class="gridItemStyles">
<div class="portfolioPicture">
<div class="portfolio">
<div class="portfolio-picture">
<h2>{name}</h2>
<Picture {placeholder} {src} {loading} {alt}>
{#each formats as { src, format, width }}
<source data-srcset={src} type="image/{format}" {width} />
{/each}
</Picture>
<slot name="portfolio-links" />
</div>
<div class="portfolio-details">
<slot />
<slot name="portfolio-details" />
</div>
</div>
<style lang="postcss">
:global(.portfolioPicture) {
:global(.portfolio-picture) {
border-radius: 3px;
max-width: 500px;
/* width: minmax(200px, 500px); */
}
:global(.gridItemStyles) {
:global(.portfolio) {
display: grid;
grid-template-columns: minmax(200px, 500px) 1fr;
width: 100%;
gap: 2rem;
margin: 0 auto;
margin: 1rem auto;
@media (max-width: 800px) {
grid-template-columns: 1fr;
}
p {
margin: 1rem 0;
padding: 0;
grid-template-columns: minmax(200px, 500px);
place-items: center;
}
}
:global(.portfolio p) {
margin: 1rem 0;
padding: 0;
}
:global(.portfolio-details) {
margin: 0 1.5rem;
}
:global(.portfolio-details ul) {
margin: 1rem;
list-style: disc;
padding-left: 1rem;
}
</style>

View file

@ -0,0 +1,43 @@
import meta from '$lib/assets/images/Bradley_Shellnut_New_Site.png?metadata';
import formatMeta from '$lib/assets/images/Bradley_Shellnut_New_Site.png?format=webp;avif;png&metadata';
import placeholder from '$lib/assets/images/Bradley_Shellnut_New_Site.png?w=100&png&blur=10';
type ImageMeta = {
format: string;
src: string;
type: string;
width: string;
height: string;
};
type Sources = {
srcset: URL;
type: string;
width: string;
height: string;
};
const { height, src, width }: ImageMeta = meta;
const sources: Sources[] = [];
const imageFormatsMetadata: ImageMeta[] = JSON.parse(formatMeta);
console.log(`Image format metadata: ${JSON.parse(imageFormatsMetadata)}`);
for (const metadata of imageFormatsMetadata) {
sources.push({
srcset: new URL(metadata.src),
type: `image/${metadata.format}`,
width: metadata.width,
height: metadata.height
});
}
const data = {
alt: 'Home Page of bradleyshellnut.com',
width,
height,
src,
sources,
placeholder
};
export { data as default };

View file

@ -0,0 +1,21 @@
---
portfolioName: 'Old Personal Website'
portfolioSubHeading: 'My first personal website.'
portfolioImage: 'Old_Website_Bradley_Shellnut.png'
portfolioImageAlt: 'Home Page of the old bradleyshellnut.com website'
---
<script>
import ExternalLink from '$lib/components/ExternalLink.svelte';
</script>
### {portfolioSubHeading}
This was my first real personal website hosted on DigitalOcean.
Tech stack:
- React
- Redux
- ReactStrap for CSS grid management
- React Router for routing links in the page

View file

@ -0,0 +1,30 @@
---
portfolioName: 'Personal Website'
portfolioSubHeading: 'My personal website written using the following technologies.'
portfolioImage: 'Bradley_Shellnut_New_Site.png'
portfolioImageAlt: 'Home Page of bradleyshellnut.com'
---
<script>
import ExternalLink from '$lib/components/ExternalLink.svelte';
</script>
### {portfolioSubHeading}
Tech Stack:
- React 18
- Gatsby 5
- <ExternalLink href="https://radix-ui.com" ariaLabel="Radix UI" showIcon>Radix UI</ExternalLink>
- Styled Components
- GraphQL
- Deployed using Netlify
- Most icons from <ExternalLink showIcon href="https://github.com/react-icons/react-icons" ariaLabel="React Icons">react-icons</ExternalLink>
- Bee, Shell, Nut, and Seattle Icons made by <ExternalLink showIcon href="https://www.flaticon.com/authors/freepik" ariaLabel="Freepik">"Freepik"</ExternalLink> from <ExternalLink showIcon href="https://www.flaticon.com" ariaLabel="Flaticon">flaticon.com</ExternalLink>
Current version was improved after the suggestions on <ExternalLink showIcon href="https://syntax.fm/show/444/syntax-highlight#t=33:19" ariaLabel="Syntax.fm Podcast Number 444">Show 444</ExternalLink> of the <ExternalLink showIcon
href="https://syntax.fm/show/444/syntax-highlight#t=33:19"
ariaLabel="Syntax.fm Podcast">Syntax Podcast</ExternalLink>
Previous archived version of my <ExternalLink showIcon
href="https://web.archive.org/web/20210224002046/https://bradleyshellnut.com/"
ariaLabel="Archive before Syntax Podcast">personal website</ExternalLink>.

View file

@ -0,0 +1,23 @@
---
portfolioName: 'Wedding Website'
portfolioSubHeading: 'An application that allows viewing of wedding details and provides the ability to RSVP to the wedding.'
portfolioImage: 'Wedding_Website.png'
portfolioImageAlt: 'Wedding Website'
---
<script>
import ExternalLink from '$lib/components/ExternalLink.svelte';
</script>
### {portfolioSubHeading}
The app was initially created for my wedding but what is linked here is a public demo of the application.
Tech stack:
- Next.js 13
- React 18
- <ExternalLink href="https://radix-ui.com" ariaLabel="Radix UI" showIcon>Radix UI</ExternalLink>
- MongoDB
- Styled Components
- Next Iron Session

View file

@ -0,0 +1,21 @@
---
portfolioName: 'Mark Shellnut Architect'
portfolioSubHeading: 'Company website for Mark Shellnut Architect.'
portfolioImage: 'Mark_Shellnut_Architect.png'
portfolioImageAlt: "Picture of Mark Shellnut Architect's Website"
---
<script>
import ExternalLink from '$lib/components/ExternalLink.svelte';
</script>
### {portfolioSubHeading}
Tech stack:
- React 18
- Gatsby 5
- <ExternalLink href="https://radix-ui.com" ariaLabel="Radix UI" showIcon>Radix UI</ExternalLink>
- Styled Components
- GraphQL
- Lambda Functions

View file

@ -0,0 +1,28 @@
import { error } from '@sveltejs/kit';
import { compile } from 'mdsvex';
import type { PageServerLoad } from '../$types';
export const prerender = true;
export const load: PageServerLoad = async () => {
try {
const personalSiteGatsby = await import(
`../../lib/content/portfolio/personal/personal-website-gatsby.md`
);
const { default: page, metadata } = personalSiteGatsby;
// const [personalSiteGatsbyResponse] = await Promise.all([personalSiteGatsby]);
console.log(`page: ${JSON.stringify(page)}, metadata: ${JSON.stringify(metadata)}`);
// const compiledResponse = await compile(personalSiteGatsbyResponse);
// console.log(`compiledResponse is: ${JSON.stringify(compiledResponse)}`);
return {
portfolios: ''
};
} catch (e) {
console.error(e);
throw error(500, 'Error loading portfolios');
}
};

View file

@ -1,4 +1,5 @@
<script lang="ts">
import type { PageData } from "./$types";
import {
Tab,
TabGroup,
@ -7,15 +8,28 @@
TabPanels,
} from "@rgossiaux/svelte-headlessui";
import { Picture } from "svelte-lazy-loader";
import GitHub from '@iconify-icons/simple-icons/github';
import Portfolio from '$lib/components/Portfolio.svelte';
import personalSite from "$lib/assets/images/Bradley_Shellnut_New_Site.png";
import personalSiteFormats from "$lib/assets/images/Bradley_Shellnut_New_Site.png?w=637;1274&format=webp;avif;png&metadata";
import personalSiteFormats from "$lib/assets/images/Bradley_Shellnut_New_Site.png?format=webp;avif;png&metadata";
import personalSiteBlurred from "$lib/assets/images/Bradley_Shellnut_New_Site.png?w=100&png&blur=10";
import weddingWebsite from "$lib/assets/images/Wedding_Website.png?format=webp;avif;png&metadata";
import weddingWebsite from "$lib/assets/images/Wedding_Website.png";
import weddingWebsiteFormats from "$lib/assets/images/Wedding_Website.png?format=webp;avif;png&metadata";
import weddingWebsiteBlurred from "$lib/assets/images/Wedding_Website.png?w=100&png&blur=10";
import oldSite from '$lib/assets/images/Old_Website_Bradley_Shellnut.png?format=webp;avif;png&metadata';
import oldSite from '$lib/assets/images/Old_Website_Bradley_Shellnut.png';
import oldSiteFormats from '$lib/assets/images/Old_Website_Bradley_Shellnut.png?format=webp;avif;png&metadata';
import oldSiteBlurred from '$lib/assets/images/Old_Website_Bradley_Shellnut.png?w=100&png&blur=10';
import shellnutArchitectWebsite from "$lib/assets/images/Mark_Shellnut_Architect.png?format=webp;avif;png&metadata";
import shellnutArchitectWebsiteBlurred from "$lib/assets/images/Mark_Shellnut_Architect.png?w=400px&blur=10";
import shellnutArchitectWebsite from "$lib/assets/images/Mark_Shellnut_Architect.png";
import shellnutArchitectWebsiteFormats from "$lib/assets/images/Mark_Shellnut_Architect.png?format=webp;avif;png&metadata";
import shellnutArchitectWebsiteBlurred from "$lib/assets/images/Mark_Shellnut_Architect.png?w=100px&blur=10";
import PersonalWebsiteGatsby from "$lib/content/portfolio/personal/personal-website-gatsby.md";
import WeddingWebsite from '$lib/content/portfolio/personal/wedding-website.md';
import MarkShellnutArchitect from '$lib/content/portfolio/professional/mark-shellnut-architect.md';
import OldWebsite from '$lib/content/portfolio/personal/old-website.md';
import ExternalLink from '$lib/components/ExternalLink.svelte';
export let data: PageData;
</script>
<svelte:head>
@ -23,346 +37,92 @@
</svelte:head>
<h1>Portfolio!</h1>
<div class="portfolioTabStyles">
<TabGroup>
<TabList
aria-label="tabs portfolios"
style="
display: grid;
gap: 1rem;
grid-template-columns: auto auto;
place-content: start;
place-items: center;
margin-bottom: 1.5rem;
"
>
<Tab class={({selected}) => selected ? "tab-selected portfolio-tab" : "tab-unselected portfolio-tab"}>
<h2>Personal Sites</h2>
</Tab>
<Tab value="professional-sites" class={({selected}) => selected ? "tab-selected portfolio-tab" : "tab-unselected portfolio-tab"}>
<h2>Professional Sites</h2>
</Tab>
</TabList>
<TabPanels>
<TabPanel>
<div class="portfolioStyles">
<div class="gridItemStyles">
<div class="portfolioPicture">
<h2>Personal Website</h2>
<Picture placeholder={personalSiteBlurred} src={personalSite} loading="eager" alt="Home Page of bradleyshellnut.com">
{#each personalSiteFormats as { src, format }}
<source data-srcset={src} type="image/{format}" />
{/each}
</Picture>
</div>
<div class="portfolio-details">
<p>
My personal website written using the following
technologies.
</p>
<p>Tech Stack:</p>
<ul>
<li>React 18</li>
<li>Gatsby 5</li>
<li>
<a
target="_blank"
href="https://radix-ui.com"
title="Radix UI"
rel="noreferrer"
>
Radix UI
</a>
</li>
<li>Styled Components</li>
<li>GraphQL</li>
<li>Deployed using Netlify</li>
<li>
Most icons from{' '}
<a
target="_blank"
href="https://github.com/react-icons/react-icons"
title="react icons"
rel="noreferrer"
>
react-icons
</a>
</li>
<li>
Bee, Shell, Nut, and Seattle Icons made by{' '}
<a
target="_blank"
href="https://www.flaticon.com/authors/freepik"
title="Freepik"
rel="noreferrer"
>
"Freepik"
</a>{' '}
from{' '}
<a
target="_blank"
href="https://www.flaticon.com/"
title="Flaticon"
rel="noreferrer"
>
flaticon.com
</a>
</li>
</ul>
<p>
Current version was improved after the suggestions on{' '}
<a
href="https://syntax.fm/show/444/syntax-highlight#t=33:19"
target="_blank"
aria-label="Syntax.fm Podcast Number 444"
rel="noreferrer"
>
Show 444
</a>{' '}
of the{' '}
<a
href="https://syntax.fm/show/444/syntax-highlight#t=33:19"
target="_blank"
aria-label="Syntax.fm Podcast"
rel="noreferrer"
>
Syntax Podcast
</a>
.
</p>
<p>
Previous archived version of my{' '}
<a
href="https://web.archive.org/web/20210224002046/https://bradleyshellnut.com/"
target="_blank"
aria-label="Archive before Syntax Podcast"
rel="noreferrer"
>
personal website
</a>
.
</p>
</div>
</div>
<div class="gridItemStyles">
<div>
<h2>Wedding Website</h2>
<div class="portfolioPicture">
<Picture placeholder={weddingWebsiteBlurred} src="images/Wedding_Website.png" alt="Wedding Website">
{#each weddingWebsite as { src, format }}
<source data-srcset={src} type="image/{format}" />
{/each}
</Picture>
</div>
<p>
<a
href="https://weddingsite-six.vercel.app/"
target="_blank"
aria-label="Wedding Website"
rel="noreferrer"
>
View Site
</a>{' '}
<a
href="https://weddingsite-six.vercel.app/"
target="_blank"
aria-label="Wedding Website"
rel="noreferrer"
>
<!-- <RiExternalLinkLine /> -->
</a>
</p>
<p>
<a
href="https://github.com/BradNut/weddingsite"
target="_blank"
aria-label="Github Repo for the wedding site"
rel="noreferrer"
>
Github Repo
</a>{' '}
<a
href="https://github.com/BradNut/weddingsite"
target="_blank"
aria-label="Github Repo for the wedding site"
rel="noreferrer"
>
<!-- <FaGithub /> -->
</a>
</p>
</div>
<div>
<p>
An application that allows viewing of wedding details and
provides the ability to RSVP to the wedding.
</p>
<p>
The app was initially created for my wedding but what is
linked here is a public demo of the application.
</p>
<p>Tech stack:</p>
<ul>
<li>Next.js 13</li>
<li>React 18</li>
<li>
<a
target="_blank"
href="https://radix-ui.com"
title="Radix UI"
rel="noreferrer"
>
Radix UI
</a>
</li>
<li>MongoDB</li>
<li>Styled Components</li>
<li>Next Iron Session</li>
</ul>
</div>
</div>
<div class="gridItemStyles">
<div>
<h2>Old Personal Website</h2>
<div class="portfolioPicture">
<Picture placeholder={oldSiteBlurred} src="images/Old_Website_Bradley_Shellnut.png" alt="Home Page of the old bradleyshellnut.com website">
{#each oldSite as { src, format }}
<source data-srcset={src} type="image/{format}" />
{/each}
</Picture>
</div>
<p>
<a
href="https://web.archive.org/web/20201205233507/https://bradleyshellnut.com/about"
target="_blank"
aria-label="Archive of bradleyshellnut.com"
rel="noreferrer"
>
Link to an archive snapshot
</a>
</p>
</div>
<div>
<p>
This was my first real personal website hosted on
DigitalOcean. It was built using the following:
</p>
<ul>
<li>React</li>
<li>Redux for any state management</li>
<li>ReactStrap for CSS grid management</li>
<li>React Router for routing links in the page</li>
</ul>
</div>
</div>
</div>
</TabPanel>
<TabPanel>
<div class="gridItemStyles">
<div>
<h2>Mark Shellnut Architect </h2>
<div class="portfolio-picture">
<Picture placeholder={shellnutArchitectWebsiteBlurred} src="images/Mark_Shellnut_Architect.png" alt="Mark Shellnut Architect's Website" loading="eager">
{#each shellnutArchitectWebsite as { src, format }}
<source data-srcset={src} type="image/{format}" />
{/each}
</Picture>
</div>
<p>
<a
href="https://markshellnutarchitect.com/"
target="_blank"
aria-label="Mark Shellnut Architect"
rel="noreferrer"
>
View Site
</a>{' '}
<a
href="https://markshellnutarchitect.com/"
target="_blank"
aria-label="Mark Shellnut Architect"
rel="noreferrer"
>
<!-- <RiExternalLinkLine /> -->
</a>
</p>
</div>
<div>
<p>Company website for Mark Shellnut Architect.</p>
<p>Tech stack:</p>
<ul>
<li>React 18</li>
<li>Gatsby 5</li>
<li>
<a
target="_blank"
href="https://radix-ui.com"
title="Radix UI"
rel="noreferrer"
>
Radix UI
</a>
</li>
<li>Styled Components</li>
<li>GraphQL</li>
<li>Lambda Functions</li>
</ul>
</div>
</div>
</TabPanel>
</TabPanels>
</TabGroup>
</div>
<TabGroup>
<TabList aria-label="tabs portfolios" class="tab-list">
<Tab class={({selected}) => selected ? "tab-selected portfolio-tab" : "tab-unselected portfolio-tab"}>
<h2>Personal Sites</h2>
</Tab>
<Tab value="professional-sites" class={({selected}) => selected ? "tab-selected portfolio-tab" : "tab-unselected portfolio-tab"}>
<h2>Professional Sites</h2>
</Tab>
</TabList>
<TabPanels>
<TabPanel>
<Portfolio name="Personal Website"
placeholder={personalSiteBlurred}
src={personalSite}
alt="Picture of Bradley Shellnut's Gatsby Personal Website"
loading="eager"
formats={personalSiteFormats}>
<PersonalWebsiteGatsby slot="portfolio-details" />
</Portfolio>
<Portfolio name="Wedding Website"
placeholder={weddingWebsiteBlurred}
src={weddingWebsite}
alt="Picture of Bradley Shellnut's Gatsby Personal Website"
formats={weddingWebsiteFormats}>
<span slot="portfolio-links">
<p>
<ExternalLink ariaLabel="View Wedding Website" href="https://weddingsite-six.vercel.app/" showIcon>View Site</ExternalLink>
</p>
<p>
<ExternalLink ariaLabel="View GitHub repository for the wedding site" href="https://github.com/BradNut/weddingsite" icon={GitHub} showIcon>GitHub repository</ExternalLink>
</p>
</span>
<WeddingWebsite slot="portfolio-details" />
</Portfolio>
<Portfolio name="Old Personal Website"
placeholder={oldSiteBlurred}
src={oldSite}
alt="Home Page of the old bradleyshellnut.com website"
formats={oldSiteFormats}>
<span slot="portfolio-links">
<p>
<ExternalLink ariaLabel="Archive of bradleyshellnut.com" href="https://web.archive.org/web/20201205233507/https://bradleyshellnut.com/about" showIcon>Link to an archive snapshot</ExternalLink>
</p>
</span>
<OldWebsite slot="portfolio-details" />
</Portfolio>
</TabPanel>
<TabPanel>
<!-- <div class="portfolioStyles"> -->
<Portfolio name="Mark Shellnut Architect"
placeholder={shellnutArchitectWebsiteBlurred}
src={shellnutArchitectWebsite}
alt="Picture of Mark Shellnut Architect's Website"
loading="eager"
formats={shellnutArchitectWebsiteFormats}>
<MarkShellnutArchitect slot="portfolio-details" />
</Portfolio>
<!-- </div> -->
</TabPanel>
</TabPanels>
</TabGroup>
<style lang="postcss">
:global(.tab-list) {
display: grid;
gap: 1rem;
grid-template-columns: auto auto;
place-content: start;
place-items: center;
margin-bottom: 1.5rem;
}
:global(img) {
border-radius: 3px;
}
:global(.portfolioStyles) {
margin-top: 1rem;
display: grid;
grid-template-columns: repeat(auto, minmax(300px, 400px));
gap: 3rem;
/* margin-top: 1rem; */
margin: 0.5rem auto;
@media (max-width: 767px) {
grid-template-columns: repeat(1, minmax(150px, 400px));
@media (max-width: 800px) {
grid-gap: 1.2rem;
margin: 0.2rem 0;
}
}
:global(.portfolio-details) {
margin: 1rem;
ul {
margin: 1rem;
list-style: circle;
}
}
:global(.portfolioPicture) {
border-radius: 3px;
width: minmax(200px, 500px);
}
:global(.gridItemStyles) {
display: grid;
grid-template-columns: minmax(200px, 0.7fr) 0.5fr;
width: 100%;
gap: 2rem;
margin: 0 auto;
@media (max-width: 767px) {
grid-template-columns: 1fr;
}
p {
margin: 1rem 0;
padding: 0;
}
}
:global(.tab-unselected) {
h2 {
border-bottom: 2px solid var(--white);

View file

@ -1 +0,0 @@
export const prerender = true;

View file

@ -1,9 +1,9 @@
*,
*:before,
*:after {
margin: 0;
padding: 0;
box-sizing: border-box;
margin: 0;
padding: 0;
box-sizing: border-box;
}
img,
@ -11,22 +11,22 @@ picture,
video,
canvas,
svg {
display: block;
max-width: 100%;
display: block;
max-width: 100%;
}
iframe,
video {
width: 100%;
border: none;
aspect-ratio: 16 / 9;
width: 100%;
border: none;
aspect-ratio: 16 / 9;
}
input,
button,
textarea,
select {
font: inherit;
font: inherit;
}
p,
@ -36,23 +36,23 @@ h3,
h4,
h5,
h6 {
overflow-wrap: break-word;
overflow-wrap: break-word;
}
button,
input {
font: inherit;
color: inherit;
border: none;
font: inherit;
color: inherit;
border: none;
}
button {
font: inherit;
background: none;
cursor: pointer;
font: inherit;
background: none;
cursor: pointer;
}
ul,
ol {
list-style: none;
}
list-style: none;
}

View file

@ -1,11 +1,16 @@
import adapter from '@sveltejs/adapter-vercel';
import { vitePreprocess } from '@sveltejs/kit/vite';
import { mdsvex } from 'mdsvex';
import mdsvexConfig from './mdsvex.config.js';
import relativeImages from 'mdsvex-relative-images';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
// for more information about preprocessors
preprocess: [vitePreprocess()],
extensions: ['.svelte', ...mdsvexConfig.extensions],
preprocess: [vitePreprocess(),mdsvex(mdsvexConfig)],
kit: {
adapter: adapter(),
alias: {