Skip to content

Commit 6faf428

Browse files
authored
Merge pull request #6 from ruivieira/users-avatars
feat: Add support for authors and authors page
2 parents 91f579e + 5ac3f26 commit 6faf428

File tree

11 files changed

+546
-10
lines changed

11 files changed

+546
-10
lines changed

public/authors/rui-vieira.jpg

352 KB
Loading

src/components/AuthorCard.astro

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
---
2+
export interface Props {
3+
name: string;
4+
bio: string;
5+
avatar?: string;
6+
size?: 'small' | 'medium' | 'large';
7+
showBio?: boolean;
8+
href?: string;
9+
}
10+
11+
const { name, bio, avatar, size = 'medium', showBio = true, href } = Astro.props;
12+
13+
const sizeClasses = {
14+
small: 'author-card-small',
15+
medium: 'author-card-medium',
16+
large: 'author-card-large'
17+
};
18+
---
19+
20+
<div class={`author-card ${sizeClasses[size]}`}>
21+
{href ? (
22+
<a href={href} class="author-link">
23+
{avatar && (
24+
<img
25+
src={avatar.startsWith('/') ? `${import.meta.env.BASE_URL}/${avatar.slice(1)}` : avatar}
26+
alt={name}
27+
class="author-avatar"
28+
/>
29+
)}
30+
<div class="author-info">
31+
<h3 class="author-name">{name}</h3>
32+
{showBio && <p class="author-bio">{bio}</p>}
33+
</div>
34+
</a>
35+
) : (
36+
<>
37+
{avatar && (
38+
<img
39+
src={avatar.startsWith('/') ? `${import.meta.env.BASE_URL}/${avatar.slice(1)}` : avatar}
40+
alt={name}
41+
class="author-avatar"
42+
/>
43+
)}
44+
<div class="author-info">
45+
<h3 class="author-name">{name}</h3>
46+
{showBio && <p class="author-bio">{bio}</p>}
47+
</div>
48+
</>
49+
)}
50+
</div>
51+
52+
<style>
53+
.author-card {
54+
display: flex;
55+
align-items: center;
56+
gap: 1rem;
57+
}
58+
59+
.author-link {
60+
display: flex;
61+
align-items: center;
62+
gap: 1rem;
63+
text-decoration: none;
64+
color: inherit;
65+
width: 100%;
66+
}
67+
68+
.author-avatar {
69+
border-radius: 50%;
70+
object-fit: cover;
71+
flex-shrink: 0;
72+
}
73+
74+
.author-info {
75+
flex: 1;
76+
}
77+
78+
.author-name {
79+
margin: 0;
80+
font-weight: 500;
81+
color: rgb(var(--black));
82+
}
83+
84+
.author-bio {
85+
margin: 0.25rem 0 0 0;
86+
color: rgb(var(--gray-dark));
87+
line-height: 1.4;
88+
}
89+
90+
/* Size variations */
91+
.author-card-small .author-avatar {
92+
width: 32px;
93+
height: 32px;
94+
}
95+
96+
.author-card-small .author-name {
97+
font-size: 0.9rem;
98+
}
99+
100+
.author-card-small .author-bio {
101+
font-size: 0.8rem;
102+
}
103+
104+
.author-card-medium .author-avatar {
105+
width: 48px;
106+
height: 48px;
107+
}
108+
109+
.author-card-medium .author-name {
110+
font-size: 1rem;
111+
}
112+
113+
.author-card-medium .author-bio {
114+
font-size: 0.9rem;
115+
}
116+
117+
.author-card-large .author-avatar {
118+
width: 64px;
119+
height: 64px;
120+
}
121+
122+
.author-card-large .author-name {
123+
font-size: 1.2rem;
124+
}
125+
126+
.author-card-large .author-bio {
127+
font-size: 1rem;
128+
}
129+
</style>

