Compare commits
3 Commits
df223a7b44
...
75a9ea5fce
Author | SHA1 | Date | |
---|---|---|---|
75a9ea5fce | |||
8111bdd318 | |||
a57b48af3a |
77
README.md
77
README.md
@ -1,7 +1,82 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
# justin.deal
|
# justin.deal
|
||||||
|
|
||||||
My personal website and blog.
|
My personal website and blog.
|
||||||
|
=======
|
||||||
|

|
||||||
|
|
||||||
|
Zaggonaut is a retro-inspired theme for Astro, built using TypeScript, TailwindCSS, and of course, Astro.
|
||||||
|
|
||||||
Check out [the website](https://justin.deal) to give it a spin!
|
## Getting Started
|
||||||
|
|
||||||
|
[View the demo](https://zaggonaut.dev) or [view the source code](https://github.com/RATIU5/zaggonaut).
|
||||||
|
|
||||||
|
Alternatively, you can create a new Astro project with Zaggonaut like this:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# pnpm
|
||||||
|
pnpm create astro@latest --template RATIU5/zaggonaut
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> Currently, `pnpm` is the only supported package manager due to `pnpm` throwing peer-dependency conflicts.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Dark & light mode
|
||||||
|
- Customizable colors
|
||||||
|
- 100 / 100 Lighthouse score
|
||||||
|
- Fully accessible
|
||||||
|
- Fully responsive
|
||||||
|
- Type-safe
|
||||||
|
- SEO-friendly
|
||||||
|
|
||||||
|
## Customization
|
||||||
|
|
||||||
|
The entire theme is fully customizable. The theme is setup a specific way to make it easy to customize.
|
||||||
|
|
||||||
|
### Colors
|
||||||
|
|
||||||
|
You can customize the colors of the theme by editing the `src/styles/global.css` file.
|
||||||
|
This file uses Tailwind CSS and CSS variables to customize the colors of the theme.
|
||||||
|
Zaggonaut uses the following CSS variables:
|
||||||
|
|
||||||
|
- `--color-zag-dark`: The dark color of the theme
|
||||||
|
- `--color-zag-light`: The light color of the theme
|
||||||
|
- `--color-zag-dark-muted`: The dark color of the theme with a slight opacity
|
||||||
|
- `--color-zag-light-muted`: The light color of the theme with a slight opacity
|
||||||
|
- `--color-zag-accent-light`: The light accent color of the theme
|
||||||
|
- `--color-zag-accent-light-muted`: The light accent color of the theme with a slight opacity
|
||||||
|
- `--color-zag-accent-dark`: The dark accent color of the theme
|
||||||
|
- `--color-zag-accent-dark-muted`: The dark accent color of the theme with a slight opacity
|
||||||
|
|
||||||
|
### Text
|
||||||
|
|
||||||
|
You can customize the text of the theme by editing the `src/lib/variables.ts` file.
|
||||||
|
This file contains all of the text used throughout the theme.
|
||||||
|
|
||||||
|
For example, you can change the `username` variable to your own username and everywhere the username is used will be replaced with your username.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export const GLOBAL = {
|
||||||
|
// Site metadata
|
||||||
|
username: "zaggonaut-fan123",
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
// Profile image
|
||||||
|
profileImage: "profile.webp",
|
||||||
|
|
||||||
|
// Menu items
|
||||||
|
menu: {
|
||||||
|
home: "/",
|
||||||
|
projects: "/projects",
|
||||||
|
blog: "/blog",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ready To Try?
|
||||||
|
|
||||||
|
Check out [the theme website](https://zaggonaut.dev) to give it a spin!
|
||||||
|
>>>>>>> beeac98 (initial commit)
|
||||||
|
@ -8,22 +8,30 @@ export type Props = {
|
|||||||
url: string;
|
url: string;
|
||||||
duration?: string;
|
duration?: string;
|
||||||
timestamp?: string;
|
timestamp?: string;
|
||||||
|
tags?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const { title, description, url, duration, timestamp } = Astro.props;
|
const { title, description, url, duration, timestamp, tags } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="zag-text zag-transition flex flex-col gap-3 pb-8">
|
<div class="zag-text zag-transition flex flex-col gap-3 pb-8">
|
||||||
<Anchor url={url} class="text-xl">
|
<Anchor url={url} class="text-xl">
|
||||||
{title}
|
{title}
|
||||||
</Anchor>
|
</Anchor>
|
||||||
|
<div
|
||||||
|
class="zag-muted zag-transition flex justify-between items-center"
|
||||||
|
>
|
||||||
|
{timestamp ? <p>{processArticleDate(timestamp)}</p> : null}
|
||||||
|
{duration ? <p>{duration}</p> : null}
|
||||||
|
</div>
|
||||||
<p class="">
|
<p class="">
|
||||||
{description}
|
{description}
|
||||||
</p>
|
</p>
|
||||||
<div
|
<div class="flex flex-wrap gap-2">
|
||||||
class="zag-muted zag-transition flex justify-between items-center"
|
{tags?.map((tag: string) => (
|
||||||
>
|
<span class="-zag-text -zag-bg zag-transition px-2 py-1 text-sm font-semibold">
|
||||||
{timestamp ? <p>{processArticleDate(timestamp)}</p> : null}
|
{tag}
|
||||||
{duration ? <p>{duration}</p> : null}
|
</span>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,6 +26,7 @@ const { featuredArticles } = Astro.props;
|
|||||||
url={article.filename}
|
url={article.filename}
|
||||||
timestamp={article.timestamp}
|
timestamp={article.timestamp}
|
||||||
duration={`${article.time} min`}
|
duration={`${article.time} min`}
|
||||||
|
tags={article.tags}
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
))
|
))
|
||||||
|
@ -50,6 +50,13 @@ const sourceUrl = generateSourceUrl(frontmatter.filename, "blog");
|
|||||||
<Prose>
|
<Prose>
|
||||||
<slot />
|
<slot />
|
||||||
</Prose>
|
</Prose>
|
||||||
|
<div class="flex flex-wrap gap-2 mt-4">
|
||||||
|
{frontmatter.tags?.map((tag) => (
|
||||||
|
<span class="-zag-text -zag-bg zag-transition px-2 py-1 text-sm font-semibold">
|
||||||
|
{tag}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
<p class="pt-8">~{GLOBAL.username}</p>
|
<p class="pt-8">~{GLOBAL.username}</p>
|
||||||
</Section>
|
</Section>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
@ -90,3 +90,15 @@ export const generateSourceUrl = (
|
|||||||
) => {
|
) => {
|
||||||
return `${GLOBAL.rootUrl}/${contentType}/${sourceUrl}`;
|
return `${GLOBAL.rootUrl}/${contentType}/${sourceUrl}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const countTags = (tags: string[]) => {
|
||||||
|
const tagCount: Record<string, number> = {};
|
||||||
|
tags.forEach((tag) => {
|
||||||
|
if (tagCount[tag]) {
|
||||||
|
tagCount[tag]++;
|
||||||
|
} else {
|
||||||
|
tagCount[tag] = 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return tagCount;
|
||||||
|
}
|
||||||
|
@ -7,4 +7,12 @@ time: 4
|
|||||||
featured: true
|
featured: true
|
||||||
timestamp: 2024-12-18T02:39:03+00:00
|
timestamp: 2024-12-18T02:39:03+00:00
|
||||||
filename: html-intro
|
filename: html-intro
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<div class="flex flex-wrap gap-2">
|
||||||
|
{tags.map((tag) => (
|
||||||
|
<span class="-zag-text -zag-bg zag-transition px-2 py-1 text-sm font-semibold">
|
||||||
|
{tag}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
@ -4,6 +4,9 @@ import Layout from "../../layouts/Layout.astro";
|
|||||||
import ArticleSnippet from "../../components/ArticleSnippet.astro";
|
import ArticleSnippet from "../../components/ArticleSnippet.astro";
|
||||||
import Section from "../../components/common/Section.astro";
|
import Section from "../../components/common/Section.astro";
|
||||||
import { articles } from "../../lib/list";
|
import { articles } from "../../lib/list";
|
||||||
|
import { countTags } from "../../lib/utils";
|
||||||
|
|
||||||
|
const tagCounts = countTags(articles.map((article) => article.tags).flat().filter((tag): tag is string => tag !== undefined));
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -33,9 +36,16 @@ import { articles } from "../../lib/list";
|
|||||||
<link rel="canonical" href={`${GLOBAL.rootUrl}/blog`} />
|
<link rel="canonical" href={`${GLOBAL.rootUrl}/blog`} />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
<Section class="my-8">
|
<Section class="my-8">
|
||||||
<div class="flex items-center gap-4 pt-8 pb-16">
|
<div class="flex items-center gap-4 pt-8 pb-4">
|
||||||
<h1 class="font-display text-3xl sm:text-4xl leading-loose">{GLOBAL.articlesName}</h1>
|
<h1 class="font-display text-3xl sm:text-4xl leading-loose">{GLOBAL.articlesName}</h1>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex flex-wrap gap-2 pb-16">
|
||||||
|
{Object.entries(tagCounts).map(([tag, count]) => (
|
||||||
|
<span class="-zag-text -zag-bg zag-transition px-2 py-1 text-sm font-semibold">
|
||||||
|
{tag}: {count}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
{
|
{
|
||||||
articles.map((project) => (
|
articles.map((project) => (
|
||||||
@ -46,6 +56,7 @@ import { articles } from "../../lib/list";
|
|||||||
duration={`${project.time} min`}
|
duration={`${project.time} min`}
|
||||||
url={project.filename}
|
url={project.filename}
|
||||||
timestamp={project.timestamp}
|
timestamp={project.timestamp}
|
||||||
|
tags={project.tags}
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
))
|
))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user