Compare commits

...

7 Commits

Author SHA1 Message Date
d35521b383 Merge pull request 'Revamped landing page and mobile nav' (#7) from new-landing into main
All checks were successful
Vercel Production Deployment / Deploy-Production (push) Successful in 1m30s
Reviewed-on: #7
2024-05-20 22:23:19 +00:00
55de73c6b0 imports
All checks were successful
Vercel Preview Deployment / Deploy-Preview (push) Successful in 1m32s
2024-05-21 00:21:19 +02:00
f914ab7935 added hero
All checks were successful
Vercel Preview Deployment / Deploy-Preview (push) Successful in 1m30s
2024-05-21 00:19:00 +02:00
4c93cff666 Finished with the layout for now!
All checks were successful
Vercel Preview Deployment / Deploy-Preview (push) Successful in 2m0s
2024-05-20 23:59:07 +02:00
03970bbd95 finished bottom nav (for now)
All checks were successful
Vercel Preview Deployment / Deploy-Preview (push) Successful in 1m56s
2024-05-20 23:47:53 +02:00
fc4044ecd9 removed marquee on mobile and replaced with carousel
All checks were successful
Vercel Preview Deployment / Deploy-Preview (push) Successful in 2m19s
2024-05-20 22:55:23 +02:00
bbc7c2e365 working on bottom nav
All checks were successful
Vercel Preview Deployment / Deploy-Preview (push) Successful in 2m10s
2024-05-20 20:26:59 +02:00
14 changed files with 270 additions and 85 deletions

View File

@ -3,13 +3,19 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" /> <link rel="icon" href="%sveltekit.assets%/favicon.png" />
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Josefin+Sans:ital,wght@0,100..700;1,100..700&display=swap" rel="stylesheet"> <link
href="https://fonts.googleapis.com/css2?family=Josefin+Sans:ital,wght@0,100..700;1,100..700&display=swap"
rel="stylesheet"
/>
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head% %sveltekit.head%
</head> </head>
<body data-sveltekit-preload-data="hover" class="bg-stone-200 dark:bg-primary-900 text-primary-900 dark:text-stone-200 font-jose font-light"> <body
data-sveltekit-preload-data="hover"
class="bg-stone-200 dark:bg-primary-900 text-primary-900 dark:text-stone-200 font-jose font-light"
>
<div style="display: contents">%sveltekit.body%</div> <div style="display: contents">%sveltekit.body%</div>
</body> </body>
</html> </html>

View File

@ -0,0 +1,51 @@
<script>
import { BottomNav, BottomNavItem, Button, ButtonGroup } from 'flowbite-svelte';
import {
HomeSolid,
ProfileCardOutline,
ImageOutline,
MobilePhoneOutline
} from 'flowbite-svelte-icons';
import { writable } from 'svelte/store';
let activeBtn = writable('');
function handleNavItemClick(btnName) {
activeBtn.set(btnName);
}
</script>
{#if $activeBtn === 'projects'}
<ButtonGroup class="fixed md:hidden bottom-20 flex justify-center w-full">
<Button href="/projects/svelte" outline class="flex-col backdrop-blur ">Svelte</Button>
<Button href="/projects/nextjs" outline class="flex-col backdrop-blur">Next.js</Button>
<Button href="/projects/homelab" outline class="flex-col backdrop-blur">Homelab</Button>
</ButtonGroup>
{/if}
<BottomNav
position="fixed"
classInner="grid-cols-4"
outerClass="md:hidden w-full z-50 border-gray-200 dark:bg-slate-900 dark:border-gray-600"
>
<BottomNavItem btnName="home" href="/" on:click={() => handleNavItemClick('home')}>
<HomeSolid
class="w-6 h-6 mb-1 text-gray-500 dark:text-gray-400 group-hover:text-primary-600 dark:group-hover:text-primary-500"
/>
</BottomNavItem>
<BottomNavItem btnName="whoami" href="/about" on:click={() => handleNavItemClick('whoami')}>
<ProfileCardOutline
class="w-6 h-6 mb-1 text-gray-500 dark:text-gray-400 group-hover:text-primary-600 dark:group-hover:text-primary-500"
/>
</BottomNavItem>
<BottomNavItem btnName="projects" on:click={() => handleNavItemClick('projects')}>
<ImageOutline
class="w-6 h-6 mb-1 text-gray-500 dark:text-gray-400 group-hover:text-primary-600 dark:group-hover:text-primary-500"
/>
</BottomNavItem>
<BottomNavItem btnName="contact" href="/contact" on:click={() => handleNavItemClick('contact')}>
<MobilePhoneOutline
class="w-6 h-6 mb-1 text-gray-500 dark:text-gray-400 group-hover:text-primary-600 dark:group-hover:text-primary-500"
/>
</BottomNavItem>
</BottomNav>

View File

@ -0,0 +1,17 @@
<script>
import { Marquee } from 'flowbite-svelte';
import { projects } from '$lib/projects.js';
import VendorIcon from '../ProjectCard/VendorIcon.svelte';
const allVendors = Array.from(
new Map(
projects.flatMap((project) => project.vendors).map((vendor) => [vendor.name, vendor])
).values()
);
</script>
<div class="p-4 bg-stone-200 dark:bg-slate-800 rounded-xl flex items-center overflow-scroll gap-4">
{#each allVendors as vendor}
<VendorIcon {...vendor} />
{/each}
</div>

View File

@ -0,0 +1,21 @@
<script>
import { Marquee } from 'flowbite-svelte';
import { projects } from '$lib/projects.js';
import VendorIcon from '../ProjectCard/VendorIcon.svelte';
const allVendors = Array.from(
new Map(
projects.flatMap((project) => project.vendors).map((vendor) => [vendor.name, vendor])
).values()
);
</script>
<Marquee
speed={0.5}
hoverSpeed={0.25}
class="py-4 bg-stone-200 dark:bg-slate-800 rounded-xl flex items-center"
>
{#each allVendors as vendor}
<VendorIcon {...vendor} />
{/each}
</Marquee>

View File

@ -7,6 +7,6 @@
<a href={url}> <a href={url}>
<div class="flex flex-col justify-center h-16 hover:scale-110"> <div class="flex flex-col justify-center h-16 hover:scale-110">
<img src={img} alt={name} class="min-h-12 max-w-12 self-center" /> <img src={img} alt={name} class="min-h-12 max-w-12 self-center" />
<p>{name}</p> <p class="text-slate-900 dark:text-stone-200 font-normal">{name}</p>
</div> </div>
</a> </a>

48
src/lib/TopNav.svelte Normal file
View File

@ -0,0 +1,48 @@
<script>
import {
Navbar,
NavBrand,
NavLi,
NavUl,
Dropdown,
DropdownItem,
DarkMode
} from 'flowbite-svelte';
import { ChevronDownOutline } from 'flowbite-svelte-icons';
import logo from '$lib/logo.png';
import { page } from '$app/stores';
$: activeUrl = $page.url.pathname;
</script>
<Navbar class="bg-transparent">
<NavBrand href="/">
<img src={logo} class="me-3 h-6 sm:h-9" alt="Flowbite Logo" />
<span class="self-center whitespace-nowrap text-xl font-semibold dark:text-stone-200"
>rannes.dev</span
>
</NavBrand>
<div class="flex">
<DarkMode btnClass="block sm:hidden" />
</div>
<NavUl class="md:flex-row" {activeUrl}>
<NavLi href="/">home</NavLi>
<NavLi href="/about">whoami</NavLi>
<NavLi class="cursor-pointer">
projects<ChevronDownOutline class="w-6 h-6 text-primary-800 dark:text-stone-200 inline" />
</NavLi>
<Dropdown
{activeUrl}
activeClass="font-bold text-primary-800 dark:text-stone-200"
class="w-44 z-20"
>
<DropdownItem href="/projects/svelte">svelte</DropdownItem>
<DropdownItem href="/projects/nextjs">nextjs</DropdownItem>
<DropdownItem href="/projects/homelab">homelab</DropdownItem>
</Dropdown>
<NavLi href="/contact">contact</NavLi>
<NavLi class="hidden sm:block">
<DarkMode btnClass="p-0" />
</NavLi>
</NavUl>
</Navbar>

BIN
src/lib/images/hero.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

View File

@ -1,55 +1,24 @@
<script> <script>
import {
Navbar,
NavBrand,
NavLi,
NavUl,
NavHamburger,
Dropdown,
DropdownItem,
DarkMode
} from 'flowbite-svelte';
import { ChevronDownOutline, HomeOutline } from 'flowbite-svelte-icons';
import '../app.css'; import '../app.css';
import CloudflareAnalytics from '$lib/CloudflareAnalytics.svelte'; import CloudflareAnalytics from '$lib/CloudflareAnalytics.svelte';
import logo from '$lib/logo.png'; import BottomNavigation from '../lib/BottomNavigation.svelte';
import { page } from '$app/stores'; import TopNav from '../lib/TopNav.svelte';
$: activeUrl = $page.url.pathname; let activeBtn = 'home';
function handleNavItemClick(btnName) {
activeBtn = btnName;
}
$: activeBtn = activeBtn === 'projects';
</script> </script>
<CloudflareAnalytics /> <CloudflareAnalytics />
<Navbar class="bg-transparent"> <TopNav />
<NavBrand href="/"> <div class="px-2 sm:px-0 mx-auto max-w-xs sm:max-w-md md:max-w-3xl text-center mb-20 md:mb-0">
<img src={logo} class="me-3 h-6 sm:h-9" alt="Flowbite Logo" />
<span class="self-center whitespace-nowrap text-xl font-semibold dark:text-stone-200"
>rannes.dev</span
>
</NavBrand>
<div class="flex">
<DarkMode btnClass="block sm:hidden" />
<NavHamburger />
</div>
<NavUl {activeUrl}>
<NavLi href="/">home</NavLi>
<NavLi href="/about">whoami</NavLi>
<NavLi class="cursor-pointer">
projects<ChevronDownOutline class="w-6 h-6 text-primary-800 dark:text-stone-200 inline" />
</NavLi>
<Dropdown class="w-44 z-20">
<DropdownItem href="/projects/svelte">svelte</DropdownItem>
<DropdownItem href="/projects/nextjs">nextjs</DropdownItem>
<DropdownItem href="/projects/homelab">homelab</DropdownItem>
</Dropdown>
<NavLi href="/contact">contact</NavLi>
<NavLi class="hidden sm:block">
<DarkMode btnClass="p-0" />
</NavLi>
</NavUl>
</Navbar>
<div class="px-2 sm:px-0 mx-auto max-w-xs sm:max-w-md md:max-w-3xl text-center">
<slot /> <slot />
</div> </div>
<footer class="mt-12 text-center"> <BottomNavigation />
<p class="text-sm text-stone-400">built by christian rannes 2024</p> <footer class="">
<div class="hidden md:block text-sm text-stone-400 mt-12 text-center">
<p>built by christian rannes 2024</p>
</div>
</footer> </footer>

View File

@ -1,11 +1,43 @@
<div class="main-container text-center"> <script>
<h1 class="text-xl mb-2">Welcome to my corner of the internet</h1> import VendorMarquee from '$lib/Landing/VendorMarquee.svelte';
<p> import VendorCarousel from '../lib/Landing/VendorCarousel.svelte';
You most likely ended up here after listening to me rambling about the wonders of self hosted import { Heading, Mark } from 'flowbite-svelte';
services, and how life would be much easier if we could just containerize everything. import portfolio from '$lib/images/portfolio.png';
</p> import hero from '$lib/images/hero.webp';
<p class="italic text-sm mt-8">
This page is my initial svelte project to try out the framework, and at the time of writing const images = [
(24th April 2024) many pages are still lacking content. {
title: '/projects/nextjs',
image: portfolio
}
];
</script>
<div class="text-center text-xl">
<div class="flex my-4 gap-4">
<Heading tag="h1" class="md:text-right">father by day <Mark>developer</Mark> by night</Heading>
<img
src={hero}
alt=""
class="hidden md:block rounded-xl max-h-36 w-auto shadow-inner border border-slate-700"
/>
</div>
<h2 class="py-2">
welcome to my space. For now it is used to document my learnings and share my projects. It might
expand over time.
</h2>
<p class="py-2">
I like to explore many different technologies and frameworks mostly surrounding web development
and infrastructure.
</p> </p>
<div class="hidden md:block py-2">
<VendorMarquee />
</div>
<div class="md:hidden py-2">
<VendorCarousel />
</div>
<h2 class="py-2">
You can see some of my web dev projects and a small write-up on my homelab in the projects
section.
</h2>
</div> </div>

View File

@ -1,17 +1,36 @@
<script> <script>
import migImg from "$lib/images/mig.jpg" import migImg from '$lib/images/mig.jpg';
import osImg from "$lib/images/os.webp" import osImg from '$lib/images/os.webp';
import { fade } from "svelte/transition"; import { fade } from 'svelte/transition';
import PageHeader from '$lib/PageHeader.svelte';
const title = 'Life is good in Copenhagen';
</script> </script>
<div class="page-container" in:fade> <div class="page-container" in:fade>
<h1 class="text-xl mb-4">Life is good in Copenhagen</h1> <PageHeader {title} />
<div class="article-container md:flex mb-4 items-center text-left"> <div class="article-container md:flex mb-4 items-center text-left">
<p class="">I live in Copenhagen with my partner and children near the water. We love going on expeditions around the city in our cargo bike, or on my electrical skateboard. <p class="">
When we're not outside I spend a lot of time fiddling around with my homelab, and development projects. You can read more about my projects and homelab under the homelab and portfolio nav. I live in Copenhagen with my partner and children near the water. We love going on expeditions
around the city in our cargo bike, or on my electrical skateboard. When we're not outside I
spend a lot of time fiddling around with my homelab, and development projects. You can read
more about my projects and homelab under the homelab and portfolio nav.
</p> </p>
<img class="rounded-2xl xl:ml-4 md:w-auto md:h-52 md:ml-0 md:mt-4 sm:ml-0 sm:mt-4 sm:w-full" src={migImg} alt="crazy man"/> <img
class="rounded-2xl xl:ml-4 md:w-auto md:h-52 md:ml-0 md:mt-4 sm:ml-0 sm:mt-4 sm:w-full"
src={migImg}
alt="crazy man"
/>
</div> </div>
<p class="mb-4 ">I work in recruitment, and I specialise in building product teams for start ups and scale ups for a small recruitment agency called <a class="underline font-semibold" href="https://www.adveniopeople.com">Advenio People</a></p> <p class="mb-4">
<img src={osImg} alt="A happy man and a beautiful woman both wearing facemasks." class="rounded-full w-1/2 h-auto m-auto"> I work in recruitment, and I specialise in building product teams for start ups and scale ups
for a small recruitment agency called <a
class="underline font-semibold"
href="https://www.adveniopeople.com">Advenio People</a
>
</p>
<img
src={osImg}
alt="A happy man and a beautiful woman both wearing facemasks."
class="rounded-full w-1/2 h-auto m-auto"
/>
</div> </div>

View File

@ -1 +1,13 @@
<h1>Under development</h1> <script>
import PageHeader from '$lib/PageHeader.svelte';
const title = 'Coming soon!';
</script>
<PageHeader {title} />
<p class="py-6">
For now you can hit me up on <a
class="font-normal underline"
href="https://www.linkedin.com/in/christian-rannes/"
target="_blank">linkedin</a
>
</p>

View File

@ -3,10 +3,12 @@
import asrockImg from '$lib/images/asrock.webp'; import asrockImg from '$lib/images/asrock.webp';
import rackImg from '$lib/images/rack.webp'; import rackImg from '$lib/images/rack.webp';
import { fade } from 'svelte/transition'; import { fade } from 'svelte/transition';
import PageHeader from '$lib/PageHeader.svelte';
const title = 'Homelab';
</script> </script>
<div in:fade > <div in:fade>
<h1 class="text-2xl mb-4">Homelab</h1> <PageHeader {title} />
<div class="content text-left"> <div class="content text-left">
<article> <article>
@ -24,9 +26,9 @@
maker-culture. maker-culture.
</p> </p>
<p> <p>
My lab started in 2020, when I wanted to set up my own DNS server at home, to add My lab started in 2020, when I wanted to set up my own DNS server at home, to add network
network wide ad-block (Pihole). As I learned more about Linux and containerization I quickly wide ad-block (Pihole). As I learned more about Linux and containerization I quickly got
got drawn into the hobby of self-hosting web-services. drawn into the hobby of self-hosting web-services.
</p> </p>
<p> <p>
Raspberry Pi's are great, but but the computing resources are limited compared to a x86, so Raspberry Pi's are great, but but the computing resources are limited compared to a x86, so
@ -80,9 +82,11 @@
<p> <p>
The homelab is also connected to two 3D printers, that are running open source custom The homelab is also connected to two 3D printers, that are running open source custom
firmware (klipper) and controlled through a web interface (Mainsail) from any device in the firmware (klipper) and controlled through a web interface (Mainsail) from any device in the
local network. I started with a Ender3, and during my parental leave last year I built <a class="underline" href="https://vorondesign.com/voron0.2">Voron 0.2</a>. The parts are all sourced, and the local network. I started with a Ender3, and during my parental leave last year I built <a
rest of the parts are 3D printed in ABS+. It took me roughly 40 hours to build it and class="underline"
calibrate it. href="https://vorondesign.com/voron0.2">Voron 0.2</a
>. The parts are all sourced, and the rest of the parts are 3D printed in ABS+. It took me
roughly 40 hours to build it and calibrate it.
</p> </p>
<h2 class="text-xl text-center mt-4">OS</h2> <h2 class="text-xl text-center mt-4">OS</h2>
<p> <p>
@ -116,8 +120,7 @@
<li>Portfolio web page</li> <li>Portfolio web page</li>
<p class="italic pl-4"> <p class="italic pl-4">
This is my portfolio page, which will soon be available at rannes.dev. I'm using This is my portfolio page, which will soon be available at rannes.dev. I'm using
svelte/sveltekit. It is svelte/sveltekit. It is currently not exposed to the internet as I am still building it.
currently not exposed to the internet as I am still building it.
</p> </p>
<li>Crowdsec Security Engine</li> <li>Crowdsec Security Engine</li>
<li>Prometheus</li> <li>Prometheus</li>
@ -152,9 +155,16 @@
</p> </p>
<p>This VM has the SATA controller passed through, for full control of the HDD's.</p> <p>This VM has the SATA controller passed through, for full control of the HDD's.</p>
<h3 class="text-lg text-center mt-4">Development server</h3> <h3 class="text-lg text-center mt-4">Development server</h3>
<p>This vm is my development server. It's running a act_runner paired up with Gitea to build my portfolio project, dockerize it and push it to my container registry. The application then deployed in the staging environment for a last check.</p> <p>
This vm is my development server. It's running a act_runner paired up with Gitea to build my
portfolio project, dockerize it and push it to my container registry. The application then
deployed in the staging environment for a last check.
</p>
<h2 class="text-xl text-center mt-4">CI/CD</h2> <h2 class="text-xl text-center mt-4">CI/CD</h2>
<p>I use Gitea Actions which is similar to Github Actions. I will post a guide soon how to set up CI for your svelte-docker project with Gitea Actions.</p> <p>
I use Gitea Actions which is similar to Github Actions. I will post a guide soon how to set
up CI for your svelte-docker project with Gitea Actions.
</p>
</article> </article>
</div> </div>
</div> </div>