Compare commits

...

6 Commits

Author SHA1 Message Date
Anton Pogrebnjak
7e4f1acbf1 Delete .github/workflows directory 2026-04-06 23:03:48 +02:00
Anton Pogrebnjak
fcb52ebdc9 Fixed gallery link 2026-04-06 23:00:56 +02:00
Anton Pogrebnjak
c0a7f193db Also added photo types 2026-04-06 22:56:43 +02:00
Anton Pogrebnjak
da9d256b71 Added phtography section 2026-04-06 22:56:12 +02:00
Anton Pogrebnjak
d03478f81a Fixed showcase and home page 2026-04-06 20:37:32 +02:00
Anton Pogrebnjak
120ce7726f Updated dependencies 2026-04-06 19:56:05 +02:00
22 changed files with 1156 additions and 3801 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
public/images/photos/*.jpg filter=lfs diff=lfs merge=lfs -text

View File

@@ -1,39 +0,0 @@
name: Deploy to GitHub Pages
on:
# Trigger the workflow every time you push to the `main` branch
# Using a different branch name? Replace `main` with your branchs name
push:
branches: [ main ]
# Allows you to run this workflow manually from the Actions tab on GitHub.
workflow_dispatch:
# Allow this job to clone the repo and create a page deployment
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout your repository using git
uses: actions/checkout@v4
- name: Install, build, and upload your site
uses: withastro/action@v3
# with:
# path: . # The root location of your Astro project inside the repository. (optional)
# node-version: 20 # The specific version of Node that should be used to build your site. Defaults to 20. (optional)
# package-manager: pnpm@latest # The Node package manager that should be used to install dependencies and build your site. Automatically detected based on your lockfile. (optional)
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

View File

@@ -4,7 +4,6 @@ import mdx from '@astrojs/mdx';
import remarkMath from 'remark-math' import remarkMath from 'remark-math'
import rehypeKatex from 'rehype-katex' import rehypeKatex from 'rehype-katex'
import sitemap from '@astrojs/sitemap'; import sitemap from '@astrojs/sitemap';
import { typst } from 'astro-typst';
// https://astro.build/config // https://astro.build/config
export default defineConfig({ export default defineConfig({
@@ -16,5 +15,5 @@ export default defineConfig({
integrations: [mdx({ integrations: [mdx({
syntaxHighlight: 'shiki', syntaxHighlight: 'shiki',
shikiConfig: { theme: "dracula" }, shikiConfig: { theme: "dracula" },
}), sitemap(), typst()], }), sitemap()],
}); });

4583
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,12 +9,10 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"@astrojs/mdx": "^4.3.13", "@astrojs/mdx": "^5.0.3",
"@astrojs/rss": "^4.0.15", "@astrojs/rss": "^4.0.18",
"@astrojs/sitemap": "^3.7.0", "@astrojs/sitemap": "^3.7.2",
"@astrojs/vue": "^5.1.4", "astro": "^6.1.4",
"astro": "^5.17.3",
"astro-typst": "^0.12.1",
"rehype-katex": "^7.0.1", "rehype-katex": "^7.0.1",
"remark-math": "^6.0.0" "remark-math": "^6.0.0"
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

View File

@@ -44,4 +44,4 @@ const { title, description, image = '/logo.png' } = Astro.props;
<meta property="twitter:url" content={Astro.url} /> <meta property="twitter:url" content={Astro.url} />
<meta property="twitter:title" content={title} /> <meta property="twitter:title" content={title} />
<meta property="twitter:description" content={description} /> <meta property="twitter:description" content={description} />
<meta property="twitter:image" content={new URL(image, Astro.url)} /> <meta property="twitter:image" content={new URL(image, Astro.url)} />

View File

@@ -0,0 +1,49 @@
---
import type { Photo } from '../models/Photo.ts';
const photos: Photo[] = Astro.props.photos;
const collection: string = Astro.props.collection;
const color = Astro.props.color || 'var(--text)';
---
<section>
{
photos.map((photo) => (
<a href={"/photography/" + photo.id}>
<img src={photo.src} />
</a>
))
}
</section>
<style define:vars={{ color }}>
section {
width: 100%;
overflow: hidden;
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 2px;
}
a {
overflow: hidden;
min-height: 200px;
max-height: 12.5rem;
min-width: 200px;
max-width: 12.5rem;
flex: 1;
}
img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 0;
transition: transform .2s;
}
img:hover {
transform: scale(1.2);
cursor: pointer;
}
</style>

View File

@@ -10,9 +10,9 @@ import Socials from "./Socials.astro";
<img src="/logo.svg" alt="ಠ_ಠ" /> <img src="/logo.svg" alt="ಠ_ಠ" />
</a> </a>
<div class="internal-links"> <div class="internal-links">
<HeaderLink href="/">Home</HeaderLink>
<HeaderLink href="/projects">Projects</HeaderLink> <HeaderLink href="/projects">Projects</HeaderLink>
<HeaderLink href="/blog">Blog</HeaderLink> <HeaderLink href="/photography">Photography</HeaderLink>
<HeaderLink href="/blog">Blog</HeaderLink>
</div> </div>
<Socials /> <Socials />
</nav> </nav>

View File

@@ -78,6 +78,7 @@ const color = Astro.props.color || 'var(--text)';
margin: 0; margin: 0;
color: var(--color); color: var(--color);
line-height: 1; line-height: 1;
font-size: 1em;
font-variant-caps: small-caps; font-variant-caps: small-caps;
} }
.date { .date {
@@ -102,8 +103,8 @@ const color = Astro.props.color || 'var(--text)';
ul li:first-child { ul li:first-child {
margin-bottom: 0; margin-bottom: 0;
} }
ul li:first-child .title { ul li:first-child .title, ul li .title {
font-size: 1.563em; font-size: 1.2em;
} }
} }
</style> </style>

View File

@@ -1,4 +1,4 @@
import { glob } from 'astro/loaders'; import { glob, file } from 'astro/loaders';
import { defineCollection, z } from 'astro:content'; import { defineCollection, z } from 'astro:content';
const bachelor = defineCollection({ const bachelor = defineCollection({
@@ -28,6 +28,22 @@ const blog = defineCollection({
updatedDate: z.coerce.date().optional(), updatedDate: z.coerce.date().optional(),
heroImage: z.string().optional(), heroImage: z.string().optional(),
}), }),
}
);
const photography = defineCollection({
// Load Markdown and MDX files in the `src/content/projects/` directory.
loader: file(
'./src/content/photography/index.json'
),
// Type-check frontmatter using a schema
schema: z.object({
title: z.string(),
description: z.string(),
src: z.string(),
// Transform string to Date object
pubDate: z.coerce.date(),
}),
}); });
const projects = defineCollection({ const projects = defineCollection({
@@ -46,4 +62,4 @@ const projects = defineCollection({
}), }),
}); });
export const collections = { bachelor, blog, projects }; export const collections = { bachelor, blog, photography, projects };

View File

@@ -0,0 +1,44 @@
[
{
"id": "DSC05932",
"src": "DSC05932.jpg",
"title": "DSC05932",
"pubDate": "2026-04-06",
"description": ""
},
{
"id": "DSC06124",
"src": "DSC06124.jpg",
"title": "DSC06124",
"pubDate": "2026-04-06",
"description": ""
},
{
"id": "DSC06196",
"src": "DSC06196.jpg",
"title": "DSC06196",
"pubDate": "2026-04-06",
"description": ""
},
{
"id": "UKN_Topo_01",
"src": "UKN_Topo_01.jpg",
"title": "UKN_Topo_01",
"pubDate": "2026-04-06",
"description": ""
},
{
"id": "UKN_Topo_02",
"src": "UKN_Topo_02.jpg",
"title": "UKN_Topo_02",
"pubDate": "2026-04-06",
"description": ""
},
{
"id": "UKN_Topo_03",
"src": "UKN_Topo_03.jpg",
"title": "UKN_Topo_03",
"pubDate": "2026-04-06",
"description": ""
}
]

View File

@@ -0,0 +1,103 @@
---
import type { CollectionEntry } from "astro:content";
import BaseHead from "../components/BaseHead.astro";
import Header from "../components/Header.astro";
import Main from "../components/Main.astro";
import Footer from "../components/Footer.astro";
import FormattedDate from "../components/FormattedDate.astro";
type Props = CollectionEntry<"photography">["data"];
const { title, description, pubDate, src } = Astro.props;
---
<html lang="en">
<head>
<BaseHead title={title} description={description} image={src} />
<style>
article {
width: 100%;
}
h1::after {
content: "";
display: block;
/* width: 100%; */
height: 2px;
background-color: var(--primary);
margin: 0.5rem auto;
}
h2::after {
content: "";
display: block;
/* width: 100%; */
height: 2px;
background-color: var(--primary);
margin: 0.5rem auto;
}
.hero-image {
width: 100%;
}
.hero-image img {
display: block;
margin: 0 auto;
border-radius: 12px;
}
.prose {
width: 720px;
max-width: 100%;
margin: auto;
padding: 1em;
color: var(--text);
}
.title {
margin-bottom: 1em;
padding: 1em 0;
text-align: center;
line-height: 1;
}
.title h1 {
margin: 0 0 0.5em 0;
}
.date {
margin-bottom: 0.5em;
color: var(--text);
}
</style>
</head>
<body>
<Header />
<Main>
<article>
<div class="hero-image">
<img
width={1020}
height={510}
src={src}
alt=""
/>
</div>
<div class="prose">
<div class="title">
<div class="date">
<FormattedDate date={pubDate} />
</div>
<h1>{title}</h1>
</div>
<p>
{description}
</p>
</div>
</article>
</Main>
<Footer />
</body>
</html>

