Compare commits

..

1 Commits

Author SHA1 Message Date
0c1bd5218b feat(next): started porting over from dioxus to nextjs 2025-05-08 17:19:55 -06:00
71 changed files with 11865 additions and 1819 deletions

View File

@ -1,2 +0,0 @@
github: darkicewolf50
ko_fi: darkicewolf50

2
.github/FUNDING.yml vendored
View File

@ -1,2 +0,0 @@
github: darkicewolf50
ko_fi: darkicewolf50

50
.gitignore vendored
View File

@ -1,7 +1,45 @@
# Generated by Cargo
# will have compiled files and executables
/target
.DS_Store
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# These are backup files generated by rustfmt
**/*.rs.bk
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
# wrangler files
.wrangler
.dev.vars*

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"files.associations": {
"wrangler.json": "jsonc"
}
}

View File

@ -1,11 +1,67 @@
# Personal Site
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`c3`](https://developers.cloudflare.com/pages/get-started/c3).
#rust #dioxus
## Getting Started
This is the code that runs my WASM site. It currently uses dioxus 0.6 and eagerly awaiting for diouxs 0.7 as it looks to be a great update.
First, run the development server:
This is a mirror of the repo, live code is hosted [here](https://gitea.bajacloud.duckdns.org/darkicewolf50/personal_site) as well as any testing of the code.
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
I do not consent for this code to be used in any training data for AI or AI like products or services.
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
This is only uploaded here so that I can bet those sweet sweet green marks on my gituhb profile.
## Cloudflare integration
Besides the `dev` script mentioned above `c3` has added a few extra scripts that allow you to integrate the application with the [Cloudflare Pages](https://pages.cloudflare.com/) environment, these are:
- `pages:build` to build the application for Pages using the [`@cloudflare/next-on-pages`](https://github.com/cloudflare/next-on-pages) CLI
- `preview` to locally preview your Pages application using the [Wrangler](https://developers.cloudflare.com/workers/wrangler/) CLI
- `deploy` to deploy your Pages application using the [Wrangler](https://developers.cloudflare.com/workers/wrangler/) CLI
> __Note:__ while the `dev` script is optimal for local development you should preview your Pages application as well (periodically or before deployments) in order to make sure that it can properly work in the Pages environment (for more details see the [`@cloudflare/next-on-pages` recommended workflow](https://github.com/cloudflare/next-on-pages/blob/main/internal-packages/next-dev/README.md#recommended-development-workflow))
### Bindings
Cloudflare [Bindings](https://developers.cloudflare.com/pages/functions/bindings/) are what allows you to interact with resources available in the Cloudflare Platform.
You can use bindings during development, when previewing locally your application and of course in the deployed application:
- To use bindings in dev mode you need to define them in the `next.config.js` file under `setupDevBindings`, this mode uses the `next-dev` `@cloudflare/next-on-pages` submodule. For more details see its [documentation](https://github.com/cloudflare/next-on-pages/blob/05b6256/internal-packages/next-dev/README.md).
- To use bindings in the preview mode you need to add them to the `pages:preview` script accordingly to the `wrangler pages dev` command. For more details see its [documentation](https://developers.cloudflare.com/workers/wrangler/commands/#dev-1) or the [Pages Bindings documentation](https://developers.cloudflare.com/pages/functions/bindings/).
- To use bindings in the deployed application you will need to configure them in the Cloudflare [dashboard](https://dash.cloudflare.com/). For more details see the [Pages Bindings documentation](https://developers.cloudflare.com/pages/functions/bindings/).
#### KV Example
`c3` has added for you an example showing how you can use a KV binding.
In order to enable the example:
- Search for javascript/typescript lines containing the following comment:
```ts
// KV Example:
```
and uncomment the commented lines below it (also uncomment the relevant imports).
- In the `wrangler.jsonc` file add the following configuration line:
```
"kv_namespaces": [{ "binding": "MY_KV_NAMESPACE", "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }],
```
- If you're using TypeScript run the `cf-typegen` script to update the `env.d.ts` file:
```bash
npm run cf-typegen
# or
yarn cf-typegen
# or
pnpm cf-typegen
# or
bun cf-typegen
```
After doing this you can run the `dev` or `preview` script and visit the `/api/hello` route to see the example in action.
Finally, if you also want to see the example work in the deployed application make sure to add a `MY_KV_NAMESPACE` binding to your Pages application in its [dashboard kv bindings settings section](https://dash.cloudflare.com/?to=/:account/pages/view/:pages-project/settings/functions#kv_namespace_bindings_section). After having configured it make sure to re-deploy your application.

View File

@ -1,2 +0,0 @@
User-agent: *
Disallow: /blogs/

View File

@ -1,246 +0,0 @@
#blog {
margin-top: 2svh;
min-height: 80svh;
}
#blog_info {
display: flex;
flex-direction: column;
}
#blog_info ul {
display: flex;
flex-direction: row;
list-style-type: none;
margin: 0px;
padding: 0px;
}
#blog_info p {
padding: 2svh 0svw;
margin: 0px;
}
#blog_info h1 {
padding: 1svh 1svw;
margin: 2svh 0svw;
margin-bottom: 0px;
font-size: 2em;
}
#blog_info div {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 1svh 0svw;
border-bottom: var(--underlineTitle);
border-radius: var(--underlineTitleBorderRadius);
}
#blog_info div p {
padding: 0px;
margin: 0px;
}
#blog_info div div {
margin: 0px;
padding: 0px;
border: none;
}
#blog_info div p:last-child {
margin-right: 10svh;
}
#blog_info div ul li {
background-color: rgba(128, 0, 128, 0.2);
border-radius: 1rem;
padding: 0.25svh 8px;
margin: 0svh 0.25svh;
text-align: center;
}
#blog a {
color: #ffffff;
margin-top: 50px;
}
#blog a:hover {
color: #91a4d2;
}
#blog_content {
padding: 2svh 0svw;
}
#blog_content h1,
h2,
h3 {
margin: 0px;
padding: 1svh 0svw;
border-bottom: none;
}
#blog_content p {
padding: 1svh 0svw;
margin: 0px;
text-wrap: wrap;
max-width: 25rem;
}
#blog #blog_content p {
max-width: max-content;
}
#blogs {
display: flex;
flex-direction: column;
min-height: 80svh;
}
#blogs h1 {
border-bottom: var(--underlineTitle);
border-radius: var(--underlineTitleBorderRadius);
margin: 1svh 2svw;
padding: 1svh 2svw;
display: flex;
}
#blogs button {
/* background-color: transparent; */
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
border: none;
color: inherit;
font-size: x-large;
padding: 0.5rem;
margin: 1svh 0svw;
}
#blogs p {
margin: 0px;
padding: 0px;
}
#blogs a {
text-decoration: none;
color: inherit;
}
#blogs a:hover {
color: #91a4d2;
}
.blog-preview {
display: flex;
flex-direction: column;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
padding: 0svh 2svw;
}
#blogs .blog-preview h1 {
border-bottom: none;
padding: 0svh 1svw;
margin: 0px;
}
#blogs .blog-preview button {
width: max-content;
border: 2px solid rgba(145, 164, 210, 0.4);
border-radius: var(--card-border-radius);
font-size: medium;
margin-top: auto;
margin-bottom: 4svh;
}
#blogs .blog-preview #blog_info div p:last-child {
margin-right: 0svh;
margin-left: 2svw;
}
#blogs .blog-preview #blog_info div div p:last-child {
margin: 0svh 0.25svh;
padding: 0.25svh 8px;
}
#blogs-title {
display: flex;
flex-direction: column;
padding-bottom: 1svh;
}
#blogs-title p {
margin: 0svh 1svw;
padding: 1svh 0svw;
}
#blogs-on-show {
display: flex;
flex-flow: row wrap;
justify-content: center;
padding: 2svh 0svw;
row-gap: 2svh;
column-gap: 2svw;
}
#blog-loading {
display: flex;
flex-direction: column;
justify-self: center;
align-self: center;
justify-content: center;
align-items: center;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
padding: 2svh 2svw;
margin: 8svh 0svw;
}
#blog-out-of {
display: flex;
flex-direction: column;
justify-self: center;
align-self: center;
justify-content: center;
align-items: center;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
padding: 2svh 2svw;
margin: 8svh 0svw;
}
#blog-nav {
display: flex;
align-items: center;
position: relative;
padding: 0svh 2svw;
margin-top: auto;
margin-bottom: 2svh;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
}
#blog-nav a:last-child {
margin-left: auto;
}
#blog-nav div {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
justify-self: center;
margin: 1svh 0svw;
padding: 0.5rem;
column-gap: 1svw;
min-height: 28px;
font-size: large;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
position: absolute;
left: 50%;
transform: translateX(-50%);
}

14
eslint.config.mjs Normal file
View File

@ -0,0 +1,14 @@
import { dirname } from "path";
import { fileURLToPath } from "url";
import { FlatCompat } from "@eslint/eslintrc";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
});
const eslintConfig = [...compat.extends("next/core-web-vitals")];
export default eslintConfig;

7
jsconfig.json Normal file
View File

@ -0,0 +1,7 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
}
}

16
next.config.mjs Normal file
View File

@ -0,0 +1,16 @@
import { setupDevPlatform } from "@cloudflare/next-on-pages/next-dev";
// Here we use the @cloudflare/next-on-pages next-dev module to allow us to
// use bindings during local development (when running the application with
// `next dev`). This function is only necessary during development and
// has no impact outside of that. For more information see:
// https://github.com/cloudflare/next-on-pages/blob/main/internal-packages/next-dev/README.md
setupDevPlatform().catch(console.error);
/** @type {import('next').NextConfig} */
const nextConfig = {
output: "export",
trailingSlash: true, // optional: ensures all paths end with /
};
export default nextConfig;

