···363637371. Fork this repository by clicking on "Use template" (note: this repository per default uses github actions which are only free for public repositories).
38383939-2. In your repository settings, set up github pages to deploy using github actions (*SETTINGS* -> *PAGES* -> *SOURCE*: **Github Actions**)
3939+2. In your repository settings, set up github pages to deploy using github actions (_SETTINGS_ -> _PAGES_ -> _SOURCE_: **Github Actions**)
40404141-3. Set up your blog info in `src/config.json` (most importantly change `SITE` to your deployment url, e.g. for github pages `https://<your-github-username>.github.io/` and `BASE` to your base path, e.g. for github pages `/<your-repo-name>`)
4141+3. Set up your blog info in `src/config.ts` (most importantly change `SITE` to your deployment url, e.g. for github pages `https://<your-github-username>.github.io/` and `BASE` to your base path, e.g. for github pages `/<your-repo-name>`)
424243434. Your blog should be live in about 1 minute at `https://<your-github-username>.github.io/<your-repo-name>`
4444
···11---
22-import { BASE, SHOW_IMAGES } from "../config.json";
22+import { BASE, SHOW_IMAGES } from "../config.ts";
33import FormattedDate from "./FormattedDate.astro";
44import Tag from "./Tag.astro";
55import HeroImage from "./HeroImage.astro";
+1-1
src/components/BlogEntry.astro
···11---
22-import { BASE, SHOW_IMAGES } from "../config.json";
22+import { BASE, SHOW_IMAGES } from "../config.ts";
33import FormattedDate from "./FormattedDate.astro";
44import Tag from "./Tag.astro";
55import HeroImage from "./HeroImage.astro";
···11---
22-import { BASE } from "../config.json";
22+import { BASE } from "../config.ts";
33import PaginationNumber from "./PaginationNumber.astro";
4455type Props = {
+1-1
src/components/PaginationNumber.astro
···11---
22-import { BASE } from "../config.json";
22+import { BASE } from "../config.ts";
3344const { index, active, tag } = Astro.props;
55---
+1-1
src/components/Tag.astro
···11---
22-import { BASE } from "../config.json";
22+import { BASE } from "../config.ts";
33const { tag } = Astro.props;
44---
55
+1-2
src/components/bluesky/BlueskyLikes.astro
···11---
22-import { BLUESKY_IDENTIFIER } from "../../config.json";
22+import { BLUESKY_IDENTIFIER, SITE } from "../../config.ts";
33import { getCollection } from "astro:content";
44import { atUriToPostUri, getComments, getLikes } from "./utils";
55import Likes from "./Likes.svelte";
66import Comments from "./Comments.svelte";
77-import { SITE } from "../../config.json";
8798let posts = await getCollection("posts");
109
···11// keep a cache of formatter per locale, to avoid re-creating them (GC)
22-const formatters = new Map<string, Intl.RelativeTimeFormat>()
22+const formatters = new Map<string, Intl.RelativeTimeFormat>();
3344// get the Intl.RelativeTimeFormat formatter for the given locale
55export function getFormatter(locale: string) {
66- if (formatters.has(locale)) {
77- return formatters.get(locale)!
88- }
99- const formatter = new Intl.RelativeTimeFormat(locale, { numeric: 'always', style: 'narrow' })
1010- formatters.set(locale, formatter)
1111- return formatter
66+ if (formatters.has(locale)) {
77+ return formatters.get(locale)!;
88+ }
99+ const formatter = new Intl.RelativeTimeFormat(locale, {
1010+ numeric: "always",
1111+ style: "narrow",
1212+ });
1313+ formatters.set(locale, formatter);
1414+ return formatter;
1215}
+4-4
src/components/bluesky/relative-time/index.ts
···11-export * from './action'
22-export type { Callback } from './render'
33-export { register, unregister } from './state'
44-export { default as default } from './RelativeTime.svelte'11+export * from "./action";
22+export type { Callback } from "./render";
33+export { register, unregister } from "./state";
44+export { default as default } from "./RelativeTime.svelte";
+56-38
src/components/bluesky/relative-time/render.ts
···11-export type Callback = (result: { seconds: number; count: number; units: Intl.RelativeTimeFormatUnit; text: string }) => void
11+export type Callback = (result: {
22+ seconds: number;
33+ count: number;
44+ units: Intl.RelativeTimeFormatUnit;
55+ text: string;
66+}) => void;
2738export interface RenderState {
44- date: Date | number
55- callback: Callback
66- formatter: Intl.RelativeTimeFormat
99+ date: Date | number;
1010+ callback: Callback;
1111+ formatter: Intl.RelativeTimeFormat;
712}
813914// Array reprsenting one minute, hour, day, week, month, etc in seconds
1010-const cutoffs = [60, 3600, 86400, 86400 * 7, 86400 * 30, 86400 * 365, Infinity]
1515+const cutoffs = [60, 3600, 86400, 86400 * 7, 86400 * 30, 86400 * 365, Infinity];
11161217// Array equivalent to the above but in the string representation of the units
1313-const formatUnits: Intl.RelativeTimeFormatUnit[] = ['seconds', 'minutes', 'hours', 'days', 'weeks', 'months', 'years']
1818+const formatUnits: Intl.RelativeTimeFormatUnit[] = [
1919+ "seconds",
2020+ "minutes",
2121+ "hours",
2222+ "days",
2323+ "weeks",
2424+ "months",
2525+ "years",
2626+];
14271528// function to render relative time into
1629export function render(state: RenderState, now: number) {
1717- const { date, callback, formatter } = state
3030+ const { date, callback, formatter } = state;
18311919- // Allow dates or times to be passed
2020- const timeMs = typeof date === 'number' ? date : date.getTime()
3232+ // Allow dates or times to be passed
3333+ const timeMs = typeof date === "number" ? date : date.getTime();
21342222- // Get the amount of seconds between the given date and now
2323- const delta = timeMs - now
2424- const seconds = Math.round(delta / 1000)
3535+ // Get the amount of seconds between the given date and now
3636+ const delta = timeMs - now;
3737+ const seconds = Math.round(delta / 1000);
25382626- // Grab the ideal cutoff unit
2727- const unitIndex = cutoffs.findIndex(cutoff => cutoff > Math.abs(seconds))
3939+ // Grab the ideal cutoff unit
4040+ const unitIndex = cutoffs.findIndex((cutoff) => cutoff > Math.abs(seconds));
28412929- // units
3030- const units = formatUnits[unitIndex]
4242+ // units
4343+ const units = formatUnits[unitIndex];
31443232- // Get the divisor to divide from the seconds. E.g. if our unit is 'day' our divisor
3333- // is one day in seconds, so we can divide our seconds by this to get the # of days
3434- const divisor = unitIndex ? cutoffs[unitIndex - 1] : 1
4545+ // Get the divisor to divide from the seconds. E.g. if our unit is 'day' our divisor
4646+ // is one day in seconds, so we can divide our seconds by this to get the # of days
4747+ const divisor = unitIndex ? cutoffs[unitIndex - 1] : 1;
35483636- // count of units
3737- const count = Math.round(seconds / divisor)
4949+ // count of units
5050+ const count = Math.round(seconds / divisor);
38513939- // Intl.RelativeTimeFormat do its magic
4040- callback({ seconds: seconds, count, units, text: formatter.format(count, units) })
5252+ // Intl.RelativeTimeFormat do its magic
5353+ callback({
5454+ seconds: seconds,
5555+ count,
5656+ units,
5757+ text: formatter.format(count, units),
5858+ });
41594242- // calculate time to next update, taking account rounding (e.g. it goes from 2 minutes to 1 minute at 90 seconds)
4343- // and also the changeover from units (59 seconds shouldn't show as 1 minute, so at 61 seconds we schedule the next
4444- // update for 1 second time)
6060+ // calculate time to next update, taking account rounding (e.g. it goes from 2 minutes to 1 minute at 90 seconds)
6161+ // and also the changeover from units (59 seconds shouldn't show as 1 minute, so at 61 seconds we schedule the next
6262+ // update for 1 second time)
45634646- const divisorMs = divisor * 1000
6464+ const divisorMs = divisor * 1000;
47654848- let updateIn
6666+ let updateIn;
49675050- if (unitIndex) {
5151- updateIn = divisorMs / 2 - (Math.abs(delta) % divisorMs)
5252- if (updateIn < 0) {
5353- updateIn += divisorMs
5454- }
5555- } else {
5656- updateIn = divisorMs - (Math.abs(delta) % divisorMs)
5757- }
6868+ if (unitIndex) {
6969+ updateIn = divisorMs / 2 - (Math.abs(delta) % divisorMs);
7070+ if (updateIn < 0) {
7171+ updateIn += divisorMs;
7272+ }
7373+ } else {
7474+ updateIn = divisorMs - (Math.abs(delta) % divisorMs);
7575+ }
58765959- const updateAt = now + updateIn
7777+ const updateAt = now + updateIn;
60786161- return updateAt
7979+ return updateAt;
6280}
+43-37
src/components/bluesky/relative-time/state.ts
···11-import { getFormatter } from './formatter'
22-import { render } from './render'
33-import type { Callback, RenderState } from './render'
11+import { getFormatter } from "./formatter";
22+import { render } from "./render";
33+import type { Callback, RenderState } from "./render";
4455interface UpdateState extends RenderState {
66- update: number
66+ update: number;
77}
8899// keep track of each instance
1010-const instances = new Map<Object, UpdateState>()
1010+const instances = new Map<Object, UpdateState>();
11111212// we use a single timer for efficiency and to keep updates in sync
1313-let updateInterval: number | NodeJS.Timeout
1313+let updateInterval: number | NodeJS.Timeout;
14141515// register or update instance
1616-export function register(instance: Object, date: Date | number, locale: string, live: boolean, callback: Callback) {
1717- // get the formatter for the given locale, we do this here so we don't keep having to look it up on each tick
1818- const formatter = getFormatter(locale)
1616+export function register(
1717+ instance: Object,
1818+ date: Date | number,
1919+ locale: string,
2020+ live: boolean,
2121+ callback: Callback,
2222+) {
2323+ // get the formatter for the given locale, we do this here so we don't keep having to look it up on each tick
2424+ const formatter = getFormatter(locale);
19252020- // create state to render
2121- const state = { date, callback, formatter }
2626+ // create state to render
2727+ const state = { date, callback, formatter };
22282323- // initial render is immediate, so works for SSR
2424- const update = render(state, Date.now())
2929+ // initial render is immediate, so works for SSR
3030+ const update = render(state, Date.now());
25312626- // if it's to update live, we keep a track and schedule the next update
2727- if (live) {
2828- instances.set(instance, { ...state, update })
2929- } else {
3030- instances.delete(instance)
3131- }
3232+ // if it's to update live, we keep a track and schedule the next update
3333+ if (live) {
3434+ instances.set(instance, { ...state, update });
3535+ } else {
3636+ instances.delete(instance);
3737+ }
32383333- // start the clock ticking if there are any live instances
3434- if (instances.size) {
3535- updateInterval =
3636- updateInterval ||
3737- setInterval(() => {
3838- const now = Date.now()
3939- for (const state of instances.values()) {
4040- if (state.update <= now) {
4141- state.update = render(state, now)
4242- }
4343- }
4444- }, 1000)
4545- }
3939+ // start the clock ticking if there are any live instances
4040+ if (instances.size) {
4141+ updateInterval =
4242+ updateInterval ||
4343+ setInterval(() => {
4444+ const now = Date.now();
4545+ for (const state of instances.values()) {
4646+ if (state.update <= now) {
4747+ state.update = render(state, now);
4848+ }
4949+ }
5050+ }, 1000);
5151+ }
4652}
47534854export function unregister(instance: Object) {
4949- instances.delete(instance)
5050- if (instances.size === 0) {
5151- clearInterval(updateInterval)
5252- updateInterval = 0
5353- }
5555+ instances.delete(instance);
5656+ if (instances.size === 0) {
5757+ clearInterval(updateInterval);
5858+ updateInterval = 0;
5959+ }
5460}
···11<script lang="ts">
22- import { BASE } from "../../config.json";
22+ import { BASE } from "../../config.ts";
3344 import { fade, slide } from "svelte/transition";
55 import type { Pagefind } from "vite-plugin-pagefind/types";
···11+import type { AccentColor, BaseColor } from "./colors";
22+33+// if deployed to github pages, set to https://<your-github-username>.github.io/
44+export const SITE = "https://flo-bit.dev";
55+66+// if deployed to github pages, set to '/<your-repo-name>'
77+// EXCEPT if repo name is <your-github-username>.github.io
88+// in that case set to '/'
99+export const BASE = "/blog-template";
1010+1111+// will be used for the the title and meta tags and in the header (if SITE_NAME is left blank)
1212+export const SITE_TITLE = "Blog template";
1313+1414+// will be used in the meta tags (and for example shown in search results)
1515+export const SITE_DESCRIPTION = "Welcome to my website!";
1616+1717+// will be used as the icon in the header and the favicon
1818+export const SITE_FAVICON = "🙃";
1919+2020+// will be used in the footer as the name of the author (c) <YEAR> <NAME> - LICENSE
2121+export const NAME = "flo-bit";
2222+2323+// will be used in the footer as the license of the content (e.g. "All right reserved" or "CC-BY-SA 4.0")
2424+export const LICENSE = "All rights reserved.";
2525+2626+// will be used to identify your bluesky account, so that likes and comments can be shown on your posts
2727+export const BLUESKY_IDENTIFIER = "flo-bit.dev";
2828+2929+// will be used to set the base color of the blog
3030+export const BASE_COLOR: BaseColor = "stone";
3131+3232+// will be used to set the accent color of the blog
3333+export const ACCENT_COLOR: AccentColor = "rose";
3434+3535+export const SOCIAL_LINKS: {
3636+ FACEBOOK_URL?: string;
3737+ TWITTER_URL?: string;
3838+ GITHUB_URL?: string;
3939+ INSTAGRAM_URL?: string;
4040+ LINKEDIN_URL?: string;
4141+ YOUTUBE_URL?: string;
4242+ SUBSTACK_URL?: string;
4343+ EMAIL?: string;
4444+ BLUESKY_URL?: string;
4545+ SHOW_RSS?: boolean;
4646+} = {
4747+ SHOW_RSS: true,
4848+ FACEBOOK_URL: "https://www.facebook.com/flo-bit.dev",
4949+ TWITTER_URL: "https://twitter.com/flo_bit",
5050+ GITHUB_URL: "https://github.com/flo-bit",
5151+ INSTAGRAM_URL: "https://www.instagram.com/flo_bit",
5252+};
5353+// if true, will show theme toggle in header (otherwise theme is automatically detected and can't be changed by the readers)
5454+export const MANUAL_DARK_MODE = true;
5555+5656+// if true, will enable the search functionality
5757+export const SEARCH_ENABLED = true;
5858+5959+// if true, will show images in the posts
6060+export const SHOW_IMAGES = true;
6161+6262+// will be used to set the number of posts per page
6363+export const POSTS_PER_PAGE = 5;
6464+6565+// will be shown in the header, if left blank will instead show the SITE_TITLE
6666+export const SITE_NAME = "";
6767+6868+// if true, will show the SITE_FAVICON in the header
6969+export const SHOW_FAVICON_IN_HEADER = true;
+7-8
src/content.config.ts
···11import { defineCollection, z } from "astro:content";
22-import { glob } from 'astro/loaders';
22+import { glob } from "astro/loaders";
3344const blog = defineCollection({
55- loader: glob({ pattern: '**/[^_]*.{md,mdx}', base: "./src/content/blog/" }),
66- // Type-check frontmatter using a schema
77- schema: z.object({
55+ loader: glob({ pattern: "**/[^_]*.{md,mdx}", base: "./src/content/blog/" }),
66+ // Type-check frontmatter using a schema
77+ schema: z.object({
88 // title of the blog post, don't repeat this in the markdown part
99 title: z.string(),
1010···1414 disableComments: z.boolean().optional(),
15151616 disableLikes: z.boolean().optional(),
1717-1717+1818 // date published
1919 pubDate: z.coerce.date(),
2020···41414242 // whether to use the hero image as the og image (instead of the default `/src/assets/background.png`)
4343 useHeroAsOGImage: z.boolean().optional(),
4444-4444+4545 // wether to show title and short description in the og image
4646 noTextInOGImage: z.boolean().optional(),
4747 }),
4848});
49495050import { authorFeedLoader } from "@ascorbic/bluesky-loader";
5151-import { BLUESKY_IDENTIFIER } from "./config.json";
5252-5151+import { BLUESKY_IDENTIFIER } from "./config.ts";
53525453const posts = defineCollection({
5554 loader: authorFeedLoader({
+5-5
src/content/blog/comments-via-bluesky.mdx
···10101111## How it works
12121313-Set the `BLUESKY_IDENTIFIER` in your `src/config.json` file to your bluesky handle (without the `@`).
1313+Set the `BLUESKY_IDENTIFIER` in your `src/config.ts` file to your bluesky handle (without the `@`).
14141515Then just post a link to your blog post on bluesky and comments will be shown on your blog posts, looking something like this:
16161717<div class="max-w-md rounded-xl overflow-hidden border border-base-200 dark:border-base-800 shadow-lg not-prose">
1818- 
1818+ 
1919</div>
20202121Note that no "add comment" link is shown if there is no post on bluesky linking to your blog post.
22222323-Comments are both server-side rendered on build and updated on the client when you navigate to the page
2323+Comments are both server-side rendered on build and updated on the client when you navigate to the page
2424(so they work without javascript, but might be a bit outdated).
25252626-If you post a link to your blog post on bluesky, likes will also be shown (see [likes via bluesky](../likes-via-bluesky)).
2626+If you post a link to your blog post on bluesky, likes will also be shown (see [likes via bluesky](../likes-via-bluesky)).
2727If you don't want to show likes, you can disable them using the `disableLikes` option in your post options.
28282929```yml
3030disableLikes: true
3131```
32323333-See a live example below:3333+See a live example below:
+1-1
src/content/blog/configuring-the-blog.mdx
···66tags: ["setup"]
77---
8899-Change the values in `src/config.json` to configure the blog to your liking, see below for more information.
99+Change the values in `src/config.ts` to configure the blog to your liking, see below for more information.
10101111## SITE
1212
+1-1
src/content/blog/features.mdx
···1919- ✅ Tag your posts
2020- ✅ Super easy to deploy as a static site
2121- ✅ Includes some prebuilt components for you to use
2222-- ✅ Likes and comments via bluesky2222+- ✅ Likes and comments via bluesky
+2-2
src/content/blog/how-to-use.mdx
···88991. Fork [the repository of this blog](https://github.com/flo-bit/blog-template) (note: this repository per default uses github actions which are only free for public repositories)
10101111-2. In your repository settings, set up github pages to deploy using github actions (*SETTINGS* -> *PAGES* -> *SOURCE*: **Github Actions**)
1111+2. In your repository settings, set up github pages to deploy using github actions (_SETTINGS_ -> _PAGES_ -> _SOURCE_: **Github Actions**)
12121313-3. Set up your blog info in `src/config.json` (see [all options](../configuring-the-blog))
1313+3. Set up your blog info in `src/config.ts` (see [all options](../configuring-the-blog))
141415154. Your blog should be live in about 1 minute at `https://<your-github-username>.github.io/<your-repo-name>`
1616
+5-5
src/content/blog/likes-via-bluesky.mdx
···13131414## How it works
15151616-Set the `BLUESKY_IDENTIFIER` in your `src/config.json` file to your bluesky handle (without the `@`).
1616+Set the `BLUESKY_IDENTIFIER` in your `src/config.ts` file to your bluesky handle (without the `@`).
17171818Then just post a link to your blog post on bluesky and likes will be shown on your blog posts, looking something like this:
19192020<div class="max-w-md rounded-xl overflow-hidden border border-base-200 dark:border-base-800 shadow-lg not-prose">
2121- 
2121+ 
2222</div>
23232424Note that no like link is shown if there is no post on bluesky linking to your blog post.
25252626-Likes are both server-side rendered on build and updated on the client when you navigate to the page
2626+Likes are both server-side rendered on build and updated on the client when you navigate to the page
2727(so they work without javascript, but might be a bit outdated).
28282929-If you post a link to your blog post on bluesky, comments will also be shown (see [comments via bluesky](../comments-via-bluesky)).
2929+If you post a link to your blog post on bluesky, comments will also be shown (see [comments via bluesky](../comments-via-bluesky)).
3030If you don't want to show comments, you can disable them using the `disableComments` option in your post options.
31313232```yml
3333disableComments: true
3434```
35353636-See a live example below:3636+See a live example below:
+5-5
src/content/blog/showing-code.mdx
···66tags: ["code", "markdown"]
77---
8899-109this is some `inline code`
11101211this is some multiline code:
···18171918const b = "this is a string";
20192121-console.log(b);// [!code highlight]
2020+console.log(b); // [!code highlight]
22212322function test() {
2424- const test = "this is a very long string, that should hopefully wrap onto multiple lines"; // [!code highlight]
2323+ const test =
2424+ "this is a very long string, that should hopefully wrap onto multiple lines"; // [!code highlight]
25252626- console.log(test);
2626+ console.log(test);
2727}
2828-```2828+```
···2233Get the [source code here](https://github.com/flo-bit/blog-template)
4455-Minimalistic but opinionated blog template using [astro](https://astro.build/) and [svelte](https://svelte.dev/).
66-aims to be super easy to deploy and use, with a focus on performance and SEO, ease-of-use and design
55+Minimalistic but opinionated blog template using [astro](https://astro.build/) and [svelte](https://svelte.dev/).
66+aims to be super easy to deploy and use, with a focus on performance and SEO, ease-of-use and design
77(see all [features here](/blog-template/posts/features)).
8899-This blog doubles as a tutorial on how to use this template, start by [setting up your github repo](/blog-template/posts/how-to-use),
99+This blog doubles as a tutorial on how to use this template, start by [setting up your github repo](/blog-template/posts/how-to-use),
1010then [add some content](/blog-template/posts/adding-content). For more information read about [supported markdown features here](/blog-template/posts/markdown-style-guide).
1111+1212+If you want to, I'd appreciate it if you add something like this here (not required):
1313+1414+> This blog was created with [this astro blog template](https://github.com/flo-bit/blog-template) by [flo-bit](https://flo-bit.dev)
···11export default function urlMatcher(url: string): string | undefined {
22- // should be an absolute path to an svg file
33- if (url.startsWith("/src/") && url.endsWith(".svg")) {
44- return url;
55- }
66- return undefined;
77-}22+ // should be an absolute path to an svg file
33+ if (url.startsWith("/src/") && url.endsWith(".svg")) {
44+ return url;
55+ }
66+ return undefined;
77+}
-1
src/embeds/index.ts
···11-21import LinkCard from "./link-card/LinkCard.astro";
32import YouTube from "./youtube/YouTube.astro";
43import Excalidraw from "./excalidraw/Excalidraw.astro";
···3344// Function to return only the URL part
55export default function urlMatcher(url: string): string | undefined {
66- const match = url.match(urlPattern);
77- return match?.[0];
88-}66+ const match = url.match(urlPattern);
77+ return match?.[0];
88+}
+2-2
src/embeds/matcher.ts
···11-import YoutubeMatcher from './youtube/matcher.ts';
22-import LinkMatcher from './link-card/matcher.ts';
11+import YoutubeMatcher from "./youtube/matcher.ts";
22+import LinkMatcher from "./link-card/matcher.ts";
33export { YoutubeMatcher, LinkMatcher };
···11// Thanks to eleventy-plugin-youtube-embed
22// https://github.com/gfscott/eleventy-plugin-youtube-embed/blob/main/lib/extractMatches.js
33const urlPattern =
44- /(?=(\s*))\1(?:<a [^>]*?>)??(?=(\s*))\2(?:https?:\/\/)??(?:w{3}\.)??(?:youtube\.com|youtu\.be)\/(?:watch\?v=|embed\/|shorts\/)??([A-Za-z0-9-_]{11})(?:[^\s<>]*)(?=(\s*))\4(?:<\/a>)??(?=(\s*))\5/;
44+ /(?=(\s*))\1(?:<a [^>]*?>)??(?=(\s*))\2(?:https?:\/\/)??(?:w{3}\.)??(?:youtube\.com|youtu\.be)\/(?:watch\?v=|embed\/|shorts\/)??([A-Za-z0-9-_]{11})(?:[^\s<>]*)(?=(\s*))\4(?:<\/a>)??(?=(\s*))\5/;
5566/**
77 * Extract a YouTube ID from a URL if it matches the pattern.
···99 * @returns A YouTube video ID or undefined if none matched
1010 */
1111export default function matcher(url: string): string | undefined {
1212- const match = url.match(urlPattern);
1313- return match?.[3];
1212+ const match = url.match(urlPattern);
1313+ return match?.[3];
1414}
+1-1
src/layouts/PostList.astro
···11---
22-import { SITE_TITLE, SITE_DESCRIPTION } from "../config.json";
22+import { SITE_TITLE, SITE_DESCRIPTION } from "../config.ts";
3344import Footer from "$components/Footer.astro";
55import Header from "$components/Header.astro";
+1-1
src/layouts/ProseWrapper.astro
···11---
22import { colorBaseClasses, colorAccentClasses } from "src/colors";
33-import { ACCENT_COLOR, BASE_COLOR } from "../config.json";
33+import { ACCENT_COLOR, BASE_COLOR } from "../config.ts";
4455const { class: className } = Astro.props;
66---
+1-1
src/pages/about/index.astro
···11---
22-import { SITE_TITLE, SITE_DESCRIPTION } from "../../config.json";
22+import { SITE_TITLE, SITE_DESCRIPTION } from "../../config.ts";
3344import Footer from "$components/Footer.astro";
55import Header from "$components/Header.astro";
+1-1
src/pages/index.astro
···11---
22-import { POSTS_PER_PAGE } from "../config.json";
22+import { POSTS_PER_PAGE } from "../config.ts";
33import { getBlogPosts } from "src/utils";
44import PostList from "$layouts/PostList.astro";
55
···11---
22-import { POSTS_PER_PAGE } from "../../config.json";
22+import { POSTS_PER_PAGE } from "../../config.ts";
33import { getBlogPosts } from "src/utils";
44import PostList from "$layouts/PostList.astro";
55
+1-1
src/pages/posts/[...slug].astro
···99import { getBlogPosts } from "src/utils";
1010import BlueskyLikes from "$components/bluesky/BlueskyLikes.astro";
1111import Tag from "$components/Tag.astro";
1212-import { SHOW_IMAGES } from "../../config.json";
1212+import { SHOW_IMAGES } from "../../config.ts";
13131414export async function getStaticPaths() {
1515 const posts = await getBlogPosts();
+1-1
src/pages/rss.xml.js
···11import rss from "@astrojs/rss";
22-import { SITE_TITLE, SITE_DESCRIPTION, BASE } from "../config.json";
22+import { SITE_TITLE, SITE_DESCRIPTION, BASE } from "../config.ts";
33import { getBlogPosts } from "src/utils";
4455export async function GET(context) {
+1-1
src/pages/tags/[...tag]/[...index].astro
···11---
22-import { POSTS_PER_PAGE } from "../../../config.json";
22+import { POSTS_PER_PAGE } from "../../../config.ts";
3344import { getBlogPosts } from "src/utils";
55import PostList from "$layouts/PostList.astro";
+3-3
src/style-utils.ts
···11-import { type ClassValue, clsx } from 'clsx';
22-import { twMerge } from 'tailwind-merge';
11+import { type ClassValue, clsx } from "clsx";
22+import { twMerge } from "tailwind-merge";
3344export function cn(...inputs: ClassValue[]) {
55- return twMerge(clsx(inputs));
55+ return twMerge(clsx(inputs));
66}
+1-1
tailwind.config.mjs
···22import forms from "@tailwindcss/forms";
33import plugin from "tailwindcss/plugin";
44import colors from "tailwindcss/colors";
55-import { ACCENT_COLOR, BASE_COLOR, MANUAL_DARK_MODE } from "./src/config.json";
55+import { ACCENT_COLOR, BASE_COLOR, MANUAL_DARK_MODE } from "./src/config.ts";
6677/** @type {import('tailwindcss').Config} */
88export default {