32
src/models/Photo.ts Normal file
View File

@@ -0,0 +1,32 @@
export type CollectionPhoto = {
id: string;
collection: "photography";
data: {
title: string,
src: string,
pubDate: Date,
description: string
};
filePath?: string;
};
export type Photo = {
id: string,
title: string;
src: string;
pubDate: Date;
description: string;
collection: "photography";
};
export const convertPhoto = (collectionPhoto: CollectionPhoto): Photo => {
return {
id: collectionPhoto.id,
title: collectionPhoto.data.title,
src: "/images/photography/" + collectionPhoto.data.src,
pubDate: collectionPhoto.data.pubDate,
description: collectionPhoto.data.description,
collection: collectionPhoto.collection,
};
}

View File

@@ -27,11 +27,12 @@ const posts: Post[] = (await getCollection("projects"))
Welcome to my realm! Welcome to my realm!
</h2> </h2>
<h3 class="buttons"> <h4 class="buttons">
<a href="/blog">Blog</a>
<a href="/projects">Projects</a> <a href="/projects">Projects</a>
<a href="/photography">Photography</a>
<a href="/blog">Blog</a>
<a href="/about">About</a> <a href="/about">About</a>
</h3> </h4>
</section> </section>
<section id="projects"> <section id="projects">
@@ -108,14 +109,6 @@ const posts: Post[] = (await getCollection("projects"))
section { section {
padding: 1rem; padding: 1rem;
} }
#welcome h1 {
font-size: 1.5rem;
}
#welcome h2 {
font-size: 1rem;
}
} }
</style> </style>
</html> </html>