7
old dioxus/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
# Generated by Cargo
# will have compiled files and executables
/target
.DS_Store
# These are backup files generated by rustfmt
**/*.rs.bk

View File

@ -402,7 +402,7 @@ dependencies = [
"cocoa-foundation 0.1.2",
"core-foundation 0.9.4",
"core-graphics 0.23.2",
"foreign-types 0.5.0",
"foreign-types",
"libc",
"objc",
]
@ -418,7 +418,7 @@ dependencies = [
"cocoa-foundation 0.2.0",
"core-foundation 0.10.0",
"core-graphics 0.24.0",
"foreign-types 0.5.0",
"foreign-types",
"libc",
"objc",
]
@ -571,7 +571,7 @@ dependencies = [
"bitflags 1.3.2",
"core-foundation 0.9.4",
"core-graphics-types 0.1.3",
"foreign-types 0.5.0",
"foreign-types",
"libc",
]
@ -584,7 +584,7 @@ dependencies = [
"bitflags 2.9.0",
"core-foundation 0.10.0",
"core-graphics-types 0.2.0",
"foreign-types 0.5.0",
"foreign-types",
"libc",
]
@ -796,7 +796,6 @@ dependencies = [
"dioxus-signals",
"dioxus-web",
"manganis",
"serde",
"warnings",
]
@ -1311,15 +1310,6 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
name = "encoding_rs"
version = "0.8.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
dependencies = [
"cfg-if",
]
[[package]]
name = "endi"
version = "1.1.0"
@ -1456,15 +1446,6 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared 0.1.1",
]
[[package]]
name = "foreign-types"
version = "0.5.0"
@ -1472,7 +1453,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
dependencies = [
"foreign-types-macros",
"foreign-types-shared 0.3.1",
"foreign-types-shared",
]
[[package]]
@ -1486,12 +1467,6 @@ dependencies = [
"syn 2.0.100",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "foreign-types-shared"
version = "0.3.1"
@ -1980,25 +1955,6 @@ dependencies = [
"syn 2.0.100",
]
[[package]]
name = "h2"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5"
dependencies = [
"atomic-waker",
"bytes",
"fnv",
"futures-core",
"futures-sink",
"http",
"indexmap 2.9.0",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "half"
version = "2.6.0"
@ -2123,7 +2079,6 @@ dependencies = [
"bytes",
"futures-channel",
"futures-util",
"h2",
"http",
"http-body",
"httparse",
@ -2134,39 +2089,6 @@ dependencies = [
"want",
]
[[package]]
name = "hyper-rustls"
version = "0.27.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2"
dependencies = [
"futures-util",
"http",
"hyper",
"hyper-util",
"rustls",
"rustls-pki-types",
"tokio",
"tokio-rustls",
"tower-service",
]
[[package]]
name = "hyper-tls"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
dependencies = [
"bytes",
"http-body-util",
"hyper",
"hyper-util",
"native-tls",
"tokio",
"tokio-native-tls",
"tower-service",
]
[[package]]
name = "hyper-util"
version = "0.1.11"
@ -2749,23 +2671,6 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "native-tls"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e"
dependencies = [
"libc",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
"schannel",
"security-framework",
"security-framework-sys",
"tempfile",
]
[[package]]
name = "ndk"
version = "0.9.0"
@ -3057,50 +2962,6 @@ version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "openssl"
version = "0.10.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da"
dependencies = [
"bitflags 2.9.0",
"cfg-if",
"foreign-types 0.3.2",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
]
[[package]]
name = "openssl-probe"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
[[package]]
name = "openssl-sys"
version = "0.9.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "option-ext"
version = "0.2.0"
@ -3179,12 +3040,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "personal_site"
version = "2.0.2"
version = "1.0.0"
dependencies = [
"dioxus",
"reqwest",
"serde",
"serde_json",
]
[[package]]
@ -3632,34 +3490,26 @@ checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb"
dependencies = [
"base64",
"bytes",
"encoding_rs",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"http-body-util",
"hyper",
"hyper-rustls",
"hyper-tls",
"hyper-util",
"ipnet",
"js-sys",
"log",
"mime",
"mime_guess",
"native-tls",
"once_cell",
"percent-encoding",
"pin-project-lite",
"rustls-pemfile",
"serde",
"serde_json",
"serde_urlencoded",
"sync_wrapper",
"system-configuration",
"tokio",
"tokio-native-tls",
"tokio-util",
"tower",
"tower-service",
@ -3694,20 +3544,6 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "ring"
version = "0.17.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
dependencies = [
"cc",
"cfg-if",
"getrandom 0.2.15",
"libc",
"untrusted",
"windows-sys 0.52.0",
]
[[package]]
name = "rustc-demangle"
version = "0.1.24"
@ -3755,48 +3591,6 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "rustls"
version = "0.23.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321"
dependencies = [
"once_cell",
"rustls-pki-types",
"rustls-webpki",
"subtle",
"zeroize",
]
[[package]]
name = "rustls-pemfile"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "rustls-pki-types"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79"
dependencies = [
"zeroize",
]
[[package]]
name = "rustls-webpki"
version = "0.103.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7149975849f1abb3832b246010ef62ccc80d3a76169517ada7188252b9cfb437"
dependencies = [
"ring",
"rustls-pki-types",
"untrusted",
]
[[package]]
name = "rustversion"
version = "1.0.20"
@ -3818,44 +3612,12 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "schannel"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "security-framework"
version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
dependencies = [
"bitflags 2.9.0",
"core-foundation 0.9.4",
"core-foundation-sys",
"libc",
"security-framework-sys",
]
[[package]]
name = "security-framework-sys"
version = "2.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "selectors"
version = "0.22.0"
@ -4241,12 +4003,6 @@ dependencies = [
"quote",
]
[[package]]
name = "subtle"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "1.0.109"
@ -4289,27 +4045,6 @@ dependencies = [
"syn 2.0.100",
]
[[package]]
name = "system-configuration"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
dependencies = [
"bitflags 2.9.0",
"core-foundation 0.9.4",
"system-configuration-sys",
]
[[package]]
name = "system-configuration-sys"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "system-deps"
version = "6.2.2"
@ -4499,26 +4234,6 @@ dependencies = [
"syn 2.0.100",
]
[[package]]
name = "tokio-native-tls"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
dependencies = [
"native-tls",
"tokio",
]
[[package]]
name = "tokio-rustls"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b"
dependencies = [
"rustls",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.14"
@ -4743,12 +4458,6 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "url"
version = "2.5.4"
@ -4791,12 +4500,6 @@ version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "version-compare"
version = "0.2.0"
@ -5710,12 +5413,6 @@ dependencies = [
"synstructure",
]
[[package]]
name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
[[package]]
name = "zerovec"
version = "0.10.4"

View File

@ -1,15 +1,13 @@
[package]
name = "personal_site"
version = "2.0.2"
version = "1.0.0"
authors = ["darkicewolf50 <brock.tomlinson@ucalgary.ca>"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dioxus = { version = "0.6.0", features = ["router"] }
reqwest = { version = "0.12.15", features = ["json"] }
serde_json = "1"
serde = { version = "1.0", features = ["derive"] }
[features]
default = ["web"]
@ -19,9 +17,7 @@ web = ["dioxus/web"]
desktop = ["dioxus/desktop"]
# The feature that are only required for the mobile = ["dioxus/mobile"] build target should be optional and only enabled in the mobile = ["dioxus/mobile"] feature
mobile = ["dioxus/mobile"]
ssg = ["dioxus/fullstack"]
# "fullstack"
[profile]
[profile.wasm-dev]

View File

@ -1,15 +1,9 @@
<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 OPR/118.0.0.0" version="26.2.14" pages="2">
<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 OPR/117.0.0.0" version="26.2.13" pages="2">
<diagram id="A2VB4WInwAW6etmFULTm" name="Sitemap">
<mxGraphModel dx="1756" dy="678" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<mxGraphModel dx="1171" dy="812" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="tu1BIFyJs8wWzZwwhIyV-44" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-20" target="tu1BIFyJs8wWzZwwhIyV-24">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-20" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="960" y="420" width="140" height="280" as="geometry" />
</mxCell>
<mxCell id="e5eKH99aat-bvalqy8uv-24" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#000000;fillColor=#FFFFFF;" parent="1" source="e5eKH99aat-bvalqy8uv-2" target="e5eKH99aat-bvalqy8uv-16" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
@ -19,12 +13,6 @@
<mxCell id="e5eKH99aat-bvalqy8uv-39" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#000000;fillColor=#FFFFFF;" parent="1" source="e5eKH99aat-bvalqy8uv-2" target="e5eKH99aat-bvalqy8uv-28" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="e5eKH99aat-bvalqy8uv-2" target="tu1BIFyJs8wWzZwwhIyV-1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="e5eKH99aat-bvalqy8uv-2" target="tu1BIFyJs8wWzZwwhIyV-4">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e5eKH99aat-bvalqy8uv-2" value="Header" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#000000;fontColor=default;fillColor=#FFFFFF;" parent="1" vertex="1">
<mxGeometry x="330" y="110" width="120" height="60" as="geometry" />
</mxCell>
@ -66,7 +54,7 @@
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="Q4E33S6IXDZPZFDXlPAv-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="e5eKH99aat-bvalqy8uv-8" target="Q4E33S6IXDZPZFDXlPAv-1" edge="1">
<mxCell id="Q4E33S6IXDZPZFDXlPAv-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="e5eKH99aat-bvalqy8uv-8" target="Q4E33S6IXDZPZFDXlPAv-1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e5eKH99aat-bvalqy8uv-8" value="Contact" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#000000;fontColor=default;fillColor=#FFFFFF;" parent="1" vertex="1">
@ -131,7 +119,8 @@
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="520" y="640" />
<mxPoint x="520" y="1000" />
<mxPoint x="520" y="990" />
<mxPoint x="450" y="990" />
</Array>
</mxGeometry>
</mxCell>
@ -169,7 +158,7 @@
<mxPoint x="-13" y="-113" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="e5eKH99aat-bvalqy8uv-35" value="Discord Webhook Form" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#000000;fontColor=default;fillColor=#FFFFFF;" parent="1" vertex="1">
<mxCell id="e5eKH99aat-bvalqy8uv-35" value="Email Form" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#000000;fontColor=default;fillColor=#FFFFFF;" parent="1" vertex="1">
<mxGeometry x="640" y="720" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="e5eKH99aat-bvalqy8uv-54" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeColor=#000000;fillColor=#FFFFFF;" parent="1" source="e5eKH99aat-bvalqy8uv-46" target="e5eKH99aat-bvalqy8uv-48" edge="1">
@ -181,7 +170,8 @@
<mxCell id="e5eKH99aat-bvalqy8uv-55" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;strokeColor=#000000;fillColor=#FFFFFF;" parent="1" source="e5eKH99aat-bvalqy8uv-48" target="e5eKH99aat-bvalqy8uv-9" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="850" y="1000" />
<mxPoint x="850" y="990" />
<mxPoint x="450" y="990" />
</Array>
</mxGeometry>
</mxCell>
@ -200,172 +190,27 @@
<mxCell id="e5eKH99aat-bvalqy8uv-50" value="Name" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#000000;fontColor=default;fillColor=#FFFFFF;" parent="1" vertex="1">
<mxGeometry x="790" y="640" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="Q4E33S6IXDZPZFDXlPAv-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="Q4E33S6IXDZPZFDXlPAv-1" target="Q4E33S6IXDZPZFDXlPAv-2" edge="1">
<mxCell id="Q4E33S6IXDZPZFDXlPAv-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="Q4E33S6IXDZPZFDXlPAv-1" target="Q4E33S6IXDZPZFDXlPAv-2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Q4E33S6IXDZPZFDXlPAv-1" value="Experience" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxCell id="Q4E33S6IXDZPZFDXlPAv-1" value="Experience" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="330" y="790" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="Q4E33S6IXDZPZFDXlPAv-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="Q4E33S6IXDZPZFDXlPAv-2" target="e5eKH99aat-bvalqy8uv-9" edge="1">
<mxCell id="Q4E33S6IXDZPZFDXlPAv-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="Q4E33S6IXDZPZFDXlPAv-2" target="e5eKH99aat-bvalqy8uv-9">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Q4E33S6IXDZPZFDXlPAv-2" value="Education" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxCell id="Q4E33S6IXDZPZFDXlPAv-2" value="Education" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="330" y="880" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-1" target="tu1BIFyJs8wWzZwwhIyV-10">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-1" value="Blogs" style="rounded=1;whiteSpace=wrap;html=1;glass=0;shadow=0;" vertex="1" parent="1">
<mxGeometry x="970" y="230" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-4" target="tu1BIFyJs8wWzZwwhIyV-6">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-4" value="Blog" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="1230" y="230" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-6" target="tu1BIFyJs8wWzZwwhIyV-1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-11" value="almost&amp;nbsp;&lt;div&gt;no point&lt;/div&gt;" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="tu1BIFyJs8wWzZwwhIyV-9">
<mxGeometry x="0.0048" y="-1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-66" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-6" target="tu1BIFyJs8wWzZwwhIyV-39">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-6" value="Go back&lt;div&gt;to page 0&lt;/div&gt;" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="1230" y="320" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-10" target="tu1BIFyJs8wWzZwwhIyV-20">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-23" value="10 per page (default?)" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="tu1BIFyJs8wWzZwwhIyV-22">
<mxGeometry x="-0.0848" y="3" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-10" value="Blogs" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="970" y="320" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-56" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-16" target="tu1BIFyJs8wWzZwwhIyV-54">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-16" value="Blog Title" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="970" y="430" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-50" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-17" target="tu1BIFyJs8wWzZwwhIyV-45">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-17" value="First paragraph" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="970" y="570" width="120" height="65" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-36" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-24" target="tu1BIFyJs8wWzZwwhIyV-32">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-24" value="&amp;lt;-- Back" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="970" y="720" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-27" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-26" target="tu1BIFyJs8wWzZwwhIyV-20">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="920" y="535" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-26" value="hidden property,&lt;div&gt;name of file&lt;/div&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="870" y="455" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-28" target="e5eKH99aat-bvalqy8uv-9">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1030" y="1000" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-28" value="Next --&amp;gt;" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="970" y="880" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-30" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-29" target="tu1BIFyJs8wWzZwwhIyV-24">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-29" value="Hide when on id 0" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="1150" y="735" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-37" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-32" target="tu1BIFyJs8wWzZwwhIyV-28">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-32" value="Drop down with how many per page?" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="970" y="800" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-34" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-33" target="tu1BIFyJs8wWzZwwhIyV-32">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-33" value="Options&lt;div&gt;10&lt;div&gt;25&lt;/div&gt;&lt;div&gt;50&lt;/div&gt;&lt;div&gt;100&lt;/div&gt;&lt;/div&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="1150" y="815" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-67" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-39" target="tu1BIFyJs8wWzZwwhIyV-41">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-39" value="Title" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="1230" y="400" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-70" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-40" target="tu1BIFyJs8wWzZwwhIyV-42">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-40" value="Date" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="1230" y="560" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-68" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-41" target="tu1BIFyJs8wWzZwwhIyV-40">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-41" value="Tags" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="1230" y="480" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-65" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-42" target="e5eKH99aat-bvalqy8uv-9">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="1290" y="1000" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-42" value="Main Content" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="1230" y="655" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-58" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-43" target="tu1BIFyJs8wWzZwwhIyV-17">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-43" value="Date" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="970" y="527.5" width="120" height="25" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-45" value="Read More --&amp;gt;" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="970" y="655" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-53" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-51" target="tu1BIFyJs8wWzZwwhIyV-40">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-69" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-51" target="tu1BIFyJs8wWzZwwhIyV-43">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-51" value="If Possible" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="1130" y="575" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-57" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="tu1BIFyJs8wWzZwwhIyV-54" target="tu1BIFyJs8wWzZwwhIyV-43">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="tu1BIFyJs8wWzZwwhIyV-54" value="Tags" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="970" y="480" width="120" height="30" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram name="Wireframes" id="FFrjymaV3XqdK7QtWSJo">
<mxGraphModel dx="3163" dy="565" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<mxGraphModel dx="2021" dy="812" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="cChhu68VZKLTFEiYYllV-33" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-33" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="110" y="2630" width="690" height="400" as="geometry" />
</mxCell>
<mxCell id="UZYojl2K0HOaq53XvgF2-174" value="" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=default;fontColor=#000000;fillColor=#FFFFFF;" parent="1" vertex="1">
@ -913,435 +758,111 @@
<mxCell id="UZYojl2K0HOaq53XvgF2-234" value="Brock Tomlinson Copyright 2025-this year" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=default;" parent="1" vertex="1">
<mxGeometry x="110" y="1920" width="690" height="30" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-2" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-2" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="110" y="2070" width="720" height="500" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-1" value="&lt;h1 style=&quot;margin-top: 0px;&quot;&gt;&lt;font&gt;&lt;span style=&quot;&quot;&gt;Experience&lt;/span&gt;&lt;/font&gt;&lt;/h1&gt;" style="text;html=1;whiteSpace=wrap;overflow=hidden;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;labelBackgroundColor=default;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-1" value="&lt;h1 style=&quot;margin-top: 0px;&quot;&gt;&lt;font&gt;&lt;span style=&quot;&quot;&gt;Experience&lt;/span&gt;&lt;/font&gt;&lt;/h1&gt;" style="text;html=1;whiteSpace=wrap;overflow=hidden;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;labelBackgroundColor=default;" vertex="1" parent="1">
<mxGeometry x="120" y="2090" width="190" height="40" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-3" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-3" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="187.5" y="2230" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-5" value="&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;font&gt;&lt;span&gt;Professional&lt;/span&gt;&lt;/font&gt;&lt;/h2&gt;" style="text;html=1;whiteSpace=wrap;overflow=hidden;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;labelBackgroundColor=default;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-5" value="&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;font&gt;&lt;span&gt;Professional&lt;/span&gt;&lt;/font&gt;&lt;/h2&gt;" style="text;html=1;whiteSpace=wrap;overflow=hidden;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;labelBackgroundColor=default;" vertex="1" parent="1">
<mxGeometry x="187.5" y="2160" width="190" height="40" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-6" value="&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;font&gt;&lt;span style=&quot;&quot;&gt;Volunteering&lt;/span&gt;&lt;/font&gt;&lt;/h2&gt;" style="text;html=1;whiteSpace=wrap;overflow=hidden;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;labelBackgroundColor=default;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-6" value="&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;font&gt;&lt;span style=&quot;&quot;&gt;Volunteering&lt;/span&gt;&lt;/font&gt;&lt;/h2&gt;" style="text;html=1;whiteSpace=wrap;overflow=hidden;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;labelBackgroundColor=default;" vertex="1" parent="1">
<mxGeometry x="487.5" y="2160" width="190" height="40" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-10" value="Project Coordinator" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-10" value="Project Coordinator" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="235.5" y="2225" width="112" height="30" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-11" value="Project Controller" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-11" value="Project Controller" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="235.5" y="2290" width="97" height="30" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-12" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-12" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="187.5" y="2295" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-13" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-13" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="502.5" y="2295" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-14" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-14" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="502.5" y="2230" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-15" value="Software Lead" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-15" value="Software Lead" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="537.5" y="2225" width="142.5" height="30" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-18" value="&lt;div&gt;Month 2024 - Month2025&lt;/div&gt;Rally Engineering, AB" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-18" value="&lt;div&gt;Month 2024 - Month2025&lt;/div&gt;Rally Engineering, AB" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="350" y="2225" width="142.5" height="30" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-20" value="&lt;div&gt;Month 2024 - Month2025&lt;/div&gt;UCalgary Baja, AB" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-20" value="&lt;div&gt;Month 2024 - Month2025&lt;/div&gt;UCalgary Baja, AB" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="677.5" y="2225" width="142.5" height="30" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-21" value="Software &amp;amp; Logistics Lead" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-21" value="Software &amp;amp; Logistics Lead" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="537.5" y="2290" width="142.5" height="30" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-22" value="&lt;div&gt;Month 2024 - Month2025&lt;/div&gt;Schulich Off-Road, AB" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-22" value="&lt;div&gt;Month 2024 - Month2025&lt;/div&gt;Schulich Off-Road, AB" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="680" y="2290" width="142.5" height="30" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-23" value="" style="endArrow=none;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" parent="1" source="cChhu68VZKLTFEiYYllV-12" target="cChhu68VZKLTFEiYYllV-3" edge="1">
<mxCell id="cChhu68VZKLTFEiYYllV-23" value="" style="endArrow=none;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="cChhu68VZKLTFEiYYllV-12" target="cChhu68VZKLTFEiYYllV-3">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="160" y="2390" as="sourcePoint" />
<mxPoint x="210" y="2340" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-24" value="" style="endArrow=none;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" parent="1" source="cChhu68VZKLTFEiYYllV-13" target="cChhu68VZKLTFEiYYllV-14" edge="1">
<mxCell id="cChhu68VZKLTFEiYYllV-24" value="" style="endArrow=none;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="cChhu68VZKLTFEiYYllV-13" target="cChhu68VZKLTFEiYYllV-14">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="208" y="2305" as="sourcePoint" />
<mxPoint x="208" y="2260" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-25" value="&lt;div&gt;Month 2024 - Month2025&lt;/div&gt;Rally Engineering, AB" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-25" value="&lt;div&gt;Month 2024 - Month2025&lt;/div&gt;Rally Engineering, AB" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="350" y="2290" width="142.5" height="30" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-26" value="Chassis Junior" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-26" value="Chassis Junior" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="537.5" y="2360" width="142.5" height="30" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-27" value="Labourer" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-27" value="Labourer" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="235.5" y="2360" width="97" height="30" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-28" value="&lt;div&gt;Month 2024 - Month2025&lt;/div&gt;Ghostrider Storage, BC" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-28" value="&lt;div&gt;Month 2024 - Month2025&lt;/div&gt;Ghostrider Storage, BC" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="347.5" y="2360" width="142.5" height="30" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-29" value="Staff" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-29" value="Staff" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="235.5" y="2420" width="97" height="30" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-30" value="&lt;div&gt;Month 2024 - Month2025&lt;/div&gt;Red Deer Farmers Market, AB" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-30" value="&lt;div&gt;Month 2024 - Month2025&lt;/div&gt;Red Deer Farmers Market, AB" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="347.5" y="2420" width="142.5" height="30" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-31" value="Volunteer Coach, Fundraising" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-31" value="Volunteer Coach, Fundraising" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="537.5" y="2430" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-32" value="&lt;h1 style=&quot;margin-top: 0px;&quot;&gt;&lt;font&gt;&lt;span style=&quot;&quot;&gt;Education&lt;/span&gt;&lt;/font&gt;&lt;/h1&gt;" style="text;html=1;whiteSpace=wrap;overflow=hidden;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;labelBackgroundColor=default;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-32" value="&lt;h1 style=&quot;margin-top: 0px;&quot;&gt;&lt;font&gt;&lt;span style=&quot;&quot;&gt;Education&lt;/span&gt;&lt;/font&gt;&lt;/h1&gt;" style="text;html=1;whiteSpace=wrap;overflow=hidden;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;labelBackgroundColor=default;" vertex="1" parent="1">
<mxGeometry x="115" y="2640" width="190" height="40" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-35" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-35" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="302.5" y="2755" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-36" value="University of Calgary&lt;div&gt;Software Engineering&lt;/div&gt;" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-36" value="University of Calgary&lt;div&gt;Software Engineering&lt;/div&gt;" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="350.5" y="2750" width="112" height="30" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-37" value="The Fernie Academy" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-37" value="The Fernie Academy" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="350.5" y="2815" width="97" height="30" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-38" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-38" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="302.5" y="2820" width="20" height="20" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-39" value="&lt;div&gt;Month 2024 - Month2025&lt;/div&gt;Rally Engineering, AB" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-39" value="&lt;div&gt;Month 2024 - Month2025&lt;/div&gt;Rally Engineering, AB" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="465" y="2750" width="142.5" height="30" as="geometry" />
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-40" value="" style="endArrow=none;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" parent="1" source="cChhu68VZKLTFEiYYllV-38" target="cChhu68VZKLTFEiYYllV-35" edge="1">
<mxCell id="cChhu68VZKLTFEiYYllV-40" value="" style="endArrow=none;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="cChhu68VZKLTFEiYYllV-38" target="cChhu68VZKLTFEiYYllV-35">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="275" y="2915" as="sourcePoint" />
<mxPoint x="325" y="2865" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="cChhu68VZKLTFEiYYllV-41" value="&lt;div&gt;Month 2024 - Month2025&lt;/div&gt;Rally Engineering, AB" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxCell id="cChhu68VZKLTFEiYYllV-41" value="&lt;div&gt;Month 2024 - Month2025&lt;/div&gt;Rally Engineering, AB" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="465" y="2815" width="142.5" height="30" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-1" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="-830" y="350" width="470" height="1070" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-2" value="&lt;h1 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;background-color: rgb(255, 255, 255);&quot;&gt;Blogs&lt;/span&gt;&lt;/h1&gt;" style="text;html=1;whiteSpace=wrap;overflow=hidden;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;" vertex="1" parent="1">
<mxGeometry x="-820" y="360" width="180" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-3" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="-820" y="430" width="200" height="150" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-4" value="" style="group;fillColor=#FFFFFF;strokeColor=none;fontColor=#000000;" vertex="1" connectable="0" parent="1">
<mxGeometry x="-815" y="440" width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-5" value="&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font style=&quot;font-size: 16px;&quot;&gt;Blog Title&lt;/font&gt;&lt;/span&gt;&lt;/h2&gt;&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;font-size: x-small; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); color: light-dark(rgb(0, 0, 0), rgb(237, 237, 237)); font-weight: normal;&quot;&gt;#tag #tag #tag&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;Date&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font size=&quot;1&quot; style=&quot;&quot;&gt;&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;" vertex="1" parent="Eo5ilUiPJB2txGRp4zdG-4">
<mxGeometry width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-6" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#9673a6;entryX=0;entryY=0.75;entryDx=0;entryDy=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;strokeWidth=4;fillColor=#e1d5e7;fontColor=#000000;" edge="1" parent="Eo5ilUiPJB2txGRp4zdG-4" source="Eo5ilUiPJB2txGRp4zdG-5" target="Eo5ilUiPJB2txGRp4zdG-5">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-70" y="-140" as="sourcePoint" />
<mxPoint x="-60" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.25;entryDx=0;entryDy=0;" edge="1" parent="1" source="Eo5ilUiPJB2txGRp4zdG-8" target="Eo5ilUiPJB2txGRp4zdG-5">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="-843" y="458" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-8" value="1-2svh padding" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-930" y="440" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-10" value="First Para" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-815" y="510" width="185" height="50" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-11" value="Read More --&amp;gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-815" y="550" width="85" height="30" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.25;entryDx=0;entryDy=0;" edge="1" parent="1" source="Eo5ilUiPJB2txGRp4zdG-12" target="Eo5ilUiPJB2txGRp4zdG-5">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Eo5ilUiPJB2txGRp4zdG-12" target="Eo5ilUiPJB2txGRp4zdG-11">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="-860" y="495" />
<mxPoint x="-860" y="565" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-12" value="Link to blog" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-930" y="480" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-15" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="-580" y="430" width="200" height="150" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-16" value="" style="group;fillColor=#FFFFFF;strokeColor=none;fontColor=#000000;" vertex="1" connectable="0" parent="1">
<mxGeometry x="-575" y="440" width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-17" value="&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font style=&quot;font-size: 16px;&quot;&gt;Blog Title&lt;/font&gt;&lt;/span&gt;&lt;/h2&gt;&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;font-size: x-small; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); color: light-dark(rgb(0, 0, 0), rgb(237, 237, 237)); font-weight: normal;&quot;&gt;#tag #tag #tag&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;Date&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font size=&quot;1&quot; style=&quot;&quot;&gt;&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;" vertex="1" parent="Eo5ilUiPJB2txGRp4zdG-16">
<mxGeometry width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-18" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#9673a6;entryX=0;entryY=0.75;entryDx=0;entryDy=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;strokeWidth=4;fillColor=#e1d5e7;fontColor=#000000;" edge="1" parent="Eo5ilUiPJB2txGRp4zdG-16" source="Eo5ilUiPJB2txGRp4zdG-17" target="Eo5ilUiPJB2txGRp4zdG-17">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-70" y="-140" as="sourcePoint" />
<mxPoint x="-60" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-19" value="First Para" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-575" y="510" width="185" height="50" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-20" value="Read More --&amp;gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-575" y="550" width="85" height="30" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-21" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="-820" y="600" width="200" height="150" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-22" value="" style="group;fillColor=#FFFFFF;strokeColor=none;fontColor=#000000;" vertex="1" connectable="0" parent="1">
<mxGeometry x="-815" y="610" width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-23" value="&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font style=&quot;font-size: 16px;&quot;&gt;Blog Title&lt;/font&gt;&lt;/span&gt;&lt;/h2&gt;&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;font-size: x-small; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); color: light-dark(rgb(0, 0, 0), rgb(237, 237, 237)); font-weight: normal;&quot;&gt;#tag #tag #tag&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;Date&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font size=&quot;1&quot; style=&quot;&quot;&gt;&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;" vertex="1" parent="Eo5ilUiPJB2txGRp4zdG-22">
<mxGeometry width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-24" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#9673a6;entryX=0;entryY=0.75;entryDx=0;entryDy=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;strokeWidth=4;fillColor=#e1d5e7;fontColor=#000000;" edge="1" parent="Eo5ilUiPJB2txGRp4zdG-22" source="Eo5ilUiPJB2txGRp4zdG-23" target="Eo5ilUiPJB2txGRp4zdG-23">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-70" y="-140" as="sourcePoint" />
<mxPoint x="-60" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-25" value="First Para" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-815" y="680" width="185" height="50" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-26" value="Read More --&amp;gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-815" y="720" width="85" height="30" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-27" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="-580" y="600" width="200" height="150" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-28" value="" style="group;fillColor=#FFFFFF;strokeColor=none;fontColor=#000000;" vertex="1" connectable="0" parent="1">
<mxGeometry x="-575" y="610" width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-29" value="&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font style=&quot;font-size: 16px;&quot;&gt;Blog Title&lt;/font&gt;&lt;/span&gt;&lt;/h2&gt;&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;font-size: x-small; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); color: light-dark(rgb(0, 0, 0), rgb(237, 237, 237)); font-weight: normal;&quot;&gt;#tag #tag #tag&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;Date&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font size=&quot;1&quot; style=&quot;&quot;&gt;&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;" vertex="1" parent="Eo5ilUiPJB2txGRp4zdG-28">
<mxGeometry width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-30" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#9673a6;entryX=0;entryY=0.75;entryDx=0;entryDy=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;strokeWidth=4;fillColor=#e1d5e7;fontColor=#000000;" edge="1" parent="Eo5ilUiPJB2txGRp4zdG-28" source="Eo5ilUiPJB2txGRp4zdG-29" target="Eo5ilUiPJB2txGRp4zdG-29">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-70" y="-140" as="sourcePoint" />
<mxPoint x="-60" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-31" value="First Para" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-575" y="680" width="185" height="50" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-32" value="Read More --&amp;gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-575" y="720" width="85" height="30" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-33" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="-820" y="760" width="200" height="150" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-34" value="" style="group;fillColor=#FFFFFF;strokeColor=none;fontColor=#000000;" vertex="1" connectable="0" parent="1">
<mxGeometry x="-815" y="770" width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-35" value="&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font style=&quot;font-size: 16px;&quot;&gt;Blog Title&lt;/font&gt;&lt;/span&gt;&lt;/h2&gt;&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;font-size: x-small; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); color: light-dark(rgb(0, 0, 0), rgb(237, 237, 237)); font-weight: normal;&quot;&gt;#tag #tag #tag&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;Date&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font size=&quot;1&quot; style=&quot;&quot;&gt;&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;" vertex="1" parent="Eo5ilUiPJB2txGRp4zdG-34">
<mxGeometry width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-36" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#9673a6;entryX=0;entryY=0.75;entryDx=0;entryDy=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;strokeWidth=4;fillColor=#e1d5e7;fontColor=#000000;" edge="1" parent="Eo5ilUiPJB2txGRp4zdG-34" source="Eo5ilUiPJB2txGRp4zdG-35" target="Eo5ilUiPJB2txGRp4zdG-35">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-70" y="-140" as="sourcePoint" />
<mxPoint x="-60" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-37" value="First Para" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-815" y="840" width="185" height="50" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-38" value="Read More --&amp;gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-815" y="880" width="85" height="30" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-39" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="-580" y="760" width="200" height="150" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-40" value="" style="group;fillColor=#FFFFFF;strokeColor=none;fontColor=#000000;" vertex="1" connectable="0" parent="1">
<mxGeometry x="-575" y="770" width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-41" value="&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font style=&quot;font-size: 16px;&quot;&gt;Blog Title&lt;/font&gt;&lt;/span&gt;&lt;/h2&gt;&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;font-size: x-small; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); color: light-dark(rgb(0, 0, 0), rgb(237, 237, 237)); font-weight: normal;&quot;&gt;#tag #tag #tag&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;Date&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font size=&quot;1&quot; style=&quot;&quot;&gt;&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;" vertex="1" parent="Eo5ilUiPJB2txGRp4zdG-40">
<mxGeometry width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-42" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#9673a6;entryX=0;entryY=0.75;entryDx=0;entryDy=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;strokeWidth=4;fillColor=#e1d5e7;fontColor=#000000;" edge="1" parent="Eo5ilUiPJB2txGRp4zdG-40" source="Eo5ilUiPJB2txGRp4zdG-41" target="Eo5ilUiPJB2txGRp4zdG-41">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-70" y="-140" as="sourcePoint" />
<mxPoint x="-60" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-43" value="First Para" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-575" y="840" width="185" height="50" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-44" value="Read More --&amp;gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-575" y="880" width="85" height="30" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-45" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="-820" y="930" width="200" height="150" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-46" value="" style="group;fillColor=#FFFFFF;strokeColor=none;fontColor=#000000;" vertex="1" connectable="0" parent="1">
<mxGeometry x="-815" y="940" width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-47" value="&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font style=&quot;font-size: 16px;&quot;&gt;Blog Title&lt;/font&gt;&lt;/span&gt;&lt;/h2&gt;&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;font-size: x-small; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); color: light-dark(rgb(0, 0, 0), rgb(237, 237, 237)); font-weight: normal;&quot;&gt;#tag #tag #tag&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;Date&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font size=&quot;1&quot; style=&quot;&quot;&gt;&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;" vertex="1" parent="Eo5ilUiPJB2txGRp4zdG-46">
<mxGeometry width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-48" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#9673a6;entryX=0;entryY=0.75;entryDx=0;entryDy=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;strokeWidth=4;fillColor=#e1d5e7;fontColor=#000000;" edge="1" parent="Eo5ilUiPJB2txGRp4zdG-46" source="Eo5ilUiPJB2txGRp4zdG-47" target="Eo5ilUiPJB2txGRp4zdG-47">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-70" y="-140" as="sourcePoint" />
<mxPoint x="-60" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-49" value="First Para" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-815" y="1010" width="185" height="50" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-50" value="Read More --&amp;gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-815" y="1050" width="85" height="30" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-51" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="-580" y="930" width="200" height="150" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-52" value="" style="group;fillColor=#FFFFFF;strokeColor=none;fontColor=#000000;" vertex="1" connectable="0" parent="1">
<mxGeometry x="-575" y="940" width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-53" value="&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font style=&quot;font-size: 16px;&quot;&gt;Blog Title&lt;/font&gt;&lt;/span&gt;&lt;/h2&gt;&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;font-size: x-small; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); color: light-dark(rgb(0, 0, 0), rgb(237, 237, 237)); font-weight: normal;&quot;&gt;#tag #tag #tag&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;Date&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font size=&quot;1&quot; style=&quot;&quot;&gt;&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;" vertex="1" parent="Eo5ilUiPJB2txGRp4zdG-52">
<mxGeometry width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-54" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#9673a6;entryX=0;entryY=0.75;entryDx=0;entryDy=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;strokeWidth=4;fillColor=#e1d5e7;fontColor=#000000;" edge="1" parent="Eo5ilUiPJB2txGRp4zdG-52" source="Eo5ilUiPJB2txGRp4zdG-53" target="Eo5ilUiPJB2txGRp4zdG-53">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-70" y="-140" as="sourcePoint" />
<mxPoint x="-60" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-55" value="First Para" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-575" y="1010" width="185" height="50" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-56" value="Read More --&amp;gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-575" y="1050" width="85" height="30" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-57" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="-820" y="1100" width="200" height="150" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-58" value="" style="group;fillColor=#FFFFFF;strokeColor=none;fontColor=#000000;" vertex="1" connectable="0" parent="1">
<mxGeometry x="-815" y="1110" width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-59" value="&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font style=&quot;font-size: 16px;&quot;&gt;Blog Title&lt;/font&gt;&lt;/span&gt;&lt;/h2&gt;&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;font-size: x-small; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); color: light-dark(rgb(0, 0, 0), rgb(237, 237, 237)); font-weight: normal;&quot;&gt;#tag #tag #tag&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;Date&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font size=&quot;1&quot; style=&quot;&quot;&gt;&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;" vertex="1" parent="Eo5ilUiPJB2txGRp4zdG-58">
<mxGeometry width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-60" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#9673a6;entryX=0;entryY=0.75;entryDx=0;entryDy=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;strokeWidth=4;fillColor=#e1d5e7;fontColor=#000000;" edge="1" parent="Eo5ilUiPJB2txGRp4zdG-58" source="Eo5ilUiPJB2txGRp4zdG-59" target="Eo5ilUiPJB2txGRp4zdG-59">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-70" y="-140" as="sourcePoint" />
<mxPoint x="-60" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-61" value="First Para" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-815" y="1180" width="185" height="50" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-62" value="Read More --&amp;gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-815" y="1220" width="85" height="30" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-63" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="-580" y="1100" width="200" height="150" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-64" value="" style="group;fillColor=#FFFFFF;strokeColor=none;fontColor=#000000;" vertex="1" connectable="0" parent="1">
<mxGeometry x="-575" y="1110" width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-65" value="&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font style=&quot;font-size: 16px;&quot;&gt;Blog Title&lt;/font&gt;&lt;/span&gt;&lt;/h2&gt;&lt;h2 style=&quot;margin-top: 0px;&quot;&gt;&lt;span style=&quot;font-size: x-small; background-color: light-dark(#ffffff, var(--ge-dark-color, #121212)); color: light-dark(rgb(0, 0, 0), rgb(237, 237, 237)); font-weight: normal;&quot;&gt;#tag #tag #tag&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&#x9;&lt;/span&gt;Date&lt;/span&gt;&lt;/h2&gt;&lt;div&gt;&lt;span style=&quot;background-color: light-dark(#ffffff, var(--ge-dark-color, #121212));&quot;&gt;&lt;font size=&quot;1&quot; style=&quot;&quot;&gt;&lt;br&gt;&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;" style="text;html=1;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#000000;fillColor=#FFFFFF;strokeColor=none;" vertex="1" parent="Eo5ilUiPJB2txGRp4zdG-64">
<mxGeometry width="185" height="70" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-66" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#9673a6;entryX=0;entryY=0.75;entryDx=0;entryDy=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;strokeWidth=4;fillColor=#e1d5e7;fontColor=#000000;" edge="1" parent="Eo5ilUiPJB2txGRp4zdG-64" source="Eo5ilUiPJB2txGRp4zdG-65" target="Eo5ilUiPJB2txGRp4zdG-65">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-70" y="-140" as="sourcePoint" />
<mxPoint x="-60" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-67" value="First Para" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-575" y="1180" width="185" height="50" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-68" value="Read More --&amp;gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-575" y="1220" width="85" height="30" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-70" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="-830" y="1320" width="470" height="60" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-69" value="&amp;lt;-- Back" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-790" y="1335" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-72" value="Next --&amp;gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-490" y="1335" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-75" value="How Many Per Page" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="-680" y="1330" width="75" height="40" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-76" value="Dropdown" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="-605" y="1330" width="75" height="40" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-78" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="Eo5ilUiPJB2txGRp4zdG-77" target="Eo5ilUiPJB2txGRp4zdG-76">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-77" value="10&lt;div&gt;25&lt;/div&gt;&lt;div&gt;50&lt;/div&gt;&lt;div&gt;100&lt;/div&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-340" y="1380" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-81" value="" style="endArrow=none;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;strokeWidth=4;fillColor=#f5f5f5;strokeColor=#666666;" edge="1" parent="1" source="Eo5ilUiPJB2txGRp4zdG-3" target="Eo5ilUiPJB2txGRp4zdG-3">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-930" y="660" as="sourcePoint" />
<mxPoint x="-880" y="610" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-82" value="" style="endArrow=none;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;strokeWidth=4;fillColor=#f5f5f5;strokeColor=#666666;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-820" y="750" as="sourcePoint" />
<mxPoint x="-620" y="750" as="targetPoint" />
<Array as="points">
<mxPoint x="-730" y="750" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-83" value="" style="endArrow=none;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;strokeWidth=4;fillColor=#f5f5f5;strokeColor=#666666;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-580" y="580" as="sourcePoint" />
<mxPoint x="-380" y="580" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-84" value="" style="endArrow=none;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;strokeWidth=4;fillColor=#f5f5f5;strokeColor=#666666;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-580" y="750" as="sourcePoint" />
<mxPoint x="-380" y="750" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-85" value="" style="endArrow=none;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;strokeWidth=4;fillColor=#f5f5f5;strokeColor=#666666;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-820" y="910" as="sourcePoint" />
<mxPoint x="-620" y="910" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-86" value="" style="endArrow=none;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;strokeWidth=4;fillColor=#f5f5f5;strokeColor=#666666;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-580" y="910" as="sourcePoint" />
<mxPoint x="-380" y="910" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-87" value="" style="endArrow=none;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;strokeWidth=4;fillColor=#f5f5f5;strokeColor=#666666;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-820" y="1080" as="sourcePoint" />
<mxPoint x="-620" y="1080" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-88" value="" style="endArrow=none;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;strokeWidth=4;fillColor=#f5f5f5;strokeColor=#666666;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-580" y="1080" as="sourcePoint" />
<mxPoint x="-380" y="1080" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-89" value="" style="endArrow=none;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;strokeWidth=4;fillColor=#f5f5f5;strokeColor=#666666;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-820" y="1250" as="sourcePoint" />
<mxPoint x="-620" y="1250" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Eo5ilUiPJB2txGRp4zdG-90" value="" style="endArrow=none;html=1;rounded=0;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;strokeWidth=4;fillColor=#f5f5f5;strokeColor=#666666;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-580" y="1250" as="sourcePoint" />
<mxPoint x="-380" y="1250" as="targetPoint" />
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>

View File

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 130 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@ -0,0 +1,36 @@
#blog {
margin-top: 50px;
}
#blog a {
color: #ffffff;
margin-top: 50px;
}
#blogs {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 80svh;
}
#blogs h1 {
border-bottom: var(--underlineTitle);
border-radius: var(--underlineTitleBorderRadius);
}
#blogs button {
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
border: none;
color: #ffffff;
font-size: xx-large;
padding: 1rem;
}
#blogs a {
text-decoration: none;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
}

View File

@ -88,13 +88,6 @@
filter: invert() hue-rotate(180deg);
}
#contact 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) {
#contact ul li img {
display: none;

View File

@ -15,17 +15,24 @@
border-radius: var(--card-border-radius);
flex-direction: column;
justify-content: center;
margin: 2svh 0.5svw;
padding: 2svh 1svw;
max-width: 600px;
}
#ContactMe p {
margin: 2svh 0svw;
padding: 0svh 0svw;
margin: 2svh 2svw;
padding: 0svh 2svw;
}
/* #contact-me input {
#contact-me {
display: flex;
justify-content: center;
flex-direction: column;
background-color: transparent;
border-radius: 0px;
margin: 2svh 0.5svw;
padding: 0svh 1svw;
}
#contact-me input {
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
border-color: rgba(245, 245, 245, 0.5);
@ -46,9 +53,9 @@
color: inherit;
align-items: start;
min-height: 25svh;
} */
}
/* #contact-me button {
#contact-me button {
border-radius: var(--card-border-radius);
border-color: rgba(245, 245, 245, 0.5);
padding: 1svh 0svw;
@ -57,7 +64,17 @@
align-items: start;
background-color: rgba(0, 128, 0, 0.6);
border-color: transparent;
} */
}
#ContactMe form {
display: flex;
justify-content: center;
flex-direction: column;
background-color: transparent;
border-radius: 0px;
margin: 2svh 0.5svw;
padding: 0svh 1svw;
}
#ContactMe input {
background-color: var(--card-background-color);
@ -92,9 +109,3 @@
background-color: rgba(0, 128, 0, 0.6);
border-color: transparent;
}
#ContactMe button:hover {
cursor: pointer;
color: #91a4d2;
background-color: rgba(0, 150, 0, 0.6);
}