src/components/Header.astro

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { SITE_TITLE } from '../consts';
1313
<HeaderLink href={`${import.meta.env.BASE_URL}/research`}>Research</HeaderLink>
1414
<HeaderLink href={`${import.meta.env.BASE_URL}/engineering`}>Engineering</HeaderLink>
1515
<HeaderLink href={`${import.meta.env.BASE_URL}/community`}>Community</HeaderLink>
16+
<HeaderLink href={`${import.meta.env.BASE_URL}/authors`}>Authors</HeaderLink>
1617
<HeaderLink href="https://trustyai-explainability.github.io/trustyai-site/main/main.html" target="_blank">Documentation</HeaderLink>
1718
</div>
1819
<div class="social-links">
@@ -44,18 +45,18 @@ import { SITE_TITLE } from '../consts';
4445
background: white;
4546
box-shadow: 0 2px 8px rgba(var(--black), 5%);
4647
}
47-
48+
4849
.site-branding {
4950
display: flex;
5051
align-items: center;
5152
gap: 0.75rem;
5253
}
53-
54+
5455
.logo {
5556
height: 2.5rem;
5657
width: auto;
5758
}
58-
59+
5960
h2 {
6061
margin: 0;
6162
font-size: 1em;
@@ -88,7 +89,7 @@ import { SITE_TITLE } from '../consts';
8889
.social-links {
8990
display: none;
9091
}
91-
92+
9293
.logo {
9394
height: 2rem;
9495
}

src/content.config.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,25 @@ const blog = defineCollection({
1313
updatedDate: z.coerce.date().optional(),
1414
heroImage: z.string().optional(),
1515
track: z.enum(['research', 'engineering', 'community']),
16+
authors: z.array(z.string()).optional(),
1617
}),
1718
});
1819

19-
export const collections = { blog };
20+
const authors = defineCollection({
21+
// Load Markdown and MDX files in the `src/content/authors/` directory.
22+
loader: glob({ base: './src/content/authors', pattern: '**/*.{md,mdx}' }),
23+
// Type-check frontmatter using a schema
24+
schema: z.object({
25+
name: z.string(),
26+
bio: z.string().optional(),
27+
avatar: z.string().optional(),
28+
email: z.string().optional(),
29+
mastodon: z.string().optional(),
30+
bluesky: z.string().optional(),
31+
linkedin: z.string().optional(),
32+
github: z.string().optional(),
33+
website: z.string().optional(),
34+
}),
35+
});
36+
37+
export const collections = { blog, authors };

src/content/authors/rui-vieira.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
name: 'Rui Vieira'
3+
avatar: '/authors/rui-vieira.jpg'
4+
email: 'ruidevieira@googlemail.com'
5+
mastodon: '@ruivieira@fosstodon.org'
6+
linkedin: 'ruimvieira'
7+
github: 'ruivieira'
8+
website: 'https://ruivieira.dev'
9+
---

src/content/blog/community/welcome-to-community.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ description: 'Here is a sample of some basic Markdown syntax that can be used wh
44
pubDate: 'Dec 01 2024'
55
heroImage: '/blog-placeholder-3.jpg'
66
track: 'community'
7+
authors: ['rui-vieira']
78
---
89

910
Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro.

src/content/blog/first-post.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ description: 'Here is a sample of some basic Markdown syntax that can be used wh
44
pubDate: 'Jul 08 2022'
55
heroImage: '/blog-placeholder-3.jpg'
66
track: 'research'
7+
authors: ['rui-vieira']
78
---
89

910
Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro.
@@ -51,13 +52,13 @@ The blockquote element represents content that is quoted from another source, op
5152
#### Syntax
5253

5354
```markdown
54-
> Tiam, ad mint andaepu dandae nostion secatur sequo quae.
55+
> Tiam, ad mint andaepu dandae nostion secatur sequo quae.
5556
> **Note** that you can use _Markdown syntax_ within a blockquote.
5657
```
5758

5859
#### Output
5960

60-
> Tiam, ad mint andaepu dandae nostion secatur sequo quae.
61+
> Tiam, ad mint andaepu dandae nostion secatur sequo quae.
6162
> **Note** that you can use _Markdown syntax_ within a blockquote.
6263
6364
### Blockquote with attribution