View File

@@ -0,0 +1,18 @@
---
import { getCollection } from 'astro:content';
import { render } from 'astro:content';
import GalleryPhoto from '../../layouts/GalleryPhoto.astro';
import { convertCollectionPhoto, convertPhoto, type Photo } from '../../models/Photo';
export async function getStaticPaths() {
const photos: Photo[] = (await getCollection('photography')).map(convertPhoto);
return photos.map((photo) => ({
params: { slug: photo.id },
props: photo,
}));
}
type Props = Photo;
const photo: Photo = Astro.props;
---
<GalleryPhoto {...photo} />

View File

@@ -0,0 +1,29 @@
---
import BaseHead from '../../components/BaseHead.astro';
import Header from '../../components/Header.astro';
import Main from '../../components/Main.astro';
import Footer from '../../components/Footer.astro';
import { SITE_TITLE, SITE_DESCRIPTION } from '../../consts';
import { getCollection } from 'astro:content';
import Gallery from '../../components/Gallery.astro';
import { convertPhoto } from '../../models/Photo';
const photos: Photo[] = (await getCollection('photography')).map(convertPhoto).sort((a, b) => b.pubDate.valueOf() - a.pubDate.valueOf());
---
<!doctype html>
<html lang="en">
<head>
<BaseHead title={SITE_TITLE} description={SITE_DESCRIPTION} />
</head>
<body>
<Header />
<Main>
{photos.length === 0 ? (
<h1 style="opacity: .5; user-select: none;">No photos yet &#128539;</h1>
) : ( <Gallery photos={photos} /> )}
</Main>
<Footer />
</body>
</html>