View File

@ -28,10 +28,3 @@ footer a {
text-decoration: none;
color: inherit;
}
footer a:hover {
color: #91a4d2;
cursor: pointer;
filter: brightness(0) saturate(100%) invert(65%) sepia(13%) saturate(733%)
hue-rotate(187deg) brightness(95%) contrast(90%);
}

View File

@ -2,8 +2,6 @@
display: flex;
flex-direction: column;
flex-wrap: wrap;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
/* flex-basis: 50%; */
}

View File

@ -2,7 +2,7 @@
display: flex;
flex-direction: column;
width: 90%;
margin: 2svh auto;
margin-top: 2svh;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
}
@ -22,30 +22,6 @@
padding-bottom: 1svh;
}
#home-intro 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;
}
#home-intro button {
cursor: pointer;
}
#home-intro a {
text-decoration: none;
color: inherit;
}
#home-intro a:hover {
color: #91a4d2;
}
.technologies {
display: flex;
flex-direction: column;
@ -63,11 +39,15 @@
display: flex;
flex-direction: column;
margin-bottom: 4svh;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
}
#experience div {
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
margin: 4svh 0px;
}

View File

@ -15,22 +15,13 @@
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
border: none;
color: inherit;
color: #ffffff;
font-size: xx-large;
padding: 1rem;
}
#not-found button:hover {
cursor: pointer;
}
#not-found a {
text-decoration: none;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
color: inherit;
}
#not-found a:hover {
color: #91a4d2;
}