src/content/blog/second-post.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ description: 'Here is a sample of some basic Markdown syntax that can be used wh
44
pubDate: 'Jul 15 2022'
55
heroImage: '/blog-placeholder-4.jpg'
66
track: 'engineering'
7+
authors: ['rui-vieira']
78
---
89

910
Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro.
@@ -51,13 +52,13 @@ The blockquote element represents content that is quoted from another source, op
5152
#### Syntax
5253

5354
```markdown
54-
> Tiam, ad mint andaepu dandae nostion secatur sequo quae.
55+
> Tiam, ad mint andaepu dandae nostion secatur sequo quae.
5556
> **Note** that you can use _Markdown syntax_ within a blockquote.
5657
```
5758

5859
#### Output
5960

60-
> Tiam, ad mint andaepu dandae nostion secatur sequo quae.
61+
> Tiam, ad mint andaepu dandae nostion secatur sequo quae.
6162
> **Note** that you can use _Markdown syntax_ within a blockquote.
6263
6364
### Blockquote with attribution

src/layouts/BlogPost.astro

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
---
22
import type { CollectionEntry } from 'astro:content';
3+
import { getCollection } from 'astro:content';
34
import BaseHead from '../components/BaseHead.astro';
45
import Header from '../components/Header.astro';
56
import Footer from '../components/Footer.astro';
67
import FormattedDate from '../components/FormattedDate.astro';
78
89
type Props = CollectionEntry<'blog'>['data'];
910
10-
const { title, description, pubDate, updatedDate, heroImage } = Astro.props;
11+
const { title, description, pubDate, updatedDate, heroImage, authors } = Astro.props;
12+
13+
// Get author information if authors are specified
14+
let authorData: CollectionEntry<'authors'>[] = [];
15+
if (authors && authors.length > 0) {
16+
const allAuthors = await getCollection('authors');
17+
authorData = allAuthors.filter(author => authors.includes(author.id));
18+
}
1119
---
1220

1321
<html lang="en">
@@ -51,6 +59,37 @@ const { title, description, pubDate, updatedDate, heroImage } = Astro.props;
5159
.last-updated-on {
5260
font-style: italic;
5361
}
62+
.authors {
63+
margin: 1em 0;
64+
display: flex;
65+
flex-wrap: wrap;
66+
justify-content: center;
67+
gap: 1rem;
68+
}
69+
.author {
70+
display: flex;
71+
align-items: center;
72+
gap: 0.5rem;
73+
padding: 0.5rem;
74+
border-radius: 8px;
75+
background: rgba(var(--accent-light), 0.1);
76+
text-decoration: none;
77+
color: inherit;
78+
transition: background-color 0.2s ease;
79+
}
80+
.author:hover {
81+
background: rgba(var(--accent-light), 0.2);
82+
}
83+
.author-avatar {
84+
width: 32px;
85+
height: 32px;
86+
border-radius: 50%;
87+
object-fit: cover;
88+
}
89+
.author-name {
90+
font-weight: 500;
91+
color: rgb(var(--black));
92+
}
5493
</style>
5594
</head>
5695

@@ -74,6 +113,22 @@ const { title, description, pubDate, updatedDate, heroImage } = Astro.props;
74113
}
75114
</div>
76115
<h1>{title}</h1>
116+
{authorData.length > 0 && (
117+
<div class="authors">
118+
{authorData.map((author) => (
119+
<a href={`${import.meta.env.BASE_URL}/authors/${author.id}/`} class="author">
120+
{author.data.avatar && (
121+
<img
122+
src={author.data.avatar.startsWith('/') ? `${import.meta.env.BASE_URL}/${author.data.avatar.slice(1)}` : author.data.avatar}
123+
alt={author.data.name}
124+
class="author-avatar"
125+
/>
126+
)}
127+
<span class="author-name">{author.data.name}</span>
128+
</a>
129+
))}
130+
</div>
131+
)}
77132
<hr />
78133
</div>
79134
<slot />

0 commit comments

Comments
 (0)