mirror of
https://github.com/mikkelsvartveit/astro-personal-website.git
synced 2025-12-22 11:12:38 +00:00
Upgrade to Astro 5
This commit is contained in:
parent
ff787453ab
commit
c5a44e7fab
16 changed files with 2578 additions and 2018 deletions
|
|
@ -7,7 +7,7 @@ import cloudflare from "@astrojs/cloudflare";
|
|||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [tailwind(), svelte(), mdx()],
|
||||
output: "hybrid",
|
||||
output: "static",
|
||||
adapter: cloudflare({
|
||||
imageService: "compile",
|
||||
platformProxy: {
|
||||
|
|
@ -19,8 +19,5 @@ export default defineConfig({
|
|||
external: ["node:async_hooks"],
|
||||
},
|
||||
},
|
||||
experimental: {
|
||||
actions: true,
|
||||
},
|
||||
site: "https://mikkelsvartveit.com",
|
||||
});
|
||||
|
|
|
|||
18
package.json
18
package.json
|
|
@ -10,20 +10,20 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/cloudflare": "^10.4.2",
|
||||
"@astrojs/mdx": "^3.1.3",
|
||||
"@astrojs/svelte": "^5.7.0",
|
||||
"@astrojs/tailwind": "^5.1.0",
|
||||
"astro": "^4.12.2",
|
||||
"@astrojs/cloudflare": "^12.1.0",
|
||||
"@astrojs/mdx": "^4.0.3",
|
||||
"@astrojs/svelte": "^7.0.2",
|
||||
"@astrojs/tailwind": "^5.1.4",
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
"astro": "^5.1.1",
|
||||
"sharp": "^0.32.6",
|
||||
"svelte": "^4.2.18",
|
||||
"tailwindcss": "^3.4.7"
|
||||
"svelte": "^5.15.0",
|
||||
"tailwindcss": "^3.4.17"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.13",
|
||||
"prettier": "3.0.3",
|
||||
"prettier-plugin-astro": "^0.12.3",
|
||||
"prettier-plugin-svelte": "^3.2.6",
|
||||
"prettier-plugin-svelte": "^3.3.2",
|
||||
"prettier-plugin-tailwindcss": "^0.5.14"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4373
pnpm-lock.yaml
4373
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
|
@ -1,18 +1,9 @@
|
|||
import { defineAction, z, getApiContext } from "astro:actions";
|
||||
import { defineAction } from "astro:actions";
|
||||
|
||||
export const server = {
|
||||
registerView: defineAction({
|
||||
input: z.object({ articleSlug: z.string() }),
|
||||
handler: async ({ articleSlug }) => {
|
||||
const context = getApiContext();
|
||||
|
||||
// @ts-ignore
|
||||
const { ViewCountKV } = context.locals.runtime.env;
|
||||
|
||||
let viewCount = (await ViewCountKV.get(articleSlug)) || 0;
|
||||
await ViewCountKV.put(articleSlug, ++viewCount);
|
||||
|
||||
return viewCount;
|
||||
dummy: defineAction({
|
||||
handler: async () => {
|
||||
return 0;
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
|
|
|||
29
src/components/ArticleViewCounter.astro
Normal file
29
src/components/ArticleViewCounter.astro
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
export const prerender = false;
|
||||
|
||||
const { articleSlug } = Astro.props;
|
||||
|
||||
const { ViewCountKV } = Astro.locals.runtime.env;
|
||||
|
||||
let counter = await ViewCountKV.get(articleSlug);
|
||||
|
||||
await ViewCountKV.put(articleSlug, ++counter);
|
||||
---
|
||||
|
||||
<span class="inline-flex items-center space-x-1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" height="12">
|
||||
<!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.-->
|
||||
<style>
|
||||
svg {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
|
||||
<path
|
||||
d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM144 256a144 144 0 1 1 288 0 144 144 0 1 1 -288 0zm144-64c0 35.3-28.7 64-64 64c-7.1 0-13.9-1.2-20.3-3.3c-5.5-1.8-11.9 1.6-11.7 7.4c.3 6.9 1.3 13.8 3.2 20.7c13.7 51.2 66.4 81.6 117.6 67.9s81.6-66.4 67.9-117.6c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3z"
|
||||
>
|
||||
</path>
|
||||
</svg>
|
||||
|
||||
<span>{counter}</span>
|
||||
</span>
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
<script lang="ts">
|
||||
import { actions } from "astro:actions";
|
||||
import { onMount } from "svelte";
|
||||
import { expoIn } from "svelte/easing";
|
||||
import { fade } from "svelte/transition";
|
||||
|
||||
export let articleSlug: string;
|
||||
|
||||
let counter: number | null = null;
|
||||
|
||||
onMount(async () => {
|
||||
const readCount = await actions.registerView({ articleSlug });
|
||||
|
||||
counter = readCount;
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if counter !== null}
|
||||
<span
|
||||
class="inline-flex items-center space-x-1"
|
||||
transition:fade={{ duration: 200, easing: expoIn }}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" height="12">
|
||||
<!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.-->
|
||||
<style>
|
||||
svg {
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
|
||||
<path
|
||||
d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM144 256a144 144 0 1 1 288 0 144 144 0 1 1 -288 0zm144-64c0 35.3-28.7 64-64 64c-7.1 0-13.9-1.2-20.3-3.3c-5.5-1.8-11.9 1.6-11.7 7.4c.3 6.9 1.3 13.8 3.2 20.7c13.7 51.2 66.4 81.6 117.6 67.9s81.6-66.4 67.9-117.6c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3z"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<span>{counter}</span>
|
||||
</span>
|
||||
{/if}
|
||||
28
src/content.config.ts
Normal file
28
src/content.config.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import { defineCollection, z } from "astro:content";
|
||||
import { glob } from "astro/loaders";
|
||||
|
||||
const blog = defineCollection({
|
||||
loader: glob({ pattern: "*.md*", base: "./src/content/blog" }),
|
||||
schema: ({ image }) =>
|
||||
z.object({
|
||||
intro: z.string(),
|
||||
image: image(),
|
||||
date: z.date(),
|
||||
}),
|
||||
});
|
||||
|
||||
const programming = defineCollection({
|
||||
loader: glob({ pattern: "*.md*", base: "./src/content/programming" }),
|
||||
schema: ({ image }) =>
|
||||
z.object({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
image: image(),
|
||||
date: z.date(),
|
||||
technologies: z.array(z.string()),
|
||||
website: z.string().optional(),
|
||||
repository: z.string().optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = { blog, programming };
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
import { z, defineCollection } from "astro:content";
|
||||
|
||||
const programmingCollection = defineCollection({
|
||||
type: "content",
|
||||
schema: ({ image }) =>
|
||||
z.object({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
image: image(),
|
||||
technologies: z.array(z.string()),
|
||||
website: z.string().url(),
|
||||
repository: z.string().url().optional(),
|
||||
date: z.date(),
|
||||
}),
|
||||
});
|
||||
|
||||
const blogCollection = defineCollection({
|
||||
type: "content",
|
||||
schema: ({ image }) =>
|
||||
z.object({
|
||||
image: image(),
|
||||
intro: z.string(),
|
||||
date: z.date(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = {
|
||||
programming: programmingCollection,
|
||||
blog: blogCollection,
|
||||
};
|
||||
12
src/env.d.ts
vendored
12
src/env.d.ts
vendored
|
|
@ -1,3 +1,13 @@
|
|||
/// <reference path="../.astro/actions.d.ts" />
|
||||
/// <reference path="../.astro/types.d.ts" />
|
||||
/// <reference types="astro/client" />
|
||||
|
||||
type KVNamespace = import("@cloudflare/workers-types").KVNamespace;
|
||||
type ENV = {
|
||||
ViewCountKV: KVNamespace;
|
||||
};
|
||||
|
||||
// use a default runtime configuration (advanced mode).
|
||||
type Runtime = import("@astrojs/cloudflare").Runtime<ENV>;
|
||||
declare namespace App {
|
||||
interface Locals extends Runtime {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,26 @@
|
|||
---
|
||||
import { getCollection, render } from "astro:content";
|
||||
import ContainerLayout from "@layouts/ContainerLayout.astro";
|
||||
import BaseLayout from "@layouts/BaseLayout.astro";
|
||||
import TextContentLayout from "@layouts/TextContentLayout.astro";
|
||||
import type { GetStaticPaths } from "astro";
|
||||
import { getCollection } from "astro:content";
|
||||
import ProseLayout from "@layouts/ProseLayout.astro";
|
||||
import ArticleViewCounter from "@components/ArticleViewCounter.svelte";
|
||||
import ArticleViewCounter from "@components/ArticleViewCounter.astro";
|
||||
import HeadContent from "@components/HeadContent.astro";
|
||||
import type { GetStaticPaths } from "astro";
|
||||
|
||||
export const getStaticPaths = (async () => {
|
||||
const blogCollection = await getCollection("blog");
|
||||
return blogCollection.map((entry) => ({
|
||||
params: {
|
||||
article: entry.slug,
|
||||
article: entry.id,
|
||||
},
|
||||
props: { entry },
|
||||
}));
|
||||
}) satisfies GetStaticPaths;
|
||||
|
||||
const project = Astro.props.entry;
|
||||
const { Content, headings } = await project.render();
|
||||
const { date, intro, image } = project.data;
|
||||
const blogPost = Astro.props.entry;
|
||||
const { Content, headings } = await render(blogPost);
|
||||
const { date, intro, image } = blogPost.data;
|
||||
const title = headings[0].text;
|
||||
---
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ const title = headings[0].text;
|
|||
|
||||
<span class="px-2">⋅</span>
|
||||
|
||||
<ArticleViewCounter articleSlug={project.slug} client:only="svelte" />
|
||||
<ArticleViewCounter server:defer articleSlug={blogPost.id} />
|
||||
</p>
|
||||
|
||||
<ProseLayout>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
---
|
||||
import { getCollection, render } from "astro:content";
|
||||
import { Image } from "astro:assets";
|
||||
import Paragraph from "@components/Paragraph.astro";
|
||||
import ContainerLayout from "@layouts/ContainerLayout.astro";
|
||||
import BaseLayout from "@layouts/BaseLayout.astro";
|
||||
import TextContentLayout from "@layouts/TextContentLayout.astro";
|
||||
import { getCollection } from "astro:content";
|
||||
import Head from "@components/HeadContent.astro";
|
||||
|
||||
const articles = await getCollection("blog");
|
||||
|
|
@ -31,13 +31,13 @@ const articles = await getCollection("blog");
|
|||
articles
|
||||
.sort((p2, p1) => p1.data.date.getTime() - p2.data.date.getTime())
|
||||
.map(async (article) => {
|
||||
const { slug, data } = article;
|
||||
const { id, data } = article;
|
||||
const { image, intro } = data;
|
||||
const { headings } = await article.render();
|
||||
const { headings } = await render(article);
|
||||
const title = headings[0].text;
|
||||
return (
|
||||
<a
|
||||
href={`/articles/${slug}`}
|
||||
href={`/articles/${id}`}
|
||||
class="group mx-auto my-8 grid max-w-xs grid-cols-1 overflow-hidden rounded-lg bg-white shadow duration-100 hover:translate-x-1 hover:shadow-md sm:max-w-none sm:grid-cols-3"
|
||||
>
|
||||
<Image
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
import { getCollection } from "astro:content";
|
||||
import { getCollection, render } from "astro:content";
|
||||
import { Image } from "astro:assets";
|
||||
import BaseLayout from "../layouts/BaseLayout.astro";
|
||||
import Link from "@components/Link.astro";
|
||||
|
|
@ -11,8 +11,8 @@ const articles = await getCollection("blog");
|
|||
const latestArticle = articles.sort(
|
||||
(p2, p1) => p1.data.date.getTime() - p2.data.date.getTime()
|
||||
)[0];
|
||||
const latestArticleSlug = latestArticle.slug;
|
||||
const latestArticleTitle = (await latestArticle.render()).headings[0].text;
|
||||
const latestArticleSlug = latestArticle.id;
|
||||
const latestArticleTitle = (await render(latestArticle)).headings[0].text;
|
||||
const latestArticleImage = latestArticle.data.image;
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,9 @@
|
|||
import type { GetStaticPaths } from "astro";
|
||||
import { Image } from "astro:assets";
|
||||
import { getFileNameFromPath } from "./index.astro";
|
||||
import RootLayout from "@layouts/RootLayout.astro";
|
||||
import HeadContent from "@components/HeadContent.astro";
|
||||
|
||||
export const getStaticPaths = (async () => {
|
||||
export const getStaticPaths: GetStaticPaths = (async () => {
|
||||
const photos = await Astro.glob("../../assets/photos/*");
|
||||
|
||||
return photos.map((photo: any) => ({
|
||||
|
|
@ -18,7 +17,7 @@ export const getStaticPaths = (async () => {
|
|||
}));
|
||||
}) satisfies GetStaticPaths;
|
||||
|
||||
const { photo } = Astro.props;
|
||||
const photo = Astro.props.photo as any;
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
|
|
|
|||
|
|
@ -6,19 +6,20 @@ import type { GetStaticPaths } from "astro";
|
|||
import { getCollection } from "astro:content";
|
||||
import ProseLayout from "@layouts/ProseLayout.astro";
|
||||
import HeadContent from "@components/HeadContent.astro";
|
||||
import { render } from "astro:content";
|
||||
|
||||
export const getStaticPaths = (async () => {
|
||||
const programmingEntries = await getCollection("programming");
|
||||
return programmingEntries.map((entry) => ({
|
||||
params: {
|
||||
project: entry.slug,
|
||||
project: entry.id,
|
||||
},
|
||||
props: { entry },
|
||||
}));
|
||||
}) satisfies GetStaticPaths;
|
||||
|
||||
const project = Astro.props.entry;
|
||||
const { Content } = await project.render();
|
||||
const { Content } = await render(project);
|
||||
const { title, description, image, date, technologies, website, repository } =
|
||||
project.data;
|
||||
---
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ const projects = await getCollection("programming");
|
|||
{
|
||||
projects
|
||||
.sort((p2, p1) => p1.data.date.getTime() - p2.data.date.getTime())
|
||||
.map(({ data, slug }) => (
|
||||
.map(({ data, id }) => (
|
||||
<a
|
||||
href={`/programming/${slug}`}
|
||||
href={`/programming/${id}`}
|
||||
class="mx-auto overflow-hidden rounded-lg bg-white pb-8 shadow-md duration-100 hover:-translate-y-1 hover:shadow-lg"
|
||||
>
|
||||
<Image
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"include": [".astro/types.d.ts", "**/*"],
|
||||
"exclude": ["dist"],
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
|
|
|
|||
Loading…
Reference in a new issue