Add resume components and job data for SvelteKit app - Added `PageHeader`, `JobCard`, `Card`, and `Badge` components - Integrated job data for Quantified Impacts and Rannes.dev - Updated layout and page structure with new components - Included LinkedIn profile image and social links - Installed `@lucide/svelte` for icons - Removed unused `$lib/index.ts` ```
This commit is contained in:
parent
298fbc50d5
commit
6f8a5f7a33
@ -39,5 +39,8 @@
|
||||
"onlyBuiltDependencies": [
|
||||
"esbuild"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@lucide/svelte": "^0.507.0"
|
||||
}
|
||||
}
|
||||
|
113
pnpm-lock.yaml
generated
113
pnpm-lock.yaml
generated
@ -7,6 +7,10 @@ settings:
|
||||
importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@lucide/svelte':
|
||||
specifier: ^0.507.0
|
||||
version: 0.507.0(svelte@5.28.2)
|
||||
devDependencies:
|
||||
'@eslint/compat':
|
||||
specifier: ^1.2.5
|
||||
@ -64,7 +68,7 @@ importers:
|
||||
version: 5.8.3
|
||||
typescript-eslint:
|
||||
specifier: ^8.20.0
|
||||
version: 8.31.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
version: 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
vite:
|
||||
specifier: ^6.2.6
|
||||
version: 6.3.5(jiti@2.4.2)(lightningcss@1.29.2)
|
||||
@ -310,6 +314,11 @@ packages:
|
||||
'@jridgewell/trace-mapping@0.3.25':
|
||||
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
|
||||
|
||||
'@lucide/svelte@0.507.0':
|
||||
resolution: {integrity: sha512-kXIg/2IHEo1bAwZG94fjA9O6+E3Sv5aQrW2yyPf4JvCYIUIF8DGLIQI4vfjoUyNq2dEX4cI33pZarzGOHr0npg==}
|
||||
peerDependencies:
|
||||
svelte: ^5
|
||||
|
||||
'@modelcontextprotocol/sdk@1.11.0':
|
||||
resolution: {integrity: sha512-k/1pb70eD638anoi0e8wUGAlbMJXyvdV4p62Ko+EZ7eBe1xMx8Uhak1R5DgfoofsK5IBBnRwsYGTaLZl+6/+RQ==}
|
||||
engines: {node: '>=18'}
|
||||
@ -606,51 +615,51 @@ packages:
|
||||
'@types/resolve@1.20.2':
|
||||
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.31.1':
|
||||
resolution: {integrity: sha512-oUlH4h1ABavI4F0Xnl8/fOtML/eu8nI2A1nYd+f+55XI0BLu+RIqKoCiZKNo6DtqZBEQm5aNKA20G3Z5w3R6GQ==}
|
||||
'@typescript-eslint/eslint-plugin@8.32.0':
|
||||
resolution: {integrity: sha512-/jU9ettcntkBFmWUzzGgsClEi2ZFiikMX5eEQsmxIAWMOn4H3D4rvHssstmAHGVvrYnaMqdWWWg0b5M6IN/MTQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
|
||||
eslint: ^8.57.0 || ^9.0.0
|
||||
typescript: '>=4.8.4 <5.9.0'
|
||||
|
||||
'@typescript-eslint/parser@8.31.1':
|
||||
resolution: {integrity: sha512-oU/OtYVydhXnumd0BobL9rkJg7wFJ9bFFPmSmB/bf/XWN85hlViji59ko6bSKBXyseT9V8l+CN1nwmlbiN0G7Q==}
|
||||
'@typescript-eslint/parser@8.32.0':
|
||||
resolution: {integrity: sha512-B2MdzyWxCE2+SqiZHAjPphft+/2x2FlO9YBx7eKE1BCb+rqBlQdhtAEhzIEdozHd55DXPmxBdpMygFJjfjjA9A==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0
|
||||
typescript: '>=4.8.4 <5.9.0'
|
||||
|
||||
'@typescript-eslint/scope-manager@8.31.1':
|
||||
resolution: {integrity: sha512-BMNLOElPxrtNQMIsFHE+3P0Yf1z0dJqV9zLdDxN/xLlWMlXK/ApEsVEKzpizg9oal8bAT5Sc7+ocal7AC1HCVw==}
|
||||
'@typescript-eslint/scope-manager@8.32.0':
|
||||
resolution: {integrity: sha512-jc/4IxGNedXkmG4mx4nJTILb6TMjL66D41vyeaPWvDUmeYQzF3lKtN15WsAeTr65ce4mPxwopPSo1yUUAWw0hQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@typescript-eslint/type-utils@8.31.1':
|
||||
resolution: {integrity: sha512-fNaT/m9n0+dpSp8G/iOQ05GoHYXbxw81x+yvr7TArTuZuCA6VVKbqWYVZrV5dVagpDTtj/O8k5HBEE/p/HM5LA==}
|
||||
'@typescript-eslint/type-utils@8.32.0':
|
||||
resolution: {integrity: sha512-t2vouuYQKEKSLtJaa5bB4jHeha2HJczQ6E5IXPDPgIty9EqcJxpr1QHQ86YyIPwDwxvUmLfP2YADQ5ZY4qddZg==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0
|
||||
typescript: '>=4.8.4 <5.9.0'
|
||||
|
||||
'@typescript-eslint/types@8.31.1':
|
||||
resolution: {integrity: sha512-SfepaEFUDQYRoA70DD9GtytljBePSj17qPxFHA/h3eg6lPTqGJ5mWOtbXCk1YrVU1cTJRd14nhaXWFu0l2troQ==}
|
||||
'@typescript-eslint/types@8.32.0':
|
||||
resolution: {integrity: sha512-O5Id6tGadAZEMThM6L9HmVf5hQUXNSxLVKeGJYWNhhVseps/0LddMkp7//VDkzwJ69lPL0UmZdcZwggj9akJaA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@typescript-eslint/typescript-estree@8.31.1':
|
||||
resolution: {integrity: sha512-kaA0ueLe2v7KunYOyWYtlf/QhhZb7+qh4Yw6Ni5kgukMIG+iP773tjgBiLWIXYumWCwEq3nLW+TUywEp8uEeag==}
|
||||
'@typescript-eslint/typescript-estree@8.32.0':
|
||||
resolution: {integrity: sha512-pU9VD7anSCOIoBFnhTGfOzlVFQIA1XXiQpH/CezqOBaDppRwTglJzCC6fUQGpfwey4T183NKhF1/mfatYmjRqQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <5.9.0'
|
||||
|
||||
'@typescript-eslint/utils@8.31.1':
|
||||
resolution: {integrity: sha512-2DSI4SNfF5T4oRveQ4nUrSjUqjMND0nLq9rEkz0gfGr3tg0S5KB6DhwR+WZPCjzkZl3cH+4x2ce3EsL50FubjQ==}
|
||||
'@typescript-eslint/utils@8.32.0':
|
||||
resolution: {integrity: sha512-8S9hXau6nQ/sYVtC3D6ISIDoJzS1NsCK+gluVhLN2YkBPX+/1wkwyUiDKnxRh15579WoOIyVWnoyIf3yGI9REw==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0
|
||||
typescript: '>=4.8.4 <5.9.0'
|
||||
|
||||
'@typescript-eslint/visitor-keys@8.31.1':
|
||||
resolution: {integrity: sha512-I+/rgqOVBn6f0o7NDTmAPWWC6NuqhV174lfYvAm9fUaWeiefLdux9/YI3/nLugEn9L8fcSi0XmpKi/r5u0nmpw==}
|
||||
'@typescript-eslint/visitor-keys@8.32.0':
|
||||
resolution: {integrity: sha512-1rYQTCLFFzOI5Nl0c8LUpJT8HxpwVRn9E4CkMsYfuN6ctmQqExjSTzzSk0Tz2apmXy7WU6/6fyaZVVA/thPN+w==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
accepts@2.0.0:
|
||||
@ -1635,8 +1644,8 @@ packages:
|
||||
resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
typescript-eslint@8.31.1:
|
||||
resolution: {integrity: sha512-j6DsEotD/fH39qKzXTQRwYYWlt7D+0HmfpOK+DVhwJOFLcdmn92hq3mBb7HlKJHbjjI/gTOqEcc9d6JfpFf/VA==}
|
||||
typescript-eslint@8.32.0:
|
||||
resolution: {integrity: sha512-UMq2kxdXCzinFFPsXc9o2ozIpYCCOiEC46MG3yEh5Vipq6BO27otTtEBZA1fQ66DulEUgE97ucQ/3YY66CPg0A==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0
|
||||
@ -1900,6 +1909,10 @@ snapshots:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
|
||||
'@lucide/svelte@0.507.0(svelte@5.28.2)':
|
||||
dependencies:
|
||||
svelte: 5.28.2
|
||||
|
||||
'@modelcontextprotocol/sdk@1.11.0':
|
||||
dependencies:
|
||||
content-type: 1.0.5
|
||||
@ -2157,14 +2170,14 @@ snapshots:
|
||||
|
||||
'@types/resolve@1.20.2': {}
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.31.1(@typescript-eslint/parser@8.31.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)':
|
||||
'@typescript-eslint/eslint-plugin@8.32.0(@typescript-eslint/parser@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.12.1
|
||||
'@typescript-eslint/parser': 8.31.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@typescript-eslint/scope-manager': 8.31.1
|
||||
'@typescript-eslint/type-utils': 8.31.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.31.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@typescript-eslint/visitor-keys': 8.31.1
|
||||
'@typescript-eslint/parser': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@typescript-eslint/scope-manager': 8.32.0
|
||||
'@typescript-eslint/type-utils': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@typescript-eslint/visitor-keys': 8.32.0
|
||||
eslint: 9.26.0(jiti@2.4.2)
|
||||
graphemer: 1.4.0
|
||||
ignore: 5.3.2
|
||||
@ -2174,27 +2187,27 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/parser@8.31.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)':
|
||||
'@typescript-eslint/parser@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 8.31.1
|
||||
'@typescript-eslint/types': 8.31.1
|
||||
'@typescript-eslint/typescript-estree': 8.31.1(typescript@5.8.3)
|
||||
'@typescript-eslint/visitor-keys': 8.31.1
|
||||
'@typescript-eslint/scope-manager': 8.32.0
|
||||
'@typescript-eslint/types': 8.32.0
|
||||
'@typescript-eslint/typescript-estree': 8.32.0(typescript@5.8.3)
|
||||
'@typescript-eslint/visitor-keys': 8.32.0
|
||||
debug: 4.4.0
|
||||
eslint: 9.26.0(jiti@2.4.2)
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/scope-manager@8.31.1':
|
||||
'@typescript-eslint/scope-manager@8.32.0':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.31.1
|
||||
'@typescript-eslint/visitor-keys': 8.31.1
|
||||
'@typescript-eslint/types': 8.32.0
|
||||
'@typescript-eslint/visitor-keys': 8.32.0
|
||||
|
||||
'@typescript-eslint/type-utils@8.31.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)':
|
||||
'@typescript-eslint/type-utils@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/typescript-estree': 8.31.1(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.31.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@typescript-eslint/typescript-estree': 8.32.0(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
debug: 4.4.0
|
||||
eslint: 9.26.0(jiti@2.4.2)
|
||||
ts-api-utils: 2.1.0(typescript@5.8.3)
|
||||
@ -2202,12 +2215,12 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/types@8.31.1': {}
|
||||
'@typescript-eslint/types@8.32.0': {}
|
||||
|
||||
'@typescript-eslint/typescript-estree@8.31.1(typescript@5.8.3)':
|
||||
'@typescript-eslint/typescript-estree@8.32.0(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.31.1
|
||||
'@typescript-eslint/visitor-keys': 8.31.1
|
||||
'@typescript-eslint/types': 8.32.0
|
||||
'@typescript-eslint/visitor-keys': 8.32.0
|
||||
debug: 4.4.0
|
||||
fast-glob: 3.3.3
|
||||
is-glob: 4.0.3
|
||||
@ -2218,20 +2231,20 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/utils@8.31.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)':
|
||||
'@typescript-eslint/utils@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0(jiti@2.4.2))
|
||||
'@typescript-eslint/scope-manager': 8.31.1
|
||||
'@typescript-eslint/types': 8.31.1
|
||||
'@typescript-eslint/typescript-estree': 8.31.1(typescript@5.8.3)
|
||||
'@typescript-eslint/scope-manager': 8.32.0
|
||||
'@typescript-eslint/types': 8.32.0
|
||||
'@typescript-eslint/typescript-estree': 8.32.0(typescript@5.8.3)
|
||||
eslint: 9.26.0(jiti@2.4.2)
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/visitor-keys@8.31.1':
|
||||
'@typescript-eslint/visitor-keys@8.32.0':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.31.1
|
||||
'@typescript-eslint/types': 8.32.0
|
||||
eslint-visitor-keys: 4.2.0
|
||||
|
||||
accepts@2.0.0:
|
||||
@ -3183,11 +3196,11 @@ snapshots:
|
||||
media-typer: 1.1.0
|
||||
mime-types: 3.0.1
|
||||
|
||||
typescript-eslint@8.31.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3):
|
||||
typescript-eslint@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3):
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 8.31.1(@typescript-eslint/parser@8.31.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@typescript-eslint/parser': 8.31.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.31.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@typescript-eslint/eslint-plugin': 8.32.0(@typescript-eslint/parser@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@typescript-eslint/parser': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
eslint: 9.26.0(jiti@2.4.2)
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
|
@ -6,7 +6,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<body data-sveltekit-preload-data="hover" class="bg-gray-100">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1 +0,0 @@
|
||||
// place files you want to import through the `$lib` alias in this folder.
|
BIN
src/lib/linkedin.jpg
Normal file
BIN
src/lib/linkedin.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 88 KiB |
@ -4,4 +4,6 @@
|
||||
let { children } = $props();
|
||||
</script>
|
||||
|
||||
{@render children()}
|
||||
<div class="mx-4 my-8">
|
||||
{@render children()}
|
||||
</div>
|
||||
|
@ -1,2 +1,26 @@
|
||||
<h1>Welcome to SvelteKit</h1>
|
||||
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
|
||||
<script lang="ts">
|
||||
import JobCard from './JobCard.svelte';
|
||||
import PageHeader from './PageHeader.svelte';
|
||||
import { qiDescription, qiAccomplish } from './qiData';
|
||||
import { rannesDescription, rannesAccomplish } from './rannesDevData';
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
<PageHeader />
|
||||
<JobCard
|
||||
title="Full Stack Developer"
|
||||
company="Quantified Impacts"
|
||||
start="Aug. 2024"
|
||||
end="Present"
|
||||
jobDescription={qiDescription}
|
||||
accomplishments={qiAccomplish}
|
||||
/>
|
||||
<JobCard
|
||||
title="Owner"
|
||||
company="Rannes.dev"
|
||||
start="Dec. 2024"
|
||||
end="Present"
|
||||
jobDescription={rannesDescription}
|
||||
accomplishments={rannesAccomplish}
|
||||
/>
|
||||
</div>
|
||||
|
7
src/routes/Badge.svelte
Normal file
7
src/routes/Badge.svelte
Normal file
@ -0,0 +1,7 @@
|
||||
<script lang="ts">
|
||||
let { children } = $props();
|
||||
</script>
|
||||
|
||||
<div class="rounded-full bg-gray-200 px-2 py-1 text-sm text-gray-600">
|
||||
{@render children()}
|
||||
</div>
|
7
src/routes/Card.svelte
Normal file
7
src/routes/Card.svelte
Normal file
@ -0,0 +1,7 @@
|
||||
<script lang="ts">
|
||||
let { children } = $props();
|
||||
</script>
|
||||
|
||||
<div class="rounded-md bg-white px-8 py-6 shadow-md">
|
||||
{@render children()}
|
||||
</div>
|
40
src/routes/JobCard.svelte
Normal file
40
src/routes/JobCard.svelte
Normal file
@ -0,0 +1,40 @@
|
||||
<script lang="ts">
|
||||
import Badge from './Badge.svelte';
|
||||
import Card from './Card.svelte';
|
||||
import type { Accomplishment } from './types';
|
||||
|
||||
type ComponentProps = {
|
||||
title: string;
|
||||
company: string;
|
||||
start: string;
|
||||
end: string;
|
||||
jobDescription: string;
|
||||
accomplishments: Accomplishment[];
|
||||
};
|
||||
let { title, company, start, end, jobDescription, accomplishments }: ComponentProps = $props();
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
<div class="flex items-center gap-4">
|
||||
<h2 class="mb-2 text-2xl tracking-tight">{title} @ {company}</h2>
|
||||
<p class="text-sm text-slate-400">{start} - {end}</p>
|
||||
</div>
|
||||
<h3 class="mt-6 text-2xl">Job Description</h3>
|
||||
<p class="mt-4">
|
||||
{jobDescription}
|
||||
</p>
|
||||
<h3 class="mt-6 text-2xl">Accomplishments</h3>
|
||||
<ul class="mt-4 list-inside list-disc">
|
||||
{#each accomplishments as accomplishment, i (i)}
|
||||
<li class="mt-4 text-xl">
|
||||
<span>{accomplishment.title}</span>
|
||||
<p class="ml-5 text-base">{accomplishment.description}</p>
|
||||
<div class="mt-2 ml-5 flex gap-2">
|
||||
{#each accomplishment.tags as tag, i (`${tag}-${i}`)}
|
||||
<Badge>{tag}</Badge>
|
||||
{/each}
|
||||
</div>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</Card>
|
35
src/routes/PageHeader.svelte
Normal file
35
src/routes/PageHeader.svelte
Normal file
@ -0,0 +1,35 @@
|
||||
<script lang="ts">
|
||||
import { AtSign, Github, Globe, Linkedin } from '@lucide/svelte';
|
||||
import Card from './Card.svelte';
|
||||
import linkedInImg from '$lib/linkedin.jpg';
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
<div class="flex justify-between">
|
||||
<div class="my-4 flex flex-col justify-between gap-2">
|
||||
<div>
|
||||
<h1 class="text-4xl tracking-tight">Developer Resume For Christian Rannes</h1>
|
||||
<h2 class="text-xl text-slate-400">
|
||||
Full Stack Developer Passionate about infrastructure, DevOps and Developer Experience
|
||||
</h2>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<a href="https://www.linkedin.com/in/christian-rannes/">
|
||||
<Linkedin />
|
||||
</a>
|
||||
<a href="mailto:christian@rannes.dev">
|
||||
<AtSign />
|
||||
</a>
|
||||
<a href="http://rannes.dev">
|
||||
<Globe />
|
||||
</a>
|
||||
<a href="https://github.com/ChrQR">
|
||||
<Github />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex min-w-44 items-center">
|
||||
<img src={linkedInImg} alt="a happy guy" class="h-44 w-44 rounded-full shadow-sm" />
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
49
src/routes/qiData.ts
Normal file
49
src/routes/qiData.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import type { Accomplishment } from './types';
|
||||
|
||||
export const qiDescription =
|
||||
'As a Full Stack Developer at Quantified Impacts I have touched every part of our code, from infrastructure and CI/CD to our Frontend in react/typescript and our backend in Django/Python. I am fast at learning new things, and now to tackle challenges, and come up with fast, durable and scaleable solutions. When we need to research or develop POCs for new features, I am often assigned the lead for these tasks. ';
|
||||
|
||||
export const qiAccomplish: Accomplishment[] = [
|
||||
{
|
||||
title: 'Planned and facilitated maturation of infrastructure.',
|
||||
description:
|
||||
'When I started with Quantified Impacts we had our application running in two container apps, and a postgresql db, which was all exposed to the world wide web. I planned out our new infrastructure and hired a consultant to do the initial implementation in terraform, securing all services in virtual networks, connected with private end-points and accesible only through Azure Frontdoor. This is all declared using Terraform, so we can easily spin up another environment.',
|
||||
tags: ['Terraform', 'Azure']
|
||||
},
|
||||
{
|
||||
title: 'Implemented CI/CD Pipeline',
|
||||
description:
|
||||
"As we're a small team that wants to get our newest features out to our users as fast as possible, I set up a build and release pipeline using github actions.",
|
||||
tags: ['Github Actions', 'Azure']
|
||||
},
|
||||
{
|
||||
title: 'External API v1',
|
||||
description:
|
||||
'I built our initial external api as an application in our Django backend. It is used by our largest clients, who are making hundreds of thousands requests overnight. The API has full test coverage of unit tests and End2End tests written i pytest.',
|
||||
tags: ['Python', 'Django', 'REST']
|
||||
},
|
||||
{
|
||||
title: 'Redesign of our datamodels and database',
|
||||
description:
|
||||
'In January started planning a big rewrite of our backend and data models, to facilitate millions of carbon footprint calculations, storing calculation parameters, history and changelog for all objects.',
|
||||
tags: ['Postgresql', 'Django', 'Python']
|
||||
},
|
||||
{
|
||||
title: 'Migration of frontend to React Router 7 framework and SSR',
|
||||
description:
|
||||
'After a big rewrite of our backend, we decided to move to the newest version of React Router and use it as framework, which required an almost full rewrite of our frontend. While rewriting the frontend we also adopted Shadcn for ui components and tailwindcss for styling.',
|
||||
tags: ['React Router', 'React', 'typescript', 'Tailwind']
|
||||
},
|
||||
{
|
||||
title: 'External API v2',
|
||||
description:
|
||||
'The second iteration of our external API is written in FastAPI for fast development speed, and better performance compared to Django.',
|
||||
tags: ['FastAPI', 'Pydantic', 'Python', 'REST']
|
||||
},
|
||||
{
|
||||
title: 'Data fetching service from OKOBAUDAT',
|
||||
description:
|
||||
'A container job (Cron job) that fetches thousands of EPD reports from OKOBAUDAT every night, transform them to fit our data models, and inserts or update them in our database. The service is written in Golang.',
|
||||
tags: ['Golang', 'Azure', 'Cron Jobs']
|
||||
}
|
||||
];
|
19
src/routes/rannesDevData.ts
Normal file
19
src/routes/rannesDevData.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import type { Accomplishment } from './types';
|
||||
|
||||
export const rannesDescription =
|
||||
'As I got a request for a web site, and another for a code review I took the opportunity to start a little consultant business. I develop solutions and web sites for restaurants, and provide technical consulting for early stage start ups. My production applications are deployed to a k3s cluster that are running on a couple of Hetzner vps.';
|
||||
|
||||
export const rannesAccomplish: Accomplishment[] = [
|
||||
{
|
||||
title: 'Developed, Deployed and maintaining Calma.dk',
|
||||
description:
|
||||
'The web page is developed in Svelte with integrated CMS (Sanity.io) which allows the client to customize all text, and menus on the page. I also wrote a program in Golang which parses their winelist from an excel sheet (their stock take list), and uploads it to a s3 bucket from where its served to the user on the web page. This enables the client to make instant changes to their website, including their winelist. The page is built mobile first, and scales for all devices. It is deployed to my k3s cluster in hetzner',
|
||||
tags: ['Svelte', 'Sveltekit', 'AWS', 'k3s', 'Object Storage', 'CMS']
|
||||
},
|
||||
{
|
||||
title: 'Developed, deployed and maintaining Sauerwine.dk',
|
||||
description:
|
||||
'The web page is developed in Svelte and integrated with CMS (Sanity.io) so the client can change all text content on the web page. It is deployed to my k3s cluster in hetzner.',
|
||||
tags: ['Svelte', 'Sveltekit', 'k3s', 'CMS']
|
||||
}
|
||||
];
|
5
src/routes/types.ts
Normal file
5
src/routes/types.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export type Accomplishment = {
|
||||
title: string;
|
||||
description: string;
|
||||
tags: string[];
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user