View File

@ -63,29 +63,6 @@
filter: invert() hue-rotate(180deg);
}
.project-title-info #gitea img {
filter: grayscale(100%) invert(100%) brightness(2.5);
}
.project-title-info #dockerhub img {
filter: grayscale(100%) invert(100%) brightness(2.5);
}
.project-title-info img:hover {
filter: brightness(0) saturate(100%) invert(65%) sepia(13%) saturate(733%)
hue-rotate(187deg) brightness(95%) contrast(90%);
}
.project-title-info #gitea img:hover {
filter: grayscale(100%) invert(165%) sepia(15%) saturate(733%)
hue-rotate(185deg) brightness(1.3) contrast(90%) saturate(100%);
}
.project-title-info #dockerhub img: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;

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -1,4 +1,6 @@
use dioxus::{document, prelude::*};
use dioxus::prelude::*;
const EXPERIENCE_CSS: Asset = asset!("/assets/styling/experience.css");
#[component]
pub fn Experience(professional_jobs: bool) -> Element {
@ -8,7 +10,7 @@ pub fn Experience(professional_jobs: bool) -> Element {
};
rsx! {
div { class: "experience-comp",
document::Stylesheet { href: asset!("/assets/styling/experience.css") }
document::Link { rel: "stylesheet", href: EXPERIENCE_CSS }
if professional_jobs {
h3 { "Professional" }
} else {
@ -30,6 +32,7 @@ pub fn Experience(professional_jobs: bool) -> Element {
td { "{exp.start_month} - {exp.end_month}" }
}
tr {
// td { "" }
td { "{exp.company}" }
td { "{exp.location}" }
}

View File

@ -3,6 +3,8 @@ use std::collections::HashMap;
use crate::helper_fun::{tech_table_lookup, TechDes};
use dioxus::prelude::*;
const ENDER_CSS: Asset = asset!("/assets/styling/ender.css");
#[component]
pub fn Ender() -> Element {
// gets list of items to get
@ -14,7 +16,7 @@ pub fn Ender() -> Element {
footer_info.insert(used_tech_item, *tech_table_lookup(used_tech_item));
}
rsx! {
document::Stylesheet { href: asset!("/assets/styling/ender.css") }
document::Link { rel: "stylesheet", href: ENDER_CSS }
footer {
p { "Brock Tomlinson © 2025" }
div {

View File

@ -2,8 +2,8 @@
//! They can be used to defined common UI elements like buttons, forms, and modals. In this template, we define a Hero
//! component to be used in our app.
// mod hero;
// pub use hero::Hero;
mod hero;
pub use hero::Hero;
mod techs;
pub use techs::TechCat;

View File

@ -1,6 +1,8 @@
use crate::helper_fun::tech_table_lookup;
use dioxus::prelude::*;
const TECHS_CSS: Asset = asset!("/assets/styling/techs.css");
#[component]
pub fn TechCard(tech_props: &'static str) -> Element {
let props_tech = tech_table_lookup(tech_props);
@ -17,12 +19,14 @@ pub fn TechCard(tech_props: &'static str) -> Element {
#[component]
pub fn TechCat(cat: &'static str, tech_vec: Vec<&'static str>) -> Element {
rsx! {
document::Stylesheet { href: asset!("/assets/styling/techs.css") }
document::Link { rel: "stylesheet", href: TECHS_CSS }
div { class: "tech-cat",
h3 { "{cat}" }
div { class: "tech-row",
for tech in tech_vec {
TechCard { tech_props: tech }
TechCard {
tech_props: tech,
}
}
}
}

View File

@ -9,15 +9,6 @@ pub fn get_tech_logos_from_str(used_tech: &'static str) -> Element {
}
}
#[component]
pub fn set_meta_tags(description: &'static str, keywords: &'static str) -> Element {
rsx! {
document::Meta { name: "description", content: description }
document::Meta { name: "keywords", content: keywords }
document::Meta { name: "author", content: "Brock Tomlinson" }
}
}
#[derive(PartialEq, Props, Clone, Copy)]
pub struct TechDes {
pub tech_name: &'static str,

View File

@ -1,7 +1,7 @@
use dioxus::prelude::*;
// use components::Hero;
use views::{Blog, Blogs, ContactMe, Home, Navbar, Projects};
use views::{Blog, Blogs, ContactMe, Home, Navbar, NewHome, Projects};
/// Define a components module that contains all shared components for our app.
mod components;
@ -28,10 +28,10 @@ pub enum Route {
Home {},
// The route attribute can include dynamic parameters that implement [`std::str::FromStr`] and [`std::fmt::Display`] with the `:` syntax.
// In this case, id will match any integer like `/blog/123` or `/blog/-456`.
#[route("/blogs/:page_num")]
#[route("/blogs/:id")]
// Fields of the route variant will be passed to the component as props. In this case, the blog component must accept
// an `id` prop of type `i32`.
Blogs { page_num: u32 },
Blogs { id: i32 },
#[route("/blogs/:blog_title")]
Blog {blog_title: String},
@ -40,20 +40,21 @@ pub enum Route {
Projects {},
#[route("/contact")]
ContactMe {},
ContactMe,
// #[route("/new_home")]
// NewHome {},
#[route("/new_home")]
NewHome {},
// PageNotFound is a catch all route that will match any route and placing the matched segments in the route field
#[route("/:..route")]
PageNotFound { route: Vec<String> },
}
const NOT_FOUND_CSS: Asset = asset!("/assets/styling/notFound.css");
#[component]
fn PageNotFound(route: Vec<String>) -> Element {
rsx! {
document::Stylesheet { href: asset!("/assets/styling/notFound.css") }
document::Title { "Brock Tomlinson - Not Found" }
document::Link { rel: "stylesheet", href: NOT_FOUND_CSS }
div { id: "not-found",
h1 { "Page not found" }
p { "We are terribly sorry, but the page you requested doesn't exist." }

35
old dioxus/src/main.rs Normal file
View File

@ -0,0 +1,35 @@
// The dioxus prelude contains a ton of common items used in dioxus apps. It's a good idea to import wherever you
// need dioxus
use dioxus::prelude::*;
use personal_site::Route;
// We can import assets in dioxus with the `asset!` macro. This macro takes a path to an asset relative to the crate root.
// The macro returns an `Asset` type that will display as the path to the asset in the browser or a local path in desktop bundles.
const FAVICON: Asset = asset!("/assets/favicon.ico");
// The asset macro also minifies some assets like CSS and JS to make bundled smaller
const MAIN_CSS: Asset = asset!("/assets/styling/main.css");
fn main() {
// The `launch` function is the main entry point for a dioxus app. It takes a component and renders it with the platform feature
// you have enabled
dioxus::launch(App);
}
/// App is the main component of our app. Components are the building blocks of dioxus apps. Each component is a function
/// that takes some props and returns an Element. In this case, App takes no props because it is the root of our app.
///
/// Components should be annotated with `#[component]` to support props, better error messages, and autocomplete
#[component]
fn App() -> Element {
// The `rsx!` macro lets us define HTML inside of rust. It expands to an Element with all of our HTML inside.
rsx! {
// In addition to element and text (which we will see later), rsx can contain other components. In this case,
// we are using the `document::Link` component to add a link to our favicon and main CSS file into the head of our app.
document::Link { rel: "icon", href: FAVICON }
document::Link { rel: "stylesheet", href: MAIN_CSS }
// The router component renders the route enum we defined above. It will handle synchronization of the URL and render
// the layouts and components for the active route.
Router::<Route> {}
}
}

View File

@ -0,0 +1,51 @@
use crate::Route;
use dioxus::{document::Link, prelude::*};
const BLOG_CSS: Asset = asset!("/assets/styling/blog.css");
/// The Blog page component that will be rendered when the current route is `[Route::Blog]`
///
/// The component takes a `id` prop of type `i32` from the route enum. Whenever the id changes, the component function will be
/// re-run and the rendered HTML will be updated.
#[component]
pub fn Blog(blog_title: String) -> Element {
rsx! {
document::Link { rel: "stylesheet", href: BLOG_CSS }
div { id: "blog",
// Content
h1 { "This is blog #{blog_title}!" }
p {
"In blog #{blog_title}, we show how the Dioxus router works and how URL parameters can be passed as props to our route components."
}
// // Navigation links
// // The `Link` component lets us link to other routes inside our app. It takes a `to` prop of type `Route` and
// // any number of child nodes.
// Link {
// // The `to` prop is the route that the link should navigate to. We can use the `Route` enum to link to the
// // blog page with the id of -1. Since we are using an enum instead of a string, all of the routes will be checked
// // at compile time to make sure they are valid.
// to: Route::Blog { id: id - 1 },
// "Previous"
// }
// span { " <---> " }
// Link { to: Route::Blog { id: id + 1 }, "Next" }
}
}
}
#[component]
pub fn Blogs(id: i32) -> Element {
rsx! {
document::Link { rel: "stylesheet", href: BLOG_CSS }
div { id: "blogs",
h1 { "Page Under Development" }
p { "Please Try Again Later" }
dioxus::prelude::Link { to: Route::Home {},
button { "Home" }
}
}
}
}

View File

@ -1,18 +1,19 @@
use dioxus::prelude::*;
const PROFESSIONAL_PHOTO_JPG: Asset = asset!("assets/professional_photo_2023.jpg");
const CONTACT_CSS: Asset = asset!("/assets/styling/contact.css");
#[component]
pub fn Contact() -> Element {
rsx! {
document::Stylesheet { href: asset!("/assets/styling/contact.css") }
document::Link { href: CONTACT_CSS, rel: "stylesheet" }
h2 { "Contact" }
div { id: "contact",
div {
div {
img {
src: PROFESSIONAL_PHOTO_JPG,
alt: "Brock's professional photo",
alt: "Borck's professional photo",
}
}
}

View File

@ -0,0 +1,74 @@
use std::collections::HashMap;
use dioxus::{logger::tracing, prelude::*};
use crate::views::Contact;
const CONTACTME_CSS: Asset = asset!("/assets/styling/contactme.css");
#[component]
pub fn ContactMe() -> Element {
let mut pre_form: Signal<HashMap<&'static str, String>> = use_signal(|| {
HashMap::from([
("Name", "".to_string()),
("Email", "".to_string()),
("Message", "".to_string()),
])
});
let mut error_box_message: Signal<String> = use_signal(|| "".to_string());
rsx! {
document::Link { rel: "stylesheet", href: CONTACTME_CSS }
div { id: "ContactMe",
div {
h2 { "Get in Touch" }
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"
}
}
div {
div { id: "contact-me",
label { "Name" }
input {
oninput: move |event| {
pre_form.write().insert("Name", event.value());
},
}
label { "Email" }
input {
r#type: "email",
oninput: move |event| {
pre_form.write().insert("Email", event.value());
},
}
label { "Message" }
textarea {
oninput: move |event| {
pre_form.write().insert("Message", event.value());
},
}
p { "{error_box_message}" }
button {
r#type: "submit",
onclick: move |_| tracing::info!("Clicked!\n{:?}", pre_form),
"Submit"
}
}
}
}
Contact {}
}
}
// onsubmit:move |event| { log::info!("Submitted! {event:?}"),
// FormEvent {
// value: "NameEmailMessageSubmit",
// values: {
// "name": FormValue(["asdasd"]),
// "message": FormValue(["asdads"]),
// "email": FormValue(["adasdad@asdasd.asdads"])
// },
// valid: false
// }

View File

@ -3,6 +3,8 @@ use crate::views::{Contact, Projects};
use crate::Route;
use dioxus::prelude::*;
const HOME_CSS: Asset = asset!("/assets/styling/home.css");
#[component]
pub fn Home() -> Element {
let languages = vec![
@ -30,33 +32,30 @@ pub fn Home() -> Element {
];
let platforms = vec!["AWS", "Cloudflare", "Vercel", "Netlify", "Gitea", "Github"];
rsx!(
document::Title { "Brock Tomlinson - Home" }
document::Stylesheet { href: asset!("/assets/styling/home.css") }
document::Link { rel: "stylesheet", href: HOME_CSS }
div {
div { id: "home-intro",
h1 { "Hi I'm Brock" }
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."
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 {
"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."
where we can collect data remotely and graph data for instantaneous and future analysis,
during vechile operation."
}
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.
where I thought the application of this was so futuristic and downright cool that I knew I wanted to persure 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 {
"I adore problem solving and building cool stuff, I'm happy to jump in and get started! "
Link { to: Route::ContactMe {},
button { "Let's create something great together!" }
}
"I advore problem solving and building cool stuff, I'm happy to jump in and get started! "
Link { to: Route::ContactMe {}, "Let's create something great together!" }
}
}
div { class: "technologies",
@ -74,7 +73,7 @@ pub fn Home() -> Element {
}
}
Contact {}
Projects { independent_page: false }
Projects {}
div { id: "experience",
h2 { "Experience" }
div {

View File

@ -8,8 +8,8 @@
//! The [`Navbar`] component will be rendered on all pages of our app since every page is under the layout. The layout defines
//! a common wrapper around all child routes.
// mod new_home;
// pub use new_home::NewHome;
mod new_home;
pub use new_home::NewHome;
mod blog;
pub use blog::{Blog, Blogs};

View File

@ -0,0 +1,32 @@
use crate::components::Ender;
use crate::Route;
use dioxus::prelude::*;
const NAVBAR_CSS: Asset = asset!("/assets/styling/navbar.css");
const STD_COLOUR_AND_FONTS_CSS: Asset = asset!("assets/styling/standardColoursandFonts.css");
/// The Navbar component that will be rendered on all pages of our app since every page is under the layout.
///
///
/// This layout component wraps the UI of [Route::Home] and [Route::Blog] in a common navbar. The contents of the Home and Blog
/// routes will be rendered under the outlet inside this component
#[component]
pub fn Navbar() -> Element {
rsx! {
document::Link { rel: "stylesheet", href: NAVBAR_CSS }
document::Link { rel: "stylesheet", href: STD_COLOUR_AND_FONTS_CSS }
div { id: "navbar",
Link { to: Route::Home {}, "Home" }
Link { to: Route::Projects {}, "Projects" }
Link { to: Route::Blogs { id: 0 }, "Blogs" }
Link { to: Route::ContactMe {}, "Contact" }
}
// The `Outlet` component is used to render the next component inside the layout. In this case, it will render either
// the [`Home`] or [`Blog`] component depending on the current route.
Outlet::<Route> {}
Ender {}
}
}

View File

@ -2,58 +2,19 @@ use crate::helper_fun::get_tech_logos_from_str;
use dioxus::prelude::*;
#[component]
pub fn Projects(#[props(default = true)] independent_page: bool) -> Element {
pub fn Projects() -> Element {
rsx! {
if independent_page {
document::Title { "Brock Tomlinson - Projects" }
}
div {
h2 { "Projects" }
p { "Top Featured and Recent Projects" }
}
div { class: "project-section",
ProjectCards {
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: vec![
"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.",
}
ProjectCards {
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_name: "Portfolio Site",
website_prop: "https://darkicewolf50.github.io",
github_prop: "https://github.com/darkicewolf50/darkicewolf50.github.io",
project_img: "https://res.cloudinary.com/dpgrgsh7g/image/upload/v1745630861/Portfolio_site_k4mhmj.png",
techs_used: vec!["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.",
}
ProjectCards {
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: vec!["Rust", "CSS", "Dioxus", "Git", "Github"],
techs_used: vec!["Rust", "CSS", "Dioxus", "Github Actions", "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.
@ -62,7 +23,6 @@ pub fn Projects(#[props(default = true)] independent_page: bool) -> Element {
ProjectCards {
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: vec!["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.
@ -72,7 +32,7 @@ pub fn Projects(#[props(default = true)] independent_page: bool) -> Element {
}
ProjectCards {
project_name: "UCalgary Baja Website",
website_link: "https://uofcbaja.pages.dev",
website_prop: "https://uofcbaja.pages.dev",
project_img: "https://res.cloudinary.com/dpgrgsh7g/image/upload/v1745633714/ucalgary-baja-site-April.png",
techs_used: vec![
"HTML5",
@ -97,19 +57,19 @@ pub fn Projects(#[props(default = true)] independent_page: bool) -> Element {
}
}
const PROJECT_CARDS_CSS: Asset = asset!("/assets/styling/projectCards.css");
#[component]
pub fn ProjectCards(
website_link: Option<&'static str>,
github_link: Option<&'static str>,
gitea_link: Option<&'static str>,
dockerhub_link: Option<&'static str>,
website_prop: Option<&'static str>,
github_prop: Option<&'static str>,
project_name: &'static str,
techs_used: Vec<&'static str>,
project_des: &'static str,
#[props(default = "https://picsum.photos/200")] project_img: &'static str,
) -> Element {
rsx! {
document::Stylesheet { href: asset!("/assets/styling/projectCards.css") }
document::Link { href: PROJECT_CARDS_CSS, rel: "stylesheet" }
div { class: "project-card",
img {
src: "{project_img}",
@ -118,22 +78,12 @@ pub fn ProjectCards(
div { class: "project-title-info",
h3 { "{project_name}" }
div {
if let Some(github_site) = github_link {
if let Some(github_site) = github_prop {
a { href: "{github_site}",
get_tech_logos_from_str { used_tech: "Github" }
}
}
if let Some(gitea_site) = gitea_link {
a { href: "{gitea_site}", id: "gitea",
get_tech_logos_from_str { used_tech: "Gitea" }
}
}
if let Some(dockerhub) = dockerhub_link {
a { href: "{dockerhub}", id: "dockerhub",
get_tech_logos_from_str { used_tech: "Docker" }
}
}
if let Some(site) = website_link {
if let Some(site) = website_prop {
a { href: "{site}",
get_tech_logos_from_str { used_tech: "Internet" }
}

10639
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

28
package.json Normal file
View File

@ -0,0 +1,28 @@
{
"name": "personal-site",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint",
"pages:build": "npx @cloudflare/next-on-pages",
"preview": "npm run pages:build && wrangler pages dev",
"deploy": "npm run pages:build && wrangler pages deploy"
},
"dependencies": {
"next": "15.3.2",
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
"devDependencies": {
"@cloudflare/next-on-pages": "^1.13.12",
"@cloudflare/workers-types": "^4.20250508.0",
"@eslint/eslintrc": "^3",
"eslint": "^9",
"eslint-config-next": "15.3.1",
"vercel": "^41.7.3",
"wrangler": "^4.14.4"
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

1
public/file.svg Normal file
View File

@ -0,0 +1 @@
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 391 B

1
public/globe.svg Normal file
View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

1
public/next.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

1
public/vercel.svg Normal file
View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 128 B

1
public/window.svg Normal file
View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>

After

Width:  |  Height:  |  Size: 385 B

53
src/app/home.css Normal file
View File

@ -0,0 +1,53 @@
#home-intro {
display: flex;
flex-direction: column;
width: 90%;
margin-top: 2svh;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
}
#home-intro h1 {
border-bottom: var(--underlineTitle);
border-radius: var(--underlineTitleBorderRadius);
display: flex;
margin: 2svh 2svw;
padding: 0svh 2svw;
padding-bottom: 1svh;
}
#home-intro p {
margin: 1svh 4svw;
padding: 0svh 2svw;
padding-bottom: 1svh;
}
.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;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
}
#experience div {
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
margin: 4svh 0px;
}

33
src/app/layout.js Normal file
View File

@ -0,0 +1,33 @@
import { Geist, Geist_Mono } from "next/font/google";
import "../globals.css";
import Navbar from "@/components/navbar/navbar";
import Ender from "@/components/footer/ender";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata = {
title: "Brock Tomlinson",
description:
"The protfolio site for Brock Tomlinson, it has some blogs, my personal preferences all skill set",
};
export default function RootLayout({ children }) {
return (
<html lang="en">
{/* className={`${geistSans.variable} ${geistMono.variable}`} */}
<body>
<Navbar />
<main>{children}</main>
<Ender />
</body>
</html>
);
}

46
src/app/not-found.js Normal file
View File

@ -0,0 +1,46 @@
import Navbar from "@/components/navbar/navbar";
export const runtime = "edge";
export default function NotFound() {
return (
<>
<title>Brock Tomlinson - Not Found</title>
<Navbar />
</>
);
}
// const styles = {
// error: {
// fontFamily:
// 'system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"',
// height: "100vh",
// textAlign: "center",
// display: "flex",
// flexDirection: "column",
// alignItems: "center",
// justifyContent: "center",
// },
// desc: {
// display: "inline-block",
// },
// h1: {
// display: "inline-block",
// margin: "0 20px 0 0",
// padding: "0 23px 0 0",
// fontSize: 24,
// fontWeight: 500,
// verticalAlign: "top",
// lineHeight: "49px",
// },
// h2: {
// fontSize: 14,
// fontWeight: 400,
// lineHeight: "49px",
// margin: 0,
// },
// };

45
src/app/page.js Normal file
View File

@ -0,0 +1,45 @@
"use client";
import Image from "next/image";
import Ender from "../components/footer/ender";
import "./home.css";
import Link from "next/link";
export default function Home() {
return (
<main>
<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
persure 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 advore problem solving and building cool stuff, I'm happy to jump in
and get started!
<Link href="ContactMe">Let's create something great together!</Link>
</p>
</div>
</main>
);
}

View File

@ -0,0 +1,30 @@
footer {
display: flex;
flex-direction: column;
text-align: center;
background-color: var(--card-background-color);
border-radius: var(--card-border-radius);
/* background-color: #d3d3d3; */
}
footer div {
display: flex;
flex-direction: row;
flex: 1 1 2;
justify-content: space-evenly;
}
footer img {
height: 60px;
filter: invert() hue-rotate(180deg);
}
footer a {
display: flex;
flex-direction: column;
align-items: center;
text-decoration: none;
color: inherit;
}

View File

@ -0,0 +1,45 @@
import "./ender.css";
export default function Ender() {
return (
<footer>
<p>Brock Tomlinson © 2025</p>
<div>
<a href="https://github.com/darkicewolf50">
<img
src="https://www.svgrepo.com/show/512317/github-142.svg"
alt="Github's logo"
/>
<p>Github</p>
</a>
<a href="mailto:darkicewolf50@gmail.com">
<img
src="https://www.svgrepo.com/show/491226/email.svg"
alt="Email icon"
/>
<p>Email</p>
</a>
<a href="https://www.linkedin.com/in/brock-tomlinson/">
<img
src="https://www.svgrepo.com/show/521725/linkedin.svg"
alt="LinkedIn's logo"
/>
<p>LinkedIn</p>
</a>
<a href="https://www.twitch.tv/darkicewolf50">
<img
src="https://www.svgrepo.com/show/519925/twitch.svg"
alt="Twitch's logo"
/>
<p>Twitch</p>
</a>
<a href="https://www.youtube.com/@darkicewolf50">
<img
src="https://www.svgrepo.com/show/521936/youtube.svg"
alt="Youtube's logo"
/>
<p>Youtube</p>
</a>
</div>
</footer>
);
}

View File

@ -0,0 +1,16 @@
#navbar {
display: flex;
flex-direction: row;
}
#navbar a {
color: #ffffff;
margin-right: 20px;
text-decoration: none;
transition: color 0.2s ease;
}
#navbar a:hover {
cursor: pointer;
color: #91a4d2;
}

View File

@ -0,0 +1,13 @@
import Link from "next/link";
import "./navbar.css";
export default function Navbar() {
return (
<div id="navbar">
<Link href="/">Home</Link>
<Link href="/projects">Projects</Link>
<Link href="/blogs/0">Blogs</Link>
<Link href="/Contact">Contact</Link>
</div>
);
}

169
src/globals.css Normal file
View File

@ -0,0 +1,169 @@
: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;
}
body {
background-color: #0f1116;
color: #ffffff;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
margin: 20px;
}
h2 {
border-bottom: var(--underlineTitle);
border-radius: var(--underlineTitleBorderRadius);
display: flex;
margin: 2svh 2svw;
padding: 0svh 2svw;
padding-bottom: 1svh;
}
/*
p {
width: 90%;
margin: 2svh 0px;
margin-left: 2svw;
padding-left: 2svw;
padding-bottom: 1svh;
} */
#hero {
margin: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
#links {
width: 400px;
text-align: left;
font-size: x-large;
color: white;
display: flex;
flex-direction: column;
}
#links a {
color: white;
text-decoration: none;
margin-top: 20px;
margin: 10px 0px;
border: white 1px solid;
border-radius: 5px;
padding: 10px;
}
#links a:hover {
background-color: #1f1f1f;
cursor: pointer;
}
#header {
max-width: 1200px;
}
/* /* :root {
--background: #ffffff;
--foreground: #171717;
}
@media (prefers-color-scheme: dark) {
:root {
--background: #0a0a0a;
--foreground: #ededed;
}
}
html,
body {
max-width: 100vw;
overflow-x: hidden;
}
body {
color: var(--foreground);
background: var(--background);
font-family: Arial, Helvetica, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
a {
color: inherit;
text-decoration: none;
}
@media (prefers-color-scheme: dark) {
html {
color-scheme: dark;
}
} */
/*
body {
background-color: #0f1116;
color: #ffffff;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
margin: 20px;
}
h2 {
border-bottom: var(--underlineTitle);
border-radius: var(--underlineTitleBorderRadius);
display: flex;
margin: 2svh 2svw;
padding: 0svh 2svw;
padding-bottom: 1svh;
}*/
/*
p {
width: 90%;
margin: 2svh 0px;
margin-left: 2svw;
padding-left: 2svw;
padding-bottom: 1svh;
} */
/*
#hero {
margin: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
#links {
width: 400px;
text-align: left;
font-size: x-large;
color: white;
display: flex;
flex-direction: column;
}
#links a {
color: white;
text-decoration: none;
margin-top: 20px;
margin: 10px 0px;
border: white 1px solid;
border-radius: 5px;
padding: 10px;
}
#links a:hover {
background-color: #1f1f1f;
cursor: pointer;
}
#header {
max-width: 1200px;
} */

View File

@ -1,72 +0,0 @@
// The dioxus prelude contains a ton of common items used in dioxus apps. It's a good idea to import wherever you
// need dioxus
use dioxus::prelude::*;
use personal_site::Route;
// We can import assets in dioxus with the `asset!` macro. This macro takes a path to an asset relative to the crate root.
// The macro returns an `Asset` type that will display as the path to the asset in the browser or a local path in desktop bundles.
const FAVICON: Asset = asset!("/assets/favicon.ico");
// The asset macro also minifies some assets like CSS and JS to make bundled smaller
// const MAIN_CSS: Asset = asset!("/assets/styling/main.css");
fn main() {
// The `launch` function is the main entry point for a dioxus app. It takes a component and renders it with the platform feature
// you have enabled
dioxus::launch(App);
// for compiling the app
// dioxus::LaunchBuilder::new()
// // Set the server config only if we are building the server target
// .with_cfg(server_only! {
// ServeConfig::builder()
// // Enable incremental rendering
// .incremental(
// IncrementalRendererConfig::new()
// // Store static files in the public directory where other static assets like wasm are stored
// .static_dir(
// std::env::current_exe()
// .unwrap()
// .parent()
// .unwrap()
// .join("public")
// )
// // Don't clear the public folder on every build. The public folder has other files including the wasm
// // binary and static assets required for the app to run
// .clear_cache(false)
// )
// .enable_out_of_order_streaming()
// })
// .launch(App);
}
/// App is the main component of our app. Components are the building blocks of dioxus apps. Each component is a function
/// that takes some props and returns an Element. In this case, App takes no props because it is the root of our app.
///
/// Components should be annotated with `#[component]` to support props, better error messages, and autocomplete
#[component]
fn App() -> Element {
// The `rsx!` macro lets us define HTML inside of rust. It expands to an Element with all of our HTML inside.
rsx! {
// In addition to element and text (which we will see later), rsx can contain other components. In this case,
// we are using the `document::Link` component to add a link to our favicon and main CSS file into the head of our app.
document::Link { rel: "icon", href: FAVICON }
// document::Link { rel: "stylesheet", href: MAIN_CSS }
document::Stylesheet { href: asset!("/assets/styling/main.css") }
// The router component renders the route enum we defined above. It will handle synchronization of the URL and render
// the layouts and components for the active route.
Router::<Route> {}
}
}
// The server function at the endpoint "static_routes" will be called by the CLI to generate the list of static
// routes. You must explicitly set the endpoint to `"static_routes"` in the server function attribute instead of
// the default randomly generated endpoint.
// #[server(endpoint = "static_routes", output = server_fn::codec::Json)]
// async fn static_routes() -> Result<Vec<String>, ServerFnError> {
// // The `Routable` trait has a `static_routes` method that returns all static routes in the enum
// Ok(Route::static_routes()
// .iter()
// .map(ToString::to_string)
// .collect())
// }

169
src/page.module.css Normal file
View File

@ -0,0 +1,169 @@
/* .page {
--gray-rgb: 0, 0, 0;
--gray-alpha-200: rgba(var(--gray-rgb), 0.08);
--gray-alpha-100: rgba(var(--gray-rgb), 0.05);
--button-primary-hover: #383838;
--button-secondary-hover: #f2f2f2;
display: grid;
grid-template-rows: 20px 1fr 20px;
align-items: center;
justify-items: center;
min-height: 100svh;
padding: 80px;
gap: 64px;
font-family: var(--font-geist-sans);
}
@media (prefers-color-scheme: dark) {
.page {
--gray-rgb: 255, 255, 255;
--gray-alpha-200: rgba(var(--gray-rgb), 0.145);
--gray-alpha-100: rgba(var(--gray-rgb), 0.06);
--button-primary-hover: #ccc;
--button-secondary-hover: #1a1a1a;
}
}
.main {
display: flex;
flex-direction: column;
gap: 32px;
grid-row-start: 2;
}
.main ol {
font-family: var(--font-geist-mono);
padding-left: 0;
margin: 0;
font-size: 14px;
line-height: 24px;
letter-spacing: -0.01em;
list-style-position: inside;
}
.main li:not(:last-of-type) {
margin-bottom: 8px;
}
.main code {
font-family: inherit;
background: var(--gray-alpha-100);
padding: 2px 4px;
border-radius: 4px;
font-weight: 600;
}
.ctas {
display: flex;
gap: 16px;
}
.ctas a {
appearance: none;
border-radius: 128px;
height: 48px;
padding: 0 20px;
border: none;
border: 1px solid transparent;
transition:
background 0.2s,
color 0.2s,
border-color 0.2s;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
line-height: 20px;
font-weight: 500;
}
a.primary {
background: var(--foreground);
color: var(--background);
gap: 8px;
}
a.secondary {
border-color: var(--gray-alpha-200);
min-width: 158px;
}
.footer {
grid-row-start: 3;
display: flex;
gap: 24px;
}
.footer a {
display: flex;
align-items: center;
gap: 8px;
}
.footer img {
flex-shrink: 0;
}
/* Enable hover only on non-touch devices */
/*
@media (hover: hover) and (pointer: fine) {
a.primary:hover {
background: var(--button-primary-hover);
border-color: transparent;
}
a.secondary:hover {
background: var(--button-secondary-hover);
border-color: transparent;
}
.footer a:hover {
text-decoration: underline;
text-underline-offset: 4px;
}
} */
/*
@media (max-width: 600px) {
.page {
padding: 32px;
padding-bottom: 80px;
}
.main {
align-items: center;
}
.main ol {
text-align: center;
}
.ctas {
flex-direction: column;
}
.ctas a {
font-size: 14px;
height: 40px;
padding: 0 16px;
}
a.secondary {
min-width: auto;
}
.footer {
flex-wrap: wrap;
align-items: center;
justify-content: center;
}
} */
/*
@media (prefers-color-scheme: dark) {
.logo {
filter: invert();
}
} */

View File

@ -1,253 +0,0 @@
use crate::Route;
// use dioxus::logger::tracing::info;
use dioxus::prelude::*;
use reqwest;
use serde::{Deserialize, Serialize};
/// The Blog page component that will be rendered when the current route is `[Route::Blog]`
///
/// The component takes a `id` prop of type `i32` from the route enum. Whenever the id changes, the component function will be
/// re-run and the rendered HTML will be updated.
#[component]
pub fn Blog(blog_title: String) -> Element {
let blog_resource = use_resource({
let title = blog_title.clone();
move || {
let value = title.clone();
async move {
get_blog(value).await.unwrap_or(BlogContent {
blog_file_name: String::new(),
date_last_edit: "9999-12-01".to_string(),
blog_title: "Not Found".to_string(),
tags: vec!["#error".to_string()],
html_blog_content: "<p>Blog not found</p>".to_string(),
})
}
}
});
rsx! {
document::Stylesheet { href: asset!("/assets/styling/blog.css") }
document::Title { "Brock Tomlinson - {blog_title.clone()}" }
// document::Meta { name: "author", content: "Brock Tomlinson" }
document::Meta { name: "robots", content: "noindex, nofollow" }
div { id: "blog",
// Content
// h1 { "This is blog #{blog_title}!" }
// p {
// "In blog #{blog_title}, we show how the Dioxus router works and how URL parameters can be passed as props to our route components."
// }
// // Navigation links
// // The `Link` component lets us link to other routes inside our app. It takes a `to` prop of type `Route` and
// // any number of child nodes.
// Link {
// // The `to` prop is the route that the link should navigate to. We can use the `Route` enum to link to the
// // blog page with the id of -1. Since we are using an enum instead of a string, all of the routes will be checked
// // at compile time to make sure they are valid.
// to: Route::Blog { id: id - 1 },
// "Previous"
// }
// span { " <---> " }
Link { to: Route::Blogs { page_num: 0 }, "Go Back" }
if let Some(blog_content) = &*blog_resource.read() {
article {
header { id: "blog_info",
h1 { "{blog_content.blog_title}" }
div {
ul {
for tag in &blog_content.tags {
li { "{tag}" }
}
}
p { "{&blog_content.date_last_edit}" }
}
}
section {
id: "blog_content",
dangerous_inner_html: *&blog_content.html_blog_content.as_str(),
}
}
} else {
p { "Loading..." }
}
}
}
}
async fn get_blog(blog_name: String) -> Result<BlogContent, reqwest::Error> {
let client = reqwest::Client::new();
let res = client
.get(format!("blogs/blog/{}", blog_name))
.timeout(std::time::Duration::from_secs(10))
.send()
.await?
.json::<BlogContent>()
// .text()
.await?;
// tracing::info!("{:?}", res);
Ok(res)
// to be removed
// let blog = serde_json::from_str(&res).unwrap_or(BlogContent {
// blog_file_name: "blog_title".to_string(),
// blog_title: "This is a blog #blog_title".to_string(),
// date_last_edit: "2025-5-20".to_string(),
// tags: "#test".to_string(),
// html_blog_content: "<p>
// In blog #{blog_title}, we show how the Dioxus router works and
// how URL parameters can be passed as props to our route components.
// </p>"
// .to_string(),
// });
// Ok(blog)
// Ok(BlogContent {
// blog_file_name: "blog_title".to_string(),
// blog_title: "This is a blog #blog_title".to_string(),
// date_last_edit: "2025-5-20".to_string(),
// tags: "#test".to_string(),
// html_blog_content: "<p>
// In blog #{blog_title}, we show how the Dioxus router works and
// how URL parameters can be passed as props to our route components.
// </p>"
// .to_string(),
// })
}
#[component]
pub fn Blogs(page_num: u32) -> Element {
let mut _num_limit: Signal<u8> = use_signal(|| 10);
let blogs_resource: Resource<Vec<BlogContent>> =
use_resource(use_reactive!(|(_num_limit, page_num)| async move {
get_blogs_preview(_num_limit(), page_num)
.await
.unwrap_or_else(|_| vec![])
}));
rsx! {
document::Stylesheet { href: asset!("/assets/styling/blog.css") }
document::Meta { name: "robots", content: "noindex, nofollow" }
document::Title { "Brock Tomlinson - Blogs" }
div { id: "blogs",
div { id: "blogs-title",
h1 { "Blogs" }
p {
"This is a collection of blog posts, ranging from tutorials, technologies I found interesting, and opinion pieces"
}
p { "These blogs are my opinion and mine alone" }
}
div { id: "blogs-on-show",
if let Some(blogs) = &*blogs_resource.read() {
if blogs.len() > 0 {
for blog in blogs.iter() {
Link {
class: "blog-preview",
to: Route::Blog {
blog_title: blog.blog_file_name.clone(),
},
div { id: "blog_info",
h1 { "{blog.blog_title}" }
div {
div {
for tag in &blog.tags {
p { "{tag}" }
}
}
p { "{&blog.date_last_edit}" }
}
}
div {
id: "blog_content",
dangerous_inner_html: *&blog.html_blog_content.as_str(),
}
button { "Read More Here" }
}
}
} else {
div { id: "blog-out-of",
p { "No more blogs available" }
Link { to: Route::Blogs { page_num: 0 },
button { "Go Back" }
}
}
}
} else {
div { id: "blog-loading",
p { "Loading blogs..." }
}
}
}
div { id: "blog-nav",
if page_num > 0 {
Link {
to: Route::Blogs {
page_num: page_num - 1,
},
button { "<-- Go Back" }
}
}
div {
label { "display: " }
select {
onchange: move |event| {
_num_limit.set(event.value().parse::<u8>().unwrap_or(10));
},
option { "10" }
option { "25" }
option { "50" }
option { "100" }
}
}
Link {
to: Route::Blogs {
page_num: page_num + 1,
},
button { "Next -->" }
}
}
}
}
}
#[derive(Deserialize, Serialize, Debug)]
struct BlogContent {
pub blog_file_name: String,
pub date_last_edit: String,
pub blog_title: String,
pub tags: Vec<String>,
pub html_blog_content: String,
}
async fn get_blogs_preview(
_num_limit: u8,
page_num: u32,
) -> Result<Vec<BlogContent>, reqwest::Error> {
let client = reqwest::Client::new();
let res = client
.get(format!("blogs/{}/{}", _num_limit, page_num))
.timeout(std::time::Duration::from_secs(10))
.send()
.await?
.json::<Vec<BlogContent>>()
// .text()
.await?;
Ok(res)
// let json: serde_json::Value = serde_json::from_str(&res).unwrap();
// let blogs: Vec<BlogContent> = serde_json::from_value(json).unwrap_or_default();
// // Extract the "Blogs" array and deserialize it into Vec<BlogContent>
// let blogs: Vec<BlogContent> = serde_json::from_value(
// json.get("Blogs")
// .cloned()
// .unwrap_or(serde_json::Value::Null),
// )
// .unwrap_or_default();
}

View File

@ -1,130 +0,0 @@
use reqwest::Client;
use serde_json;
// use dioxus::logger::tracing;
use dioxus::prelude::*;
use crate::views::Contact;
#[component]
pub fn ContactMe() -> Element {
let mut contact_me_name = use_signal(|| String::new());
let mut contact_me_email = use_signal(|| String::new());
let mut contact_me_message = use_signal(|| String::new());
let mut _error_box_message = use_signal(|| String::new());
rsx! {
document::Stylesheet { href: asset!("/assets/styling/contactme.css") }
document::Title { "Brock Tomlinson - Contact" }
div { id: "ContactMe",
div {
h2 { "Get in Touch" }
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"
}
}
div {
label { "Name" }
input {
oninput: move |event| {
contact_me_name.set(event.value());
},
}
label { "Email" }
input {
oninput: move |event| {
contact_me_email.set(event.value());
},
}
label { "Message" }
textarea {
oninput: move |event| {
contact_me_message.set(event.value());
},
}
p { "{_error_box_message}" }
button {
onclick: move |_| async move {
send_message(
contact_me_name(),
contact_me_email(),
contact_me_message(),
_error_box_message,
)
.await
},
"Submit"
}
}
}
Contact {}
}
}
async fn send_message(name: String, email: String, message: String, mut recived: Signal<String>) {
if name == "".to_string() && email == "".to_string() && message == "".to_string() {
recived.set("Please fill fill out the form first".to_string());
return ();
} else if name == "".to_string() {
recived.set("Please fill in your name so I know who I am contacting".to_string());
return ();
} else if email == "".to_string() {
recived.set("Please fill in your email so I can get into contact".to_string());
return ();
} else if message == "".to_string() {
recived.set("Please write a message so I know why you wanted to be in contact".to_string());
return ();
}
if is_valid_email_basic(&email) == false {
recived.set("Please write a vaild email".to_string());
return ();
}
let json_to_send = serde_json::json!({
"content": format!("***New Message***\n*Name*: {name}\n*Email*: [{email}](mailto:{email})\n*Message*: {message}")
});
let client = Client::new();
let res = client.post("").json(&json_to_send).send().await;
match res {
Ok(_) => {
recived.set("Sent Sucessfully, I will be in contact with you soon".to_string());
}
Err(_) => {
recived.set("An Error Occured".to_string());
}
}
}
fn is_valid_email_basic(email: &str) -> bool {
// Find the position of '@'
if let Some(at_pos) = email.find('@') {
// Ensure there's only one '@'
if email.rfind('@') != Some(at_pos) {
return false;
}
// Split into local and domain parts
let local = &email[..at_pos];
let domain = &email[at_pos + 1..];
// Check both parts are non-empty
if local.is_empty() || domain.is_empty() {
return false;
}
// Check domain contains at least one '.' and it's not at the start or end
if let Some(dot_pos) = domain.find('.') {
// '.' must not be at the beginning or end of the domain
if dot_pos == 0 || dot_pos == domain.len() - 1 {
return false;
}
return true;
}
}
false
}

View File

@ -1,67 +0,0 @@
use crate::components::Ender;
use crate::helper_fun::set_meta_tags;
use crate::Route;
use dioxus::prelude::*;
const _ROBOTS_TXT: Asset = asset!("/assets/robots.txt");
const PROFESSIONAL_PHOTO_JPG: Asset = asset!("assets/professional_photo_2023.jpg");
/// The Navbar component that will be rendered on all pages of our app since every page is under the layout.
///
///
/// This layout component wraps the UI of [Route::Home] and [Route::Blog] in a common navbar. The contents of the Home and Blog
/// routes will be rendered under the outlet inside this component
#[component]
pub fn Navbar() -> Element {
let PHOTO_FORMAT_URL = format!("https://darkicewolf50.pages.dev{PROFESSIONAL_PHOTO_JPG}");
rsx! {
document::Stylesheet { href: asset!("/assets/styling/navbar.css") }
document::Stylesheet { href: asset!("assets/styling/standardColoursandFonts.css") }
set_meta_tags {
description: "Fourth year Software Engineering student specializing in full-stack development with a backend focus. Always improving through experience.",
keywords: "webdev Rust software engineer projects blog darkicewol50",
}
document::Meta { name: "robots", content: "index, follow" }
document::Link { rel: "canonical", href: "https://darkicewolf50.pages.dev/" }
document::Meta {
name: "google-site-verification",
content: "lsAs9c2Pv7c6Sm26z1hd2YqR2depbp4sJddIDYKHkxY",
}
document::Meta {
property: "og:title",
content: "Brock Tomlinson - Software Engineering Student",
}
document::Meta {
property: "og:description",
content: "Fourth year Software Engineering student specializing in full-stack development with a backend focus. Always improving through experience.",
}
document::Meta { property: "og:type", content: "website" }
document::Meta { property: "og:url", content: "https://darkicewolf50.pages.dev/" }
document::Meta { name: "twitter:card", content: "summary_large_image" }
document::Meta {
name: "twitter:title",
content: "Brock Tomlinson - Software Engineer",
}
document::Meta {
name: "twitter:description",
content: "Fourth year Software Engineering student specializing in full-stack development with a backend focus. Always improving through experience.",
}
document::Meta { name: "twitter:image", content: PHOTO_FORMAT_URL.clone() }
document::Meta { property: "og:image", content: PHOTO_FORMAT_URL.clone() }
div { id: "navbar",
Link { to: Route::Home {}, "Home" }
Link { to: Route::Projects {}, "Projects" }
Link { to: Route::Blogs { page_num: 0 }, "Blogs" }
Link { to: Route::ContactMe {}, "Contact" }
}
// The `Outlet` component is used to render the next component inside the layout. In this case, it will render either
// the [`Home`] or [`Blog`] component depending on the current route.
Outlet::<Route> {}
Ender {}
}
}

50
wrangler.jsonc Normal file
View File

@ -0,0 +1,50 @@
/**
* For more details on how to configure Wrangler, refer to:
* https://developers.cloudflare.com/workers/wrangler/configuration/
*/
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "personal-site",
"compatibility_date": "2025-05-08",
"compatibility_flags": [
"nodejs_compat"
],
"pages_build_output_dir": ".vercel/output/static",
"observability": {
"enabled": true
}
/**
* Smart Placement
* Docs: https://developers.cloudflare.com/workers/configuration/smart-placement/#smart-placement
*/
// "placement": { "mode": "smart" },
/**
* Bindings
* Bindings allow your Worker to interact with resources on the Cloudflare Developer Platform, including
* databases, object storage, AI inference, real-time communication and more.
* https://developers.cloudflare.com/workers/runtime-apis/bindings/
*/
/**
* Environment Variables
* https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
*/
// "vars": { "MY_VARIABLE": "production_value" },
/**
* Note: Use secrets to store sensitive data.
* https://developers.cloudflare.com/workers/configuration/secrets/
*/
/**
* Static Assets
* https://developers.cloudflare.com/workers/static-assets/binding/
*/
// "assets": { "directory": "./public/", "binding": "ASSETS" },
/**
* Service Bindings (communicate between multiple Workers)
* https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings
*/
// "services": [{ "binding": "MY_SERVICE", "service": "my-service" }]
}