feat(projects, home): converted over from dioxus completely, todo blogs and rewrite projects to get data from backend, possibly rewrite techCat as well

This commit is contained in:
2025-07-15 18:08:37 -06:00
parent 4734a4cd57
commit 2d17aaa0e7
12 changed files with 1543 additions and 4 deletions

View File

@ -1,5 +1,5 @@
{
"name": "ssg-sveltekit-template",
"name": "darkicewolf50",
"private": true,
"version": "0.0.1",
"type": "module",

View File

@ -0,0 +1,177 @@
<!-- const: Asset = asset!("assets/professional_photo_2023.jpg"); -->
<script>
import PROFESSIONAL_PHOTO_JPG from '$lib/professional_photo_2023.jpg';
</script>
<!-- document::Stylesheet { href: asset!("/assets/styling/contact.css") } -->
<h2>Contact</h2>
<div>
<div>
<div>
<img src={PROFESSIONAL_PHOTO_JPG} alt="Brock's professional headshot" />
</div>
</div>
<div>
<div>
<h4>Brock Tomlinson</h4>
<ul>
<li>FullStack Webdev and Student Software Engineer</li>
<li>
<a href="mailto:darkicewolf50@gmail.com">
<img src="https://www.svgrepo.com/show/491226/email.svg" alt="Email icon/logo" />
<div>
<p>Email I check:</p>
<p>darkicewolf50@gmail.com</p>
</div>
</a>
</li>
<li>
<a href="mailto:brock@eatsleepski.com">
<img src="https://www.svgrepo.com/show/491226/email.svg" alt="Email icon/logo" />
<div>
<p>Professional Email:</p>
<p>brock@eatsleepski.com</p>
</div>
</a>
</li>
<li>
<a href="https://github.com/darkicewolf50">
<img src="https://www.svgrepo.com/show/512317/github-142.svg" alt="Github logo" />
<p>darkicewolf50</p>
</a>
</li>
<li>
<a href="https://www.linkedin.com/in/brock-tomlinson/">
<img src="https://www.svgrepo.com/show/521725/linkedin.svg" alt="LinkedIn logo" />
<p>Brock Tomlinson</p>
</a>
</li>
<li>
<a href="https://www.twitch.tv/darkicewolf50">
<img src="https://www.svgrepo.com/show/519925/twitch.svg" alt="Twitch logo" />
<p>darkicewolf50</p>
</a>
</li>
<li>
<a href="https://www.youtube.com/@darkicewolf50">
<img src="https://www.svgrepo.com/show/521936/youtube.svg" alt="Youtube logo" />
<p>@darkicewolf50</p>
</a>
</li>
</ul>
</div>
</div>
</div>
<style>
div {
display: flex;
flex-direction: row;
gap: 2svw;
align-items: center;
justify-content: center;
}
img {
border-radius: 100%;
max-height: 250px;
display: block;
background-color: var(--card-background-color);
padding: 0.5rem;
}
div div {
display: flex;
justify-content: center;
/* flex: 0 0 48%; */
}
div div div {
display: flex;
flex-direction: column;
flex-basis: auto;
}
div div ul {
display: flex;
flex-direction: column;
}
div div ul div {
display: flex;
flex-direction: row;
}
a {
text-decoration: none;
color: inherit;
}
h4 {
text-align: center;
margin-bottom: 0px;
}
div div ul {
list-style-type: none;
gap: 1svh;
padding: 0px;
}
div div ul li {
/* display: flex;
justify-content: flex-start; */
/* text-wrap: nowrap; */
padding-right: 1svw;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
/* border: 1px solid whitesmoke; */
padding: 0.5svh 1svw;
}
div div ul li a {
display: flex;
flex-direction: row;
align-items: center;
}
div div ul li a div {
display: flex;
flex-direction: column;
}
ul li p {
padding: 0px;
margin: 0px;
}
ul li img {
height: var(--img-width);
width: var(--img-height);
object-fit: contain;
border-radius: 0px;
background-color: transparent;
filter: invert() hue-rotate(180deg);
}
ul li a:hover {
cursor: pointer;
color: #91a4d2;
filter: brightness(0) saturate(100%) invert(65%) sepia(13%) saturate(733%) hue-rotate(187deg)
brightness(95%) contrast(90%);
}
@media only screen and (max-width: 500px) {
ul li img {
display: none;
}
img {
border-radius: 100%;
max-width: 100%;
max-height: 250px;
display: block;
}
}
</style>

View File

@ -0,0 +1,189 @@
<script>
const EXPERIENCE_JOBS = [
{
postition: 'Project Coordinator',
company: 'Rally Engineering',
location: 'Ab',
start_month: 'Jan 2025',
end_month: 'May 2025'
},
{
postition: 'Project Controller Student',
company: 'Rally Engineering',
location: 'Ab',
start_month: 'May 2024',
end_month: 'Jan 2025'
},
{
postition: 'Staff',
company: "Red Deer Farmer's Market",
location: 'Ab',
start_month: 'Mar 2013',
end_month: 'Present'
},
{
postition: 'Staff',
company: 'Ghostrider Storage',
location: 'BC',
start_month: 'Mar 2020',
end_month: 'Present'
}
];
const EXPERIENCE_VOL = [
{
postition: 'Software Subteam Lead',
company: 'UCalgary Baja',
location: 'Ab',
start_month: 'Sept 2024',
end_month: 'Present'
},
{
postition: 'Software, Logistics and Business Sub Team Lead',
company: 'Schulich Off-Road',
location: 'Ab',
start_month: 'May 2023',
end_month: 'Sept 2024'
},
{
postition: 'Chassis Junior Member',
company: 'Schulich Off-Road',
location: 'Ab',
start_month: 'Sept 2022',
end_month: 'May 2023'
},
{
postition: 'Coaching with Elk Valley Special Olympics',
company: 'Elk Valley Dolphins',
location: 'BC',
start_month: 'May 2019',
end_month: 'May 2019'
}
];
let { professional_jobs } = $props();
let experience = $derived(professional_jobs ? EXPERIENCE_JOBS : EXPERIENCE_VOL);
</script>
<div class="experience-comp">
{#if professional_jobs === true}
<h3>Professional</h3>
{:else}
<h3>Volunteering</h3>
{/if}
<table>
<colgroup>
<col class="symbol" />
<col class="postion" />
<col class="date-location" />
</colgroup>
<tbody>
{#each experience as exp}
<tr>
<td class="symbol" rowspan="2">
<span class="dot"></span>
</td>
<td>{exp.postition}</td>
<td>{exp.start_month} - {exp.end_month}</td>
</tr>
<tr>
<td>{exp.company}</td>
<td>{exp.location}</td>
</tr>
{/each}
</tbody>
</table>
</div>
<style>
div {
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: space-evenly;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
margin: 4svh 0;
}
h3 {
display: flex;
border-bottom: var(--underlineTitle);
border-radius: var(--underlineTitleBorderRadius);
margin: 2svh 2svw;
padding: 0svh 2svw;
padding-bottom: 1svh;
}
table {
border-collapse: separate;
border-spacing: 0svh 0px;
}
td {
position: relative;
margin: 0px;
padding: 0.25svh 2svw;
}
tr:nth-child(even) td {
padding-bottom: 2svh;
}
.postion {
text-wrap: nowrap;
}
.date-location {
text-wrap: nowrap;
}
.symbol {
position: relative;
width: 30px;
text-align: center;
}
.symbol[rowspan]::before {
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 50%;
width: 2px;
background-color: rgb(120, 120, 120);
transform: translateX(-50%);
z-index: 0;
}
.symbol::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 18px;
height: 18px;
z-index: 1;
}
.dot {
display: inline-block;
background-color: rgb(120, 120, 120);
border-radius: 100%;
width: 16px;
height: 16px;
line-height: 16px;
font-size: 12px;
font-weight: bold;
position: relative;
z-index: 2;
}
tr:nth-child(1) > .symbol::before {
top: 50%;
}
tr:nth-last-child(2) > .symbol::before {
bottom: 50%;
}
</style>

View File

@ -0,0 +1,96 @@
<script>
import ProjectsCard from './projectsCard.svelte';
let { independent_page = true } = $props();
</script>
{#if independent_page}
<title>Brock Tomlinson - Projects</title>
{/if}
<div>
<h2>Projects</h2>
<p>Top Featured and Recent Projects</p>
</div>
<div class="project-section">
<ProjectsCard
project_name="Personal Backend"
gitea_link="https://gitea.bajacloud.duckdns.org/darkicewolf50/darkicewolf50Cloud"
dockerhub_link="https://hub.docker.com/r/darkicewolf50/darkicewolf50cloud"
project_img="https://actix.rs/img/logo.png"
techs_used={['Rust', 'Actix', 'Github Actions', 'Docker', 'Traefik', 'Gitea', 'Git', 'Github']}
project_des="I find that this is a much better option in compareision to FastAPI as it does not require a post request
to input data instead it give the option for the url to give the parameters it needs. I don't have any complains about using Actix, its mature stable and fairly popular.
This backend application also uses comrak to convert markdown blogs into html docuemnts that are then seen by you the user.
This honestly was a fun challenge getting the blogs previews, ensuring correctness and not allowing for any unknown states,
this will serve as a great basis for any future backend requirements that I may have."
/>
<ProjectsCard
project_name="Portfolio Site Version 2.0.1"
website_link="https://darkicewolf50.pages.dev"
gitea_link="https://gitea.bajacloud.duckdns.org/darkicewolf50/personal_site"
project_img="https://res.cloudinary.com/dpgrgsh7g/image/upload/v1745630861/Portfolio_site_k4mhmj.png"
techs_used={['Rust', 'CSS', 'Dioxus', 'Git', 'Gitea']}
project_des="This project was a great test of my newly learned Rust.
This major update added functionality for the contact me, the blogs part of the site, as well as many minor
UI consistencies to ensure that all of the buttons and links felt like buttons and links.
I was surprise how easy it was to set up a discord webhook using the 'reqwest' crate.
As I continue on I find myself struggling with how and why to use databases for content I generate.
I think using tools like disocrd webhooks and email notifications are great for users but certainly not great for reading data from.
I was very satisfied with serde, and comrak for converting markdown fiels into html.
I use this extensively for the blogs search menu and the blog itself to display the blog itself in a consistent way without needing to write a whole library."
/>
<ProjectsCard
project_name="Portfolio Site 1.0.0"
website_link="https://darkicewolf50.github.io"
github_link="https://github.com/darkicewolf50/darkicewolf50.github.io"
project_img="https://res.cloudinary.com/dpgrgsh7g/image/upload/v1745630861/Portfolio_site_k4mhmj.png"
techs_used={['Rust', 'CSS', 'Dioxus', 'Git', 'Github']}
project_des="This project was a great test of my newly learned Rust.
It was certainly interesting to go through all of the stages of front end web developement, while the orignal and new found scope is not currently achieved, it will be on a later pass through.
I am very happy with how it turned out in compairison to my origanl site map, and wireframes.
Considering this phase one was accomplished in 3 working days I believe it is an excellent show of my skill."
/>
<ProjectsCard
project_name="UCalgary Baja Backend"
project_img="https://www.svgrepo.com/show/448221/docker.svg"
dockerhub_link="https://hub.docker.com/r/darkicewolf50/uofcbajacloud"
techs_used={['Python', 'FastAPI', 'Github Actions', 'Docker', 'Traefik', 'Git', 'Github']}
project_des="This is going to be extremely cost saving for the non-profit club UCalgary Baja.
Using automated uploads and linting to check the Python and FastAPI code was excellent for learning how to self-host a web server.
This was then upgraded later with the addition of treafik so that it could be SSL certified, this is also known as supporting HTTPS transmissions.
Ultimately it will serve as a great stepping stone for both myself an anyone else in UCalgary Baja Software subteam.
This will lead into using Actixs in the migration Soon to be."
/>
<ProjectsCard
project_name="UCalgary Baja Website"
website_link="https://uofcbaja.pages.dev"
project_img="https://res.cloudinary.com/dpgrgsh7g/image/upload/v1745633714/ucalgary-baja-site-April.png"
techs_used={[
'HTML5',
'CSS',
'JavaScript',
'Markdown',
'YAML',
'React',
'Git',
'Github',
'Cloudflare'
]}
project_des="The flexibility that we achieved using React,
rather than a locked down platform or framework has allows all the Software members of UCalgary Baja to learn infinitely more.
This isn't to say that it is faster or have additional perks of using 'non-code website builders'.
This is provided massive opportunities to learn teach and save on cost compaired to the website builders.
Overall I would say this will be worth it in the long run and opened my eyes to different website hosting providers,
with their associated perks and costs.
When we change it, it will most likely we re-written in Vue as there is a good non-depreciated way to initalize the framework."
/>
</div>
<style>
.project-section {
display: flex;
flex-direction: row;
flex-wrap: wrap;
column-gap: 1svw;
}
</style>

View File

@ -0,0 +1,438 @@
<script>
const tech_table_lookup = (to_lookup) => {
let tech_to_return = {
tech_name: 'Not in table',
tech_logo: '',
project_site: '',
skill_level: 0
};
// let tech_to_return = null; // Default value for tech_to_return
for (let tech of TECH_TABLE) {
if (tech.tech_name === to_lookup) {
tech_to_return = tech;
break; // Optional: stop the loop once the match is found
}
}
return tech_to_return;
};
const TECH_TABLE = [
{
tech_name: 'Rust',
tech_logo: 'https://www.svgrepo.com/show/374056/rust.svg',
project_site: 'https://www.rust-lang.org',
skill_level: 60
},
{
tech_name: 'Python',
tech_logo: 'https://www.svgrepo.com/show/452091/python.svg',
project_site: 'https://www.python.org',
skill_level: 50
},
{
tech_name: 'JavaScript',
tech_logo: 'https://www.svgrepo.com/show/303206/javascript-logo.svg',
project_site: 'https://www.python.org',
skill_level: 60
},
{
tech_name: 'YAML',
tech_logo: 'https://yaml.org/favicon.svg',
project_site: 'https://yaml.org',
skill_level: 95
},
{
tech_name: 'Github',
tech_logo: 'https://www.svgrepo.com/show/512317/github-142.svg',
project_site: 'https://github.com/darkicewolf50',
skill_level: 80
},
{
tech_name: 'Email',
tech_logo: 'https://www.svgrepo.com/show/491226/email.svg',
project_site: 'mailto:darkicewolf50@gmail.com',
skill_level: 100
},
{
tech_name: 'LinkedIn',
tech_logo: 'https://www.svgrepo.com/show/521725/linkedin.svg',
project_site: 'https://www.linkedin.com/in/brock-tomlinson/',
skill_level: 40
},
{
tech_name: 'Twitch',
tech_logo: 'https://www.svgrepo.com/show/519925/twitch.svg',
project_site: 'https://www.twitch.tv/darkicewolf50',
skill_level: 60
},
{
tech_name: 'Youtube',
tech_logo: 'https://www.svgrepo.com/show/521936/youtube.svg',
project_site: 'https://www.youtube.com/@darkicewolf50',
skill_level: 40
},
{
tech_name: 'Internet',
tech_logo: 'https://www.svgrepo.com/show/490809/internet.svg',
project_site: 'https://google.com',
skill_level: 99
},
{
tech_name: 'React',
tech_logo: 'https://www.svgrepo.com/show/452092/react.svg',
project_site: 'https://react.dev',
skill_level: 70
},
{
tech_name: 'Docker',
tech_logo: 'https://www.svgrepo.com/show/448221/docker.svg',
project_site: 'https://www.docker.com',
skill_level: 70
},
{
tech_name: 'FastAPI',
tech_logo: 'https://fastapi.tiangolo.com/img/favicon.png',
project_site: 'https://fastapi.tiangolo.com',
skill_level: 80
},
{
tech_name: 'Actix',
tech_logo: 'https://actix.rs/img/logo.png',
project_site: 'https://actix.rs',
skill_level: 20
},
{
tech_name: 'HTML5',
tech_logo: 'https://www.svgrepo.com/show/452228/html-5.svg',
project_site: 'https://google.com',
skill_level: 90
},
{
tech_name: 'CSS',
tech_logo: 'https://www.svgrepo.com/show/452185/css-3.svg',
project_site: 'https://google.com',
skill_level: 65
},
{
tech_name: 'Git',
tech_logo: 'https://www.svgrepo.com/show/452210/git.svg',
project_site: 'https://git-scm.com',
skill_level: 55
},
{
tech_name: 'Github Actions',
tech_logo: 'https://cdn.simpleicons.org/githubactions/2088FF',
project_site: 'https://github.com/',
skill_level: 50
},
{
tech_name: 'Vs Code',
tech_logo: 'https://www.svgrepo.com/show/452129/vs-code.svg',
project_site: 'https://code.visualstudio.com',
skill_level: 60
},
{
tech_name: 'Gitea',
tech_logo: 'https://about.gitea.com/gitea.png',
project_site: 'https://about.gitea.com',
skill_level: 85
},
{
tech_name: 'AWS',
tech_logo: 'https://www.svgrepo.com/show/448266/aws.svg',
project_site: 'https://aws.amazon.com',
skill_level: 30
},
{
tech_name: 'Firefox',
tech_logo: 'https://www.svgrepo.com/show/378808/firefox-developer-edition-57-70.svg',
project_site: 'https://www.mozilla.org/en-CA/firefox/developer/',
skill_level: 80
},
{
tech_name: 'Markdown',
tech_logo: 'https://www.svgrepo.com/show/510065/markdown.svg',
project_site: 'https://www.markdownguide.org',
skill_level: 90
},
{
tech_name: 'Prettier',
tech_logo: 'https://prettier.io/icon.png',
project_site: 'https://prettier.io',
skill_level: 90
},
{
tech_name: 'Cloudflare',
tech_logo:
'https://qualified-production.s3.us-east-1.amazonaws.com/uploads/3b522ef84c409e4457032e4b4e3b984abbc92522c6f100f4ccc55c0ccfd3062b.png',
project_site: 'https://www.cloudflare.com/en-ca/',
skill_level: 65
},
{
tech_name: 'Netlify',
tech_logo:
'https://qualified-production.s3.us-east-1.amazonaws.com/uploads/0f63ae7280d8d193e346973a1915bf99aea8c63e254eb062bad0bde99b43a9b7.png',
project_site: 'https://www.netlify.com',
skill_level: 60
},
{
tech_name: 'Vercel',
tech_logo: 'https://www.svgrepo.com/show/361653/vercel-logo.svg',
project_site: 'https://vercel.com/home',
skill_level: 60
},
{
tech_name: 'Dioxus',
tech_logo: 'https://dioxuslabs.com/assets/smalllogo-b1926fd214dc8427.png',
project_site: 'https://dioxuslabs.com',
skill_level: 70
},
{
tech_name: 'SvelteKit',
tech_logo: 'https://svelte.dev/favicon.png',
project_site: 'https://svelte.dev',
skill_level: 1
},
{
tech_name: 'Mongodb',
tech_logo: 'https://www.svgrepo.com/show/331488/mongodb.svg',
project_site: 'https://www.mongodb.com',
skill_level: 10
},
{
tech_name: 'Sqlite',
tech_logo: 'https://www.svgrepo.com/show/374094/sqlite.svg',
project_site: 'https://www.sqlite.org',
skill_level: 10
},
{
tech_name: 'PostgreSQL',
tech_logo: 'https://www.svgrepo.com/show/303301/postgresql-logo.svg',
project_site: 'https://www.postgresql.org',
skill_level: 10
},
{
tech_name: 'DynamoDB',
tech_logo: 'https://www.svgrepo.com/show/473526/amazondynamodb.svg',
project_site: 'https://aws.amazon.com/dynamodb/',
skill_level: 70
},
{
tech_name: 'Diesel',
tech_logo:
'https://res.cloudinary.com/dpgrgsh7g/image/upload/v1745443276/diesel_logo_ujtvia.png',
project_site: 'https://diesel.rs',
skill_level: 10
},
{
tech_name: 'Kubernetes',
tech_logo: 'https://kubernetes.io/images/kubernetes.png',
project_site: 'https://kubernetes.io',
skill_level: 5
},
{
tech_name: 'Terraform',
tech_logo: 'https://www.svgrepo.com/show/448253/terraform.svg',
project_site: 'https://www.terraform.io',
skill_level: 15
},
{
tech_name: 'Traefik',
tech_logo: 'https://hub.docker.com/api/media/repos_logo/v1/library%2Ftraefik',
project_site: 'https://traefik.io/traefik/',
skill_level: 60
}
];
let {
website_link,
github_link,
gitea_link,
dockerhub_link,
project_name,
techs_used,
project_des,
project_img = 'https://picsum.photos/200'
} = $props();
</script>
<div class="project-card" key={project_name + techs_used}>
<img src={project_img} alt="dashboard of project or the logo of the project" />
<div class="project-title-info">
<h3>{project_name}</h3>
<div>
{#if github_link}
<a href={github_link}>
<img
class="lookup"
src={tech_table_lookup('Github').tech_logo}
alt={{ techs_used } + "'s logo/icon"}
/>
</a>
{/if}
{#if gitea_link}
<a href={gitea_link} class="gitea">
<img
class="lookup"
src={tech_table_lookup('Gitea').tech_logo}
alt={{ techs_used } + "'s logo/icon"}
/>
</a>
{/if}
{#if dockerhub_link}
<a href={dockerhub_link} class="dockerhub">
<img
class="lookup"
src={tech_table_lookup('Docker').tech_logo}
alt={{ techs_used } + "'s logo/icon"}
/>
</a>
{/if}
{#if website_link}
<a href={website_link}>
<img
class="lookup"
src={tech_table_lookup('Internet').tech_logo}
alt={{ techs_used } + "'s logo/icon"}
/>
</a>
{/if}
</div>
</div>
<div>
<p>{project_des}</p>
</div>
<div class="project-tech-logos">
{#each techs_used as tech, index}
<img
key={tech + index}
src={tech_table_lookup(tech).tech_logo}
alt={{ techs_used } + "'s logo/icon"}
/>
{/each}
</div>
</div>
<style>
.project-card {
flex: 0 1 30%;
margin-bottom: 3svh;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
}
@media only screen and (max-width: 800px) {
.project-card {
flex: 0 1 auto;
}
}
.project-card img {
max-width: 96%;
max-height: 200px;
justify-self: center;
margin: 0svh 1svw;
padding-top: 1svh;
object-fit: contain;
color: transparent;
display: flex;
}
.project-title-info {
display: flex;
flex-direction: row;
height: 50px;
border-bottom: var(--underlineTitle);
border-radius: var(--underlineTitleBorderRadius);
margin: 0px 2svw;
padding: 0px 2svw;
justify-content: space-between;
align-items: center;
flex-wrap: nowrap;
}
.project-title-info h3 {
margin: 0px;
text-align: start;
white-space: nowrap;
align-self: center;
font-weight: normal;
text-wrap: wrap;
border-radius: var(--underlineTitleBorderRadius);
}
.lookup {
height: var(--img-width);
width: var(--img-height);
margin: 1svh 6px;
padding: 0px;
filter: invert() hue-rotate(180deg);
}
.gitea .lookup {
filter: grayscale(100%) invert(100%) brightness(2.5);
}
.dockerhub .lookup {
filter: grayscale(100%) invert(100%) brightness(2.5);
}
.lookup:hover {
filter: brightness(0) saturate(100%) invert(65%) sepia(13%) saturate(733%) hue-rotate(187deg)
brightness(95%) contrast(90%);
}
.gitea .lookup:hover {
filter: grayscale(100%) invert(165%) sepia(15%) saturate(733%) hue-rotate(185deg)
brightness(1.3) contrast(90%) saturate(100%);
}
.dockerhub .lookup:hover {
filter: grayscale(100%) invert(165%) sepia(15%) saturate(733%) hue-rotate(185deg)
brightness(1.3) contrast(90%) saturate(100%);
}
.project-title-info div {
display: flex;
gap: 1svw;
justify-content: flex-end;
border-bottom: none;
}
.project-card div p {
display: flex;
width: 90%;
justify-self: center;
text-align: start;
}
.project-tech-logos {
display: flex;
flex-flow: row wrap;
align-items: center;
align-self: center;
width: 90%;
justify-content: flex-start;
column-gap: 0.5svw;
row-gap: 1svw;
padding-left: 2svw;
padding-bottom: 1svh;
}
.project-tech-logos img {
aspect-ratio: 1;
height: var(--img-width);
width: var(--img-height);
}
</style>

View File

@ -0,0 +1,316 @@
<script>
const tech_table_lookup = (to_lookup) => {
let tech_to_return = {
tech_name: 'Not in table',
tech_logo: '',
project_site: '',
skill_level: 0
};
// let tech_to_return = null; // Default value for tech_to_return
for (let tech of TECH_TABLE) {
if (tech.tech_name === to_lookup) {
tech_to_return = tech;
break; // Optional: stop the loop once the match is found
}
}
return tech_to_return;
};
const TECH_TABLE = [
{
tech_name: 'Rust',
tech_logo: 'https://www.svgrepo.com/show/374056/rust.svg',
project_site: 'https://www.rust-lang.org',
skill_level: 60
},
{
tech_name: 'Python',
tech_logo: 'https://www.svgrepo.com/show/452091/python.svg',
project_site: 'https://www.python.org',
skill_level: 50
},
{
tech_name: 'JavaScript',
tech_logo: 'https://www.svgrepo.com/show/303206/javascript-logo.svg',
project_site: 'https://www.python.org',
skill_level: 60
},
{
tech_name: 'YAML',
tech_logo: 'https://yaml.org/favicon.svg',
project_site: 'https://yaml.org',
skill_level: 95
},
{
tech_name: 'Github',
tech_logo: 'https://www.svgrepo.com/show/512317/github-142.svg',
project_site: 'https://github.com/darkicewolf50',
skill_level: 80
},
{
tech_name: 'Email',
tech_logo: 'https://www.svgrepo.com/show/491226/email.svg',
project_site: 'mailto:darkicewolf50@gmail.com',
skill_level: 100
},
{
tech_name: 'LinkedIn',
tech_logo: 'https://www.svgrepo.com/show/521725/linkedin.svg',
project_site: 'https://www.linkedin.com/in/brock-tomlinson/',
skill_level: 40
},
{
tech_name: 'Twitch',
tech_logo: 'https://www.svgrepo.com/show/519925/twitch.svg',
project_site: 'https://www.twitch.tv/darkicewolf50',
skill_level: 60
},
{
tech_name: 'Youtube',
tech_logo: 'https://www.svgrepo.com/show/521936/youtube.svg',
project_site: 'https://www.youtube.com/@darkicewolf50',
skill_level: 40
},
{
tech_name: 'Internet',
tech_logo: 'https://www.svgrepo.com/show/490809/internet.svg',
project_site: 'https://google.com',
skill_level: 99
},
{
tech_name: 'React',
tech_logo: 'https://www.svgrepo.com/show/452092/react.svg',
project_site: 'https://react.dev',
skill_level: 70
},
{
tech_name: 'Docker',
tech_logo: 'https://www.svgrepo.com/show/448221/docker.svg',
project_site: 'https://www.docker.com',
skill_level: 70
},
{
tech_name: 'FastAPI',
tech_logo: 'https://fastapi.tiangolo.com/img/favicon.png',
project_site: 'https://fastapi.tiangolo.com',
skill_level: 80
},
{
tech_name: 'Actix',
tech_logo: 'https://actix.rs/img/logo.png',
project_site: 'https://actix.rs',
skill_level: 20
},
{
tech_name: 'HTML5',
tech_logo: 'https://www.svgrepo.com/show/452228/html-5.svg',
project_site: 'https://google.com',
skill_level: 90
},
{
tech_name: 'CSS',
tech_logo: 'https://www.svgrepo.com/show/452185/css-3.svg',
project_site: 'https://google.com',
skill_level: 65
},
{
tech_name: 'Git',
tech_logo: 'https://www.svgrepo.com/show/452210/git.svg',
project_site: 'https://git-scm.com',
skill_level: 55
},
{
tech_name: 'Github Actions',
tech_logo: 'https://cdn.simpleicons.org/githubactions/2088FF',
project_site: 'https://github.com/',
skill_level: 50
},
{
tech_name: 'Vs Code',
tech_logo: 'https://www.svgrepo.com/show/452129/vs-code.svg',
project_site: 'https://code.visualstudio.com',
skill_level: 60
},
{
tech_name: 'Gitea',
tech_logo: 'https://about.gitea.com/gitea.png',
project_site: 'https://about.gitea.com',
skill_level: 85
},
{
tech_name: 'AWS',
tech_logo: 'https://www.svgrepo.com/show/448266/aws.svg',
project_site: 'https://aws.amazon.com',
skill_level: 30
},
{
tech_name: 'Firefox',
tech_logo: 'https://www.svgrepo.com/show/378808/firefox-developer-edition-57-70.svg',
project_site: 'https://www.mozilla.org/en-CA/firefox/developer/',
skill_level: 80
},
{
tech_name: 'Markdown',
tech_logo: 'https://www.svgrepo.com/show/510065/markdown.svg',
project_site: 'https://www.markdownguide.org',
skill_level: 90
},
{
tech_name: 'Prettier',
tech_logo: 'https://prettier.io/icon.png',
project_site: 'https://prettier.io',
skill_level: 90
},
{
tech_name: 'Cloudflare',
tech_logo:
'https://qualified-production.s3.us-east-1.amazonaws.com/uploads/3b522ef84c409e4457032e4b4e3b984abbc92522c6f100f4ccc55c0ccfd3062b.png',
project_site: 'https://www.cloudflare.com/en-ca/',
skill_level: 65
},
{
tech_name: 'Netlify',
tech_logo:
'https://qualified-production.s3.us-east-1.amazonaws.com/uploads/0f63ae7280d8d193e346973a1915bf99aea8c63e254eb062bad0bde99b43a9b7.png',
project_site: 'https://www.netlify.com',
skill_level: 60
},
{
tech_name: 'Vercel',
tech_logo: 'https://www.svgrepo.com/show/361653/vercel-logo.svg',
project_site: 'https://vercel.com/home',
skill_level: 60
},
{
tech_name: 'Dioxus',
tech_logo: 'https://dioxuslabs.com/assets/smalllogo-b1926fd214dc8427.png',
project_site: 'https://dioxuslabs.com',
skill_level: 70
},
{
tech_name: 'SvelteKit',
tech_logo: 'https://svelte.dev/favicon.png',
project_site: 'https://svelte.dev',
skill_level: 1
},
{
tech_name: 'Mongodb',
tech_logo: 'https://www.svgrepo.com/show/331488/mongodb.svg',
project_site: 'https://www.mongodb.com',
skill_level: 10
},
{
tech_name: 'Sqlite',
tech_logo: 'https://www.svgrepo.com/show/374094/sqlite.svg',
project_site: 'https://www.sqlite.org',
skill_level: 10
},
{
tech_name: 'PostgreSQL',
tech_logo: 'https://www.svgrepo.com/show/303301/postgresql-logo.svg',
project_site: 'https://www.postgresql.org',
skill_level: 10
},
{
tech_name: 'DynamoDB',
tech_logo: 'https://www.svgrepo.com/show/473526/amazondynamodb.svg',
project_site: 'https://aws.amazon.com/dynamodb/',
skill_level: 70
},
{
tech_name: 'Diesel',
tech_logo:
'https://res.cloudinary.com/dpgrgsh7g/image/upload/v1745443276/diesel_logo_ujtvia.png',
project_site: 'https://diesel.rs',
skill_level: 10
},
{
tech_name: 'Kubernetes',
tech_logo: 'https://kubernetes.io/images/kubernetes.png',
project_site: 'https://kubernetes.io',
skill_level: 5
},
{
tech_name: 'Terraform',
tech_logo: 'https://www.svgrepo.com/show/448253/terraform.svg',
project_site: 'https://www.terraform.io',
skill_level: 15
},
{
tech_name: 'Traefik',
tech_logo: 'https://hub.docker.com/api/media/repos_logo/v1/library%2Ftraefik',
project_site: 'https://traefik.io/traefik/',
skill_level: 60
}
];
let { tech_props } = $props();
let props_tech = $derived(tech_table_lookup(tech_props));
</script>
<a href={props_tech.project_site} class="tech-card">
<img src={props_tech.tech_logo} alt={tech_props + "'s logo"} />
<h4>{tech_props}</h4>
<progress value={props_tech.skill_level} max="100"></progress>
</a>
<style>
a {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
flex: 0 1 70px;
text-decoration: none;
color: inherit;
padding: 0px 0.5svw;
padding-top: 2svh;
padding-bottom: 0.5svh;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
}
img {
width: 32px;
height: 32px;
aspect-ratio: 1;
object-fit: contain;
}
progress {
width: 90%;
margin-bottom: 0.5svh;
overflow: hidden;
appearance: none;
border-radius: 999px;
justify-self: flex-end;
align-self: center;
}
h4 {
margin: 1svh 0.5svw;
width: 80px;
text-align: center;
font-weight: normal;
}
/* for chromium browsers */
progress::-webkit-progress-value {
background-color: steelblue;
/* border-radius: 999px; */
}
/* for firefox browsers */
progress::-moz-progress-bar {
background-color: steelblue;
/* border-radius: 999px; */
}
</style>

View File

@ -0,0 +1,45 @@
<script>
import TechCard from './techCard.svelte';
let { cat, tech_vec } = $props();
</script>
<div class="tech-cat">
<h3>{cat}</h3>
<div class="tech-row">
{#each tech_vec as tech}
<TechCard tech_props={tech} />
{/each}
</div>
</div>
<style>
:root {
--tech-gap: 4svw;
}
h3 {
border-bottom: var(--underlineTitle);
border-radius: var(--underlineTitleBorderRadius);
display: flex;
margin: 2svh 2svw;
padding: 0svh 2svw;
padding-bottom: 1svh;
}
.tech-cat {
padding: 0px 1svw;
padding-bottom: 2svh;
margin-bottom: 3svh;
flex: 1 1 auto;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
}
.tech-row {
display: flex;
flex-flow: row wrap;
justify-content: space-evenly;
row-gap: 1svh;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@ -40,10 +40,15 @@
</footer>
<style>
:root {
:global(:root) {
--underlineTitle: 4px solid purple;
--underlineTitleBorderRadius: 4px;
--img-width: 32px;
--img-height: 32px;
--card-background-color: rgba(38, 38, 38, 0.5);
--card-border-radius: 0.5rem;
}
:global(body) {
background-color: #0f1116;
color: #ffffff;
@ -51,6 +56,15 @@
margin: 20px;
}
:global(h2) {
border-bottom: var(--underlineTitle);
border-radius: var(--underlineTitleBorderRadius);
display: flex;
margin: 2svh 2svw;
padding: 0svh 2svw;
padding-bottom: 1svh;
}
nav {
display: flex;
flex-direction: row;

View File

@ -1,2 +1,152 @@
<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
<script>
import Contact from '$lib/components/contact.svelte';
import Experience from '$lib/components/experience.svelte';
import Projects from '$lib/components/projects/projects.svelte';
import TechCat from '$lib/components/techs/techCat.svelte';
let languages = ['Rust', 'Python', 'YAML', 'HTML5', 'CSS', 'JavaScript', 'Markdown'];
let backend = ['Actix', 'FastAPI', 'Dioxus', 'Diesel'];
let frontend = ['React', 'Dioxus', 'Vue'];
let databases = ['Sqlite', 'PostgreSQL', 'Mongodb', 'DynamoDB'];
let tools = [
'Vs Code',
'Git',
'Prettier',
'Firefox',
'Github Actions',
'Traefik',
'Docker',
'Kubernetes',
'Terraform'
];
let platforms = ['AWS', 'Cloudflare', 'Vercel', 'Netlify', 'Gitea', 'Github'];
</script>
<title>Brock Tomlinson - Home</title>
<div>
<div id="home-intro">
<h1>Hi I'm Brock</h1>
<p>
a fourth year Software Engineering Student specializing in full-stack development with a
strong focus on backend technologies. I am developing the language of how to design, develop,
and create programs that are to industry standards and reasonably efficent. I bring the
lessons learned from each project I have completed, learning from the mistakes I have made and
bringing improved versions forward into the next project.
</p>
<p>
As of writing this I intend to bring the knowledge learned from my time at university in
Software Engineering onto a Baja SAE car, where we can collect data remotely and graph data
for instantaneous and future analysis, during vechile operation.
</p>
<p>
I grew up in a small ski town where, I started learning about programming, from of course
Minecraft, where I thought the application of this was so futuristic and downright cool that I
knew I wanted to persue it further. While living there I spend a majority of my time outside
of school swimming competitively, where I ranked top 10 in BC. Along with swimming I spend a
lot of time volunteering with fundraising events and coaching the local Special Olympics swim
team.
</p>
<p>
I adore problem solving and building cool stuff, I'm happy to jump in and get started!
<a href="/contact"> <button>Let's create something great together!</button></a>
</p>
</div>
</div>
<div class="technologies">
<h2>Technology</h2>
<p>Here is what I prefer to use and their self assessed skill</p>
<!-- <p>Here is what I developed skills in.</p> -->
<div class="technologies-cat">
<TechCat cat="Languages" tech_vec={languages} />
<TechCat cat="Backend" , tech_vec={backend} />
<TechCat cat="Frontend" , tech_vec={frontend} />
<TechCat cat="Databases" , tech_vec={databases} />
<TechCat cat="Platforms" , tech_vec={platforms} />
<TechCat cat="Tools" , tech_vec={tools} />
</div>
</div>
<Contact />
<Projects independent_page={false} />
<div id="experience">
<h2>Experience</h2>
<div>
<Experience professional_jobs={true} />
<Experience professional_jobs={false} />
</div>
</div>
<style>
#home-intro {
display: flex;
flex-direction: column;
width: 90%;
margin: 2svh auto;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
}
h1 {
border-bottom: var(--underlineTitle);
border-radius: var(--underlineTitleBorderRadius);
display: flex;
margin: 2svh 2svw;
padding: 0svh 2svw;
padding-bottom: 1svh;
}
div:first-of-type p {
margin: 1svh 4svw;
padding: 0svh 2svw;
padding-bottom: 1svh;
}
button {
display: block;
background-color: transparent;
color: inherit;
border-radius: var(--card-border-radius);
background-color: var(--card-background-color);
border: 2px solid purple;
padding: 2svh 0.5svw;
margin: 2svh 0svw;
cursor: pointer;
}
a {
text-decoration: none;
color: inherit;
}
a:hover {
color: #91a4d2;
}
.technologies {
display: flex;
flex-direction: column;
}
.technologies-cat {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
column-gap: 1svw;
row-gap: 1svh;
}
#experience {
display: flex;
flex-direction: column;
margin-bottom: 4svh;
}
#experience div {
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
margin: 4svh 0px;
}
</style>

View File

@ -0,0 +1,109 @@
<script>
import Contact from '$lib/components/contact.svelte';
let contactName = $state('');
let contactEmail = $state('');
let contactMessage = $state('');
let error_box_message = $state('');
</script>
<title>Brock Tomlinson - Contact</title>
<div id="ContactMe">
<div>
<h2>Get in Touch</h2>
<p>
Please feel free to reach out about questions, opporunities or just want to connect. Feel free
to either fill out this form or contact me through one of the many of the platforms below
</p>
</div>
<form
onsubmit={(e) => {
e.preventDefault();
}}
>
<label for="name">Name</label>
<input type="text" id="name" bind:value={contactName} />
<label for="email">Email</label>
<input type="email" id="email" bind:value={contactEmail} />
<label for="message">Message</label>
<textarea id="message" bind:value={contactMessage}></textarea>
<p>{error_box_message}</p>
<button onclick={() => console.log('Clicked')}> Submit </button>
</form>
</div>
<Contact />
<style>
#ContactMe {
display: flex;
flex-flow: row wrap;
column-gap: 2svw;
row-gap: 4svh;
min-height: 70svh;
margin-top: 4svh;
justify-content: space-evenly;
}
div div,
form {
display: flex;
flex-grow: 1;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
flex-direction: column;
justify-content: center;
margin: 2svh 0.5svw;
padding: 2svh 1svw;
max-width: 600px;
}
p {
margin: 2svh 0svw;
padding: 0svh 0svw;
}
input {
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
border-color: rgba(245, 245, 245, 0.5);
border-width: 2px;
padding: 1svh 0svw;
margin: 1svh 0.5svw;
color: inherit;
align-items: start;
}
textarea {
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
border-color: rgba(245, 245, 245, 0.4);
border-width: 2px;
padding: 1svh 0svw;
margin: 1svh 0.5svw;
color: inherit;
align-items: start;
min-height: 25svh;
}
button {
border-radius: var(--card-border-radius);
border-color: rgba(245, 245, 245, 0.5);
padding: 1svh 0svw;
margin: 1svh 0.5svw;
color: inherit;
align-items: start;
background-color: rgba(0, 128, 0, 0.6);
border-color: transparent;
}
button:hover {
cursor: pointer;
color: #91a4d2;
background-color: rgba(0, 150, 0, 0.6);
}
</style>

View File

@ -0,0 +1,5 @@
<script>
import Projects from '$lib/components/projects/projects.svelte';
</script>
<Projects />