Compare commits
43 Commits
Author | SHA1 | Date | |
---|---|---|---|
369e97af41 | |||
754ff5d9a9 | |||
351cac00b3 | |||
11c85e324e | |||
5a418428d3 | |||
3d4c9c2214 | |||
10262c4b7a | |||
57ea8374a5 | |||
e9e1cabd11 | |||
4c1ec680a9 | |||
4f826e8964 | |||
3ddce86e64 | |||
61aa06310c | |||
03195017c5 | |||
fc3f4fdad4 | |||
fc42f31fb0 | |||
|
e56b3a001e | ||
|
13711618b7 | ||
04980a38af | |||
385ad20c82 | |||
761652f46d | |||
|
8f6b1af8ad | ||
|
90c8d30e3f | ||
|
ad9128acea | ||
|
5f9235c9dc | ||
|
3b2702af36 | ||
|
f999b9a92c | ||
|
35c940bef7 | ||
|
7aa6898a93 | ||
9d77c9db2a | |||
528eb8fb2e | |||
14e73d61ef | |||
|
d10fe280a5 | ||
|
5ea5774042 | ||
|
3c82fb43d8 | ||
|
c7071ab583 | ||
|
125d70d62e | ||
|
357634d3f0 | ||
|
bd4b85c874 | ||
7efa375427 | |||
358d6b91c6 | |||
92d4be91df | |||
0f5fc27371 |
58
.gitea/workflows/release-image-gitea.yml
Normal file
58
.gitea/workflows/release-image-gitea.yml
Normal file
@@ -0,0 +1,58 @@
|
||||
name: release-image-gitea
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 0.*
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Create Kubeconfig
|
||||
run: |
|
||||
mkdir $HOME/.kube
|
||||
echo "${{ secrets.KUBECONFIG_BUILDX }}" > $HOME/.kube/config
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
driver: kubernetes
|
||||
driver-opts: |
|
||||
namespace=gitea
|
||||
qemu.install=true
|
||||
|
||||
- name: Available Platforms
|
||||
run: echo ${{ steps.buildx.outputs.platforms }}
|
||||
|
||||
- name: Login to Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ vars.REPOSITORY_HOST }}
|
||||
username: ${{ gitea.actor }}
|
||||
password: ${{ secrets.REPOSITORY_TOKEN }}
|
||||
|
||||
- name: Extract Metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
images: ${{ vars.REPOSITORY_HOST }}/${{ gitea.repository }}
|
||||
|
||||
- name: Build and Push Image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: linux/amd64
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
file: ./Dockerfile
|
58
.gitea/workflows/release-image-harbor.yml
Normal file
58
.gitea/workflows/release-image-harbor.yml
Normal file
@@ -0,0 +1,58 @@
|
||||
name: release-image-harbor
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 0.*
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Create Kubeconfig
|
||||
run: |
|
||||
mkdir $HOME/.kube
|
||||
echo "${{ secrets.KUBECONFIG_BUILDX }}" > $HOME/.kube/config
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
driver: kubernetes
|
||||
driver-opts: |
|
||||
namespace=gitea
|
||||
qemu.install=true
|
||||
|
||||
- name: Available Platforms
|
||||
run: echo ${{ steps.buildx.outputs.platforms }}
|
||||
|
||||
- name: Login to Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ vars.REGISTRY_HOST }}
|
||||
username: ${{ vars.REGISTRY_USER }}
|
||||
password: ${{ secrets.REGISTRY_SECRET }}
|
||||
|
||||
- name: Extract Metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
images: ${{ vars.REGISTRY_HOST }}/images
|
||||
|
||||
- name: Build and Push Image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: linux/amd64
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
file: ./Dockerfile
|
@@ -1,2 +0,0 @@
|
||||
# This file is processed by Renovate bot so that it creates a PR on new major Renovate versions
|
||||
FROM renovate/renovate:38
|
44
.github/renovate.json
vendored
44
.github/renovate.json
vendored
@@ -1,44 +0,0 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:recommended",
|
||||
"mergeConfidence:all-badges",
|
||||
":rebaseStalePrs"
|
||||
],
|
||||
"timezone": "US/Central",
|
||||
"schedule": [
|
||||
"every weekday"
|
||||
],
|
||||
"labels": [],
|
||||
"prHourlyLimit": 0,
|
||||
"prConcurrentLimit": 0,
|
||||
"packageRules": [
|
||||
{
|
||||
"description": "Disables for non major Renovate version",
|
||||
"matchPaths": [
|
||||
".github/renovate-update-notification/Dockerfile"
|
||||
],
|
||||
"matchUpdateTypes": [
|
||||
"minor",
|
||||
"patch",
|
||||
"pin",
|
||||
"digest",
|
||||
"rollback"
|
||||
],
|
||||
"enabled": false
|
||||
},
|
||||
{
|
||||
"description": "Generate for major Renovate version",
|
||||
"matchPaths": [
|
||||
".github/renovate-update-notification/Dockerfile"
|
||||
],
|
||||
"matchUpdateTypes": [
|
||||
"major"
|
||||
],
|
||||
"addLabels": [
|
||||
"upgrade"
|
||||
],
|
||||
"automerge": false
|
||||
}
|
||||
]
|
||||
}
|
45
.github/workflows/release-image.yml
vendored
45
.github/workflows/release-image.yml
vendored
@@ -1,45 +0,0 @@
|
||||
name: release-image
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 0.*
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
release-image:
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log into the container registry
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@60a0d343a0d8a18aedee9d34e62251f752153bdb
|
||||
with:
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@5cd11c3a4ced054e52742c5fd54dca954e0edd85
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
file: ./Dockerfile
|
4
.gitignore
vendored
4
.gitignore
vendored
@@ -23,5 +23,7 @@ pnpm-debug.log*
|
||||
# jetbrains setting folder
|
||||
.idea/
|
||||
|
||||
# vscode workspace
|
||||
# ide
|
||||
.vscode/
|
||||
site-profile.code-workspace
|
||||
.pre-commit-config.yaml
|
||||
|
@@ -1,7 +1,7 @@
|
||||
FROM node:20.16.0-alpine3.20 AS base
|
||||
FROM node:22.14.0-alpine3.20 AS base
|
||||
|
||||
LABEL version="0.4.0"
|
||||
LABEL description="Astro based website to use as a profile"
|
||||
LABEL version="0.6.6"
|
||||
LABEL description="Astro based website to use as a personal site"
|
||||
|
||||
ENV PNPM_HOME="/pnpm"
|
||||
ENV PATH="$PNPM_HOME:$PATH"
|
||||
|
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Alex Lebens
|
||||
Copyright (c) 2025 Alex Lebens
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
31
README.md
31
README.md
@@ -1 +1,30 @@
|
||||
# Profile
|
||||
# Astro Starter Kit: Portfolio
|
||||
|
||||
```sh
|
||||
pnpm create astro@latest -- --template portfolio
|
||||
```
|
||||
|
||||
[](https://stackblitz.com/github/withastro/astro/tree/latest/examples/portfolio)
|
||||
[](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/portfolio)
|
||||
[](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/portfolio/devcontainer.json)
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
|
||||

|
||||
|
||||
## 🧞 Commands
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
|
||||
| Command | Action |
|
||||
| :------------------------ | :----------------------------------------------- |
|
||||
| `pnpm install` | Installs dependencies |
|
||||
| `pnpm dev` | Starts local dev server at `localhost:4321` |
|
||||
| `pnpm build` | Build your production site to `./dist/` |
|
||||
| `pnpm preview` | Preview your build locally, before deploying |
|
||||
| `pnpm astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||
| `pnpm astro -- --help` | Get help using the Astro CLI |
|
||||
|
||||
## 👀 Want to learn more?
|
||||
|
||||
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
||||
|
@@ -3,7 +3,7 @@ import { defineConfig } from 'astro/config';
|
||||
import node from "@astrojs/node";
|
||||
|
||||
export default defineConfig({
|
||||
output: "hybrid",
|
||||
output: "static",
|
||||
adapter: node({
|
||||
mode: "standalone"
|
||||
})
|
||||
|
50
lib/directus.ts
Normal file
50
lib/directus.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { createDirectus, rest, } from '@directus/sdk';
|
||||
|
||||
type Global = {
|
||||
title: string;
|
||||
description: string;
|
||||
name: string;
|
||||
tagline: string;
|
||||
email: string;
|
||||
portrait: string;
|
||||
about: string;
|
||||
}
|
||||
|
||||
type About = {
|
||||
background: string;
|
||||
experience: string;
|
||||
education: string;
|
||||
certifications: string;
|
||||
}
|
||||
|
||||
type Skills = {
|
||||
skill_1: string;
|
||||
skill_1_description: string;
|
||||
skill_2: string;
|
||||
skill_2_description: string;
|
||||
skill_3: string;
|
||||
skill_3_description: string;
|
||||
}
|
||||
|
||||
export type Post = {
|
||||
slug: string;
|
||||
title: string;
|
||||
content: string;
|
||||
image: string;
|
||||
image_alt: string;
|
||||
published_date: string;
|
||||
tags: string[];
|
||||
}
|
||||
|
||||
type Schema = {
|
||||
global: Global;
|
||||
about: About;
|
||||
skills: Skills;
|
||||
posts: Post[];
|
||||
}
|
||||
|
||||
export const directus_url = "https://directus.alexlebens.dev"
|
||||
|
||||
const directus = createDirectus<Schema>(directus_url).with(rest());
|
||||
|
||||
export default directus;
|
15
package.json
15
package.json
@@ -1,19 +1,18 @@
|
||||
{
|
||||
"name": "site-profile",
|
||||
"type": "module",
|
||||
"version": "0.4.0",
|
||||
"version": "0.6.6",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro check && astro build",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/check": "^0.9.3",
|
||||
"@astrojs/node": "^8.3.3",
|
||||
"@directus/sdk": "^17.0.0",
|
||||
"astro": "^4.14.2",
|
||||
"typescript": "^5.5.4"
|
||||
"@astrojs/check": "^0.9.4",
|
||||
"@astrojs/node": "^9.1.3",
|
||||
"@directus/sdk": "^19.0.1",
|
||||
"astro": "^5.5.2",
|
||||
"typescript": "^5.8.2"
|
||||
}
|
||||
}
|
3090
pnpm-lock.yaml
generated
3090
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 3.5 MiB |
Binary file not shown.
Before Width: | Height: | Size: 188 KiB |
Binary file not shown.
Before Width: | Height: | Size: 38 KiB |
Binary file not shown.
Before Width: | Height: | Size: 20 KiB |
Binary file not shown.
Before Width: | Height: | Size: 21 KiB |
Binary file not shown.
Before Width: | Height: | Size: 27 KiB |
16
renovate.json
Normal file
16
renovate.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:recommended",
|
||||
"mergeConfidence:all-badges",
|
||||
":rebaseStalePrs"
|
||||
],
|
||||
"timezone": "US/Central",
|
||||
"schedule": [
|
||||
"every weekday"
|
||||
],
|
||||
"labels": [],
|
||||
"prHourlyLimit": 0,
|
||||
"prConcurrentLimit": 0,
|
||||
"packageRules": []
|
||||
}
|
@@ -1,11 +1,16 @@
|
||||
---
|
||||
import CallToAction from './CallToAction.astro';
|
||||
import Icon from './Icon.astro';
|
||||
|
||||
import directus from "../../lib/directus"
|
||||
import { readSingleton } from "@directus/sdk";
|
||||
|
||||
const global = await directus.request(readSingleton("global"));
|
||||
---
|
||||
|
||||
<aside>
|
||||
<h2>Interested in working together?</h2>
|
||||
<CallToAction href="mailto:alexander.lebens@gmail.com">
|
||||
<CallToAction href=`mailto:${global.email}`>
|
||||
Send Me a Message
|
||||
<Icon icon="paper-plane-tilt" size="1.2em" />
|
||||
</CallToAction>
|
||||
|
@@ -1,6 +1,11 @@
|
||||
---
|
||||
import Icon from './Icon.astro';
|
||||
const currentYear = new Date().getFullYear();
|
||||
|
||||
import directus from "../../lib/directus"
|
||||
import { readSingleton } from "@directus/sdk";
|
||||
|
||||
const global = await directus.request(readSingleton("global"));
|
||||
---
|
||||
|
||||
<footer>
|
||||
@@ -9,7 +14,7 @@ const currentYear = new Date().getFullYear();
|
||||
Designed & Developed in Minnesota with <a href="https://astro.build/">Astro</a>
|
||||
<Icon icon="rocket-launch" size="1.2em" />
|
||||
</p>
|
||||
<p>© {currentYear} Alex Lebens</p>
|
||||
<p>© {currentYear} {global.name}</p>
|
||||
</div>
|
||||
<p class="socials">
|
||||
<a href="https://github.com/alexlebens"> GitHub</a>
|
||||
|
@@ -1,14 +1,19 @@
|
||||
---
|
||||
import '../styles/global.css';
|
||||
|
||||
import directus from "../../lib/directus"
|
||||
import { readSingleton } from "@directus/sdk";
|
||||
|
||||
interface Props {
|
||||
title?: string | undefined;
|
||||
description?: string | undefined;
|
||||
}
|
||||
|
||||
const global = await directus.request(readSingleton("global"));
|
||||
|
||||
const {
|
||||
title = 'Alex Lebens',
|
||||
description = 'A profile of Alex Lebens',
|
||||
title = `${global.name}`,
|
||||
description = `A profile of ${global.name}`,
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
|
@@ -3,6 +3,9 @@ import Icon from './Icon.astro';
|
||||
import ThemeToggle from './ThemeToggle.astro';
|
||||
import type { iconPaths } from './IconPaths';
|
||||
|
||||
import directus from "../../lib/directus"
|
||||
import { readSingleton } from "@directus/sdk";
|
||||
|
||||
const textLinks: { label: string; href: string }[] = [
|
||||
{ label: 'Home', href: '/' },
|
||||
{ label: 'Projects', href: '/projects/' },
|
||||
@@ -13,13 +16,15 @@ const iconLinks: { label: string; href: string; icon: keyof typeof iconPaths }[]
|
||||
{ label: 'GitHub', href: 'https://github.com/alexlebens', icon: 'github-logo' },
|
||||
{ label: 'LinkedIn', href: 'https://www.linkedin.com/in/alexanderlebens', icon: 'linkedin-logo' },
|
||||
];
|
||||
|
||||
const global = await directus.request(readSingleton("global"));
|
||||
---
|
||||
|
||||
<nav>
|
||||
<div class="menu-header">
|
||||
<a href="/" class="site-title">
|
||||
<Icon icon="terminal-window" color="var(--accent-regular)" size="1.6em" gradient />
|
||||
Alex Lebens
|
||||
{global.name}
|
||||
</a>
|
||||
<menu-button>
|
||||
<template>
|
||||
|
@@ -1,16 +1,17 @@
|
||||
---
|
||||
import type { CollectionEntry } from 'astro:content';
|
||||
import type { Post } from '../../lib/directus';
|
||||
import { directus_url } from '../../lib/directus';
|
||||
|
||||
interface Props {
|
||||
project: CollectionEntry<'projects'>;
|
||||
posts: Post;
|
||||
}
|
||||
|
||||
const { data, slug } = Astro.props.project;
|
||||
const post: Post = Astro.props.posts;
|
||||
---
|
||||
|
||||
<a class="card" href={`/projects/${slug}`}>
|
||||
<span class="title">{data.title}</span>
|
||||
<img src={data.img} alt={data.img_alt || ''} loading="lazy" decoding="async" />
|
||||
<a class="card" href={`/projects/${post.slug}`}>
|
||||
<span class="title">{post.title}</span>
|
||||
<img src={`${directus_url}/assets/${post.image}?width=500`} alt={post.image_alt || ''} loading="lazy" decoding="async" />
|
||||
</a>
|
||||
|
||||
<style>
|
||||
|
@@ -1,22 +1,27 @@
|
||||
---
|
||||
import Icon from './Icon.astro';
|
||||
|
||||
import directus from "../../lib/directus"
|
||||
import { readSingleton } from "@directus/sdk";
|
||||
|
||||
const skills = await directus.request(readSingleton("skills"));
|
||||
---
|
||||
|
||||
<section class="box skills">
|
||||
<div class="stack gap-2 lg:gap-4">
|
||||
<Icon icon="cloud" color="var(--accent-regular)" size="2.5rem" gradient />
|
||||
<h2>AWS</h2>
|
||||
<p>Certified DevOps Engineer and former AWS Cloud Engineer skilled in deploying, managing, and architecting a wide range of AWS services.</p>
|
||||
<h2 set:html={skills.skill_1}/>
|
||||
<p set:html={skills.skill_1_description}/>
|
||||
</div>
|
||||
<div class="stack gap-2 lg:gap-4">
|
||||
<Icon icon="network" color="var(--accent-regular)" size="2.5rem" gradient />
|
||||
<h2>Kubernetes</h2>
|
||||
<p>My skills encompass Kubernetes administration and application development, validated by my CKA and CKAD certifications.</p>
|
||||
<h2 set:html={skills.skill_2}/>
|
||||
<p set:html={skills.skill_2_description}/>
|
||||
</div>
|
||||
<div class="stack gap-2 lg:gap-4">
|
||||
<Icon icon="strategy" color="var(--accent-regular)" size="2.5rem" gradient />
|
||||
<h2>GitOps</h2>
|
||||
<p>Hands-on experience leveraging a variety of IaC tools such as CloudFormation, CDK, Helm, and ArgoCD to streamline infrastructure provisioning and management across multiple projects.</p>
|
||||
<h2 set:html={skills.skill_3}/>
|
||||
<p set:html={skills.skill_3_description}/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
@@ -1,15 +0,0 @@
|
||||
import { defineCollection, z } from 'astro:content';
|
||||
|
||||
export const collections = {
|
||||
projects: defineCollection({
|
||||
type: 'content',
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
publishDate: z.coerce.date(),
|
||||
tags: z.array(z.string()),
|
||||
img: z.string(),
|
||||
img_alt: z.string().optional(),
|
||||
}),
|
||||
}),
|
||||
};
|
@@ -1,21 +0,0 @@
|
||||
---
|
||||
title: Placeholder
|
||||
publishDate: 2019-12-01 00:00:00
|
||||
img: /assets/stock-2.jpg
|
||||
img_alt: A bright pink sheet of paper used to wrap flowers curves in front of rich blue background
|
||||
description: |
|
||||
Placeholder
|
||||
tags:
|
||||
- Dev
|
||||
- Backend
|
||||
---
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur posuere commodo venenatis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nam non ligula vel metus efficitur hendrerit. In hac habitasse platea dictumst. Praesent et mauris ut mi dapibus semper. Curabitur tortor justo, efficitur sit amet pretium cursus, porta eget odio. Cras ac venenatis dolor. Donec laoreet posuere malesuada. Curabitur nec mi tempor, placerat leo sit amet, tincidunt est. Quisque pellentesque venenatis magna, eget tristique nibh pulvinar in. Vestibulum vitae volutpat arcu. Aenean ut malesuada odio, sit amet pellentesque odio. Suspendisse nunc elit, blandit nec hendrerit non, aliquet at magna. Donec id leo ut nulla sagittis sodales.
|
||||
|
||||
Integer vitae nibh elit. Suspendisse eget urna eu neque bibendum pharetra. Sed interdum lectus sem, in pulvinar magna dignissim vel. Quisque maximus at urna nec laoreet. Suspendisse potenti. Vestibulum rhoncus sem ut mi pellentesque, in vestibulum erat blandit. Aliquam sodales dui ac maximus consectetur. Duis quis est vehicula, imperdiet nisl nec, fermentum erat. Duis tortor diam, pharetra eu euismod in, vehicula non eros. Curabitur facilisis dui at erat ultrices gravida. In at nunc ultricies, pulvinar mi vel, sagittis mauris. Praesent pharetra posuere purus ac imperdiet. Nulla facilisi.
|
||||
|
||||
Sed pulvinar porttitor mi in ultricies. Etiam non dolor gravida eros pulvinar pellentesque et dictum ex. Proin eu ornare ligula, sed condimentum dui. Vivamus tincidunt tellus mi, sed semper ipsum pharetra a. Suspendisse sollicitudin at sapien nec volutpat. Etiam justo urna, laoreet ac lacus sed, ultricies facilisis dolor. Integer posuere, metus vel viverra gravida, risus elit ornare magna, id feugiat erat risus ullamcorper libero. Proin vitae diam auctor, laoreet lorem vitae, varius tellus.
|
||||
|
||||
Mauris sed eros in ex maximus volutpat. Suspendisse potenti. Donec lacinia justo consectetur sagittis tempor. Proin ullamcorper nisi vitae auctor rhoncus. Sed tristique aliquam augue. Pellentesque vitae fringilla ligula. Nulla arcu elit, efficitur eu nunc malesuada, eleifend tincidunt orci. Interdum et malesuada fames ac ante ipsum primis in faucibus. Integer mattis orci in bibendum ultricies. Quisque a dui erat. Phasellus et vulputate ipsum. Proin metus ex, lobortis nec ornare eget, bibendum ut sapien. Aliquam in dolor lobortis, aliquam tellus a, congue augue. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
|
||||
Aenean pretium purus augue, ut bibendum erat convallis quis. Cras condimentum quis velit ac mollis. Suspendisse non purus fringilla, venenatis nisl porta, finibus odio. Curabitur aliquet metus faucibus libero interdum euismod. Morbi sed magna nisl. Morbi odio nibh, facilisis vel sapien eu, tempus tincidunt erat. Nullam erat velit, sagittis at purus quis, tristique scelerisque tortor. Pellentesque lacinia tortor id est aliquam viverra. Vestibulum et diam ac ipsum mollis fringilla.
|
@@ -3,9 +3,15 @@ import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
|
||||
import ContactCTA from '../components/ContactCTA.astro';
|
||||
import Hero from '../components/Hero.astro';
|
||||
|
||||
import directus, { directus_url } from "../../lib/directus"
|
||||
import { readSingleton } from "@directus/sdk";
|
||||
|
||||
const global = await directus.request(readSingleton("global"));
|
||||
const about = await directus.request(readSingleton("about"));
|
||||
---
|
||||
|
||||
<BaseLayout title="About | Alex Lebens" description="About Alex Lebens">
|
||||
<BaseLayout title=`About | ${global.name}` description=`About ${global.name}`>
|
||||
<div class="stack gap-20">
|
||||
<main class="wrapper about">
|
||||
<Hero
|
||||
@@ -15,51 +21,38 @@ import Hero from '../components/Hero.astro';
|
||||
<img
|
||||
width="1553"
|
||||
height="873"
|
||||
src="/assets/hiking.jpg"
|
||||
alt="Alex Lebens hiking in Texas"
|
||||
src=`${directus_url}/assets/${global.about}`
|
||||
alt=`${global.name} hiking in Texas`
|
||||
/>
|
||||
</Hero>
|
||||
|
||||
<section>
|
||||
<h2 class="section-title">Background</h2>
|
||||
<div class="content">
|
||||
<p>
|
||||
Grew up exploring the outdoors just north of the Twin Cities. Now, my passions include tinkering with my homelab,
|
||||
camping adventures in my Jeep, and hitting the slopes or trails for skiing and hiking. I've also been fortunate
|
||||
enough to travel extensively, visiting nearly every continent, including Antarctica!
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="content"
|
||||
set:html={about.background}
|
||||
/>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title">Expierence</h2>
|
||||
<div class="content">
|
||||
<p>
|
||||
Proudly served 6 years in the US Air Force, gaining valuable experience in Cyber Operations and Reconnaissance
|
||||
while stationed in Japan, Korea, and Texas.
|
||||
</p>
|
||||
<p>
|
||||
Gained valuable experience working in the heart of Washington, D.C. for several years, including time at AWS.
|
||||
Relocated to Denver in late 2020 to enjoy the outdoor opportunities Colorado has to offer.
|
||||
</p>
|
||||
<p>
|
||||
Recently returned to my roots in Minnesota and eager to embrace new opportunities and challenges in my home state.
|
||||
</p>
|
||||
</div>
|
||||
<h2 class="section-title">Experience</h2>
|
||||
<div
|
||||
class="content"
|
||||
set:html={about.experience}
|
||||
/>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title">Education</h2>
|
||||
<div class="content">
|
||||
<p>Currently completing my B.S. in Cloud Computing at Western Governors University. Excited to graduate in 2025!</p>
|
||||
</div>
|
||||
<div
|
||||
class="content"
|
||||
set:html={about.education}
|
||||
/>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title">Certifications</h2>
|
||||
<div class="content">
|
||||
<p>AWS DevOps Engineer</p>
|
||||
<p>Certified Kubernetes Administrator</p>
|
||||
<p>Certified Kubernetes Application Developer</p>
|
||||
<p>CompTIA Cloud+</p>
|
||||
</div>
|
||||
<div
|
||||
class="content"
|
||||
set:html={about.certifications}
|
||||
/>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
---
|
||||
import { getCollection } from 'astro:content';
|
||||
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
|
||||
import CallToAction from '../components/CallToAction.astro';
|
||||
@@ -13,21 +11,29 @@ import PortfolioPreview from '../components/PortfolioPreview.astro';
|
||||
import ContactCTA from '../components/ContactCTA.astro';
|
||||
import Skills from '../components/Skills.astro';
|
||||
|
||||
const projects = (await getCollection('projects'))
|
||||
.sort((a, b) => b.data.publishDate.valueOf() - a.data.publishDate.valueOf())
|
||||
.slice(0, 4);
|
||||
import directus, { directus_url } from "../../lib/directus"
|
||||
import { readItems,readSingleton } from "@directus/sdk";
|
||||
|
||||
const global = await directus.request(readSingleton("global"));
|
||||
|
||||
const posts = await directus.request(
|
||||
readItems("posts", {
|
||||
fields: ['*'],
|
||||
sort: ["-published_date"],
|
||||
})
|
||||
);
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title="Home | Alex Lebens"
|
||||
title=`Home | ${global.name}`
|
||||
description=""
|
||||
>
|
||||
<div class="stack gap-20 lg:gap-48">
|
||||
<div class="wrapper stack gap-8 lg:gap-20">
|
||||
<header class="hero">
|
||||
<Hero
|
||||
title="Hello, my name is Alex Lebens"
|
||||
tagline="I am a Cloud Engineer who is currently based in St. Paul, Minnesota."
|
||||
title=`Hello, my name is ${global.name}`
|
||||
tagline={global.tagline}
|
||||
align="start"
|
||||
>
|
||||
<div class="roles">
|
||||
@@ -38,10 +44,10 @@ const projects = (await getCollection('projects'))
|
||||
</Hero>
|
||||
|
||||
<img
|
||||
alt="Alex Lebens in Antarctica"
|
||||
alt=`${global.name} in Antarctica`
|
||||
width="480"
|
||||
height="620"
|
||||
src="/assets/portrait.jpg"
|
||||
src=`${directus_url}/assets/${global.portrait}`
|
||||
/>
|
||||
</header>
|
||||
|
||||
@@ -57,13 +63,13 @@ const projects = (await getCollection('projects'))
|
||||
|
||||
<div class="gallery">
|
||||
<Grid variant="offset">
|
||||
{
|
||||
projects.map((project) => (
|
||||
<li>
|
||||
<PortfolioPreview project={project} />
|
||||
</li>
|
||||
))
|
||||
}
|
||||
{
|
||||
posts.map((post) => (
|
||||
<li>
|
||||
<PortfolioPreview posts={post} />
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</Grid>
|
||||
</div>
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
---
|
||||
import { getCollection } from 'astro:content';
|
||||
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
|
||||
import ContactCTA from '../components/ContactCTA.astro';
|
||||
@@ -8,14 +6,22 @@ import PortfolioPreview from '../components/PortfolioPreview.astro';
|
||||
import Hero from '../components/Hero.astro';
|
||||
import Grid from '../components/Grid.astro';
|
||||
|
||||
const projects = (await getCollection('projects')).sort(
|
||||
(a, b) => b.data.publishDate.valueOf() - a.data.publishDate.valueOf(),
|
||||
import directus from "../../lib/directus"
|
||||
import { readItems,readSingleton } from "@directus/sdk";
|
||||
|
||||
const global = await directus.request(readSingleton("global"));
|
||||
|
||||
const posts = await directus.request(
|
||||
readItems("posts", {
|
||||
fields: ['*'],
|
||||
sort: ["-published_date"],
|
||||
})
|
||||
);
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title="My Projects | Alex Lebens"
|
||||
description="Learn about Alex Lebens's most recent projects"
|
||||
title=`My Projects | ${global.name}`
|
||||
description=`Learn about ${global.name}'s most recent projects`
|
||||
>
|
||||
<div class="stack gap-20">
|
||||
<main class="wrapper stack gap-8">
|
||||
@@ -25,13 +31,13 @@ const projects = (await getCollection('projects')).sort(
|
||||
align="start"
|
||||
/>
|
||||
<Grid variant="offset">
|
||||
{
|
||||
projects.map((project) => (
|
||||
<li>
|
||||
<PortfolioPreview project={project} />
|
||||
</li>
|
||||
))
|
||||
}
|
||||
{
|
||||
posts.map((post) => (
|
||||
<li>
|
||||
<PortfolioPreview posts={post} />
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</Grid>
|
||||
</main>
|
||||
<ContactCTA />
|
||||
|
@@ -1,6 +1,4 @@
|
||||
---
|
||||
import { type CollectionEntry, getCollection } from 'astro:content';
|
||||
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
|
||||
import ContactCTA from '../../components/ContactCTA.astro';
|
||||
@@ -8,43 +6,44 @@ import Hero from '../../components/Hero.astro';
|
||||
import Icon from '../../components/Icon.astro';
|
||||
import Pill from '../../components/Pill.astro';
|
||||
|
||||
interface Props {
|
||||
entry: CollectionEntry<'projects'>;
|
||||
}
|
||||
import directus, { directus_url } from "../../../lib/directus";
|
||||
import { readItems } from "@directus/sdk";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const projects = await getCollection('projects');
|
||||
return projects.map((entry) => ({
|
||||
params: { slug: entry.slug },
|
||||
props: { entry },
|
||||
}));
|
||||
const posts = await directus.request(readItems("posts", {
|
||||
fields: ['*'],
|
||||
}));
|
||||
return posts.map((post) => ({ params: { slug: post.slug }, props: post }));
|
||||
}
|
||||
|
||||
const { entry } = Astro.props;
|
||||
const { Content } = await entry.render();
|
||||
const post = Astro.props;
|
||||
const published_date: string = new Date(post.published_date).toLocaleDateString();
|
||||
---
|
||||
|
||||
<BaseLayout title={entry.data.title} description={entry.data.description}>
|
||||
<BaseLayout title={post.title}>
|
||||
<div class="stack gap-20">
|
||||
<div class="stack gap-15">
|
||||
<header>
|
||||
<div class="wrapper stack gap-2">
|
||||
<a class="back-link" href="/projects/"><Icon icon="arrow-left" /> Projects</a>
|
||||
<Hero title={entry.data.title} align="start">
|
||||
<Hero
|
||||
title={post.title}
|
||||
tagline=`Published on ${published_date}`
|
||||
align="start"
|
||||
>
|
||||
<div class="details">
|
||||
<div class="tags">
|
||||
{entry.data.tags.map((t) => <Pill>{t}</Pill>)}
|
||||
{post.tags.map((t) => <Pill>{t}</Pill>)}
|
||||
</div>
|
||||
<p class="description">{entry.data.description}</p>
|
||||
</div>
|
||||
</Hero>
|
||||
</div>
|
||||
</header>
|
||||
<main class="wrapper">
|
||||
<div class="stack gap-10 content">
|
||||
{entry.data.img && <img src={entry.data.img} alt={entry.data.img_alt || ''} />}
|
||||
{post.image && <img src={`${directus_url}/assets/${post.image}?width=500`} alt={post.image_alt || ''} />}
|
||||
<div class="content">
|
||||
<Content />
|
||||
<div set:html={post.content} />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
@@ -1,3 +1,5 @@
|
||||
{
|
||||
"extends": "astro/tsconfigs/strict"
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"include": [".astro/types.d.ts", "**/*"],
|
||||
"exclude": ["dist"]
|
||||
}
|
Reference in New Issue
Block a user