Skip to content

Commit 9af9990

Browse files
authored
Merge pull request #39 from edpacca/posts-015
Posts 015-2
2 parents f67eb49 + 41cf441 commit 9af9990

17 files changed

Lines changed: 141 additions & 21 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"type": "module",
55
"scripts": {
66
"dev": "vite dev",
7-
"build": "vite build",
7+
"build": "vite build --mode production",
88
"prod": "vite dev --mode=production --host 0.0.0.0 --port 8080",
99
"preview": "vite preview --host 0.0.0.0 --port 8080",
1010
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",

src/lib/data/galleries.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,17 @@ export const MINIATURE_SPOTLIGHT_IMG = '/images/miniatures/gallery/dw-knights-al
8080

8181
export const MINIATURE_GALLERY: ImageMetadata[] = [
8282
{
83-
path: '/images/miniatures/arch/build_1/s6_0.webp',
83+
path: '/images/miniatures/dw-librarian/finished-0-alpha.webp',
84+
alt: 'Deathwing Librarian',
85+
},
86+
{
87+
path: '/images/miniatures/arch/painting/p8_0.webp',
8488
alt: 'The Grand Archway'
8589
},
90+
{
91+
path: '/images/miniatures/diorama-strike-at-dawn/diorama-backdrop.webp',
92+
alt: 'Diorama: Strike at Dawn'
93+
},
8694
{
8795
path: '/images/miniatures/diorama-strike-at-dawn/diorama-0.webp',
8896
alt: 'Diorama: Strike at Dawn'
@@ -96,11 +104,16 @@ export const MINIATURE_GALLERY: ImageMetadata[] = [
96104
alt: 'Deathwing Knights',
97105
wide: true
98106
},
107+
{
108+
path: '/images/miniatures/gallery/frostgrave-dude.webp',
109+
alt: 'Tower Shield',
110+
},
99111
{
100112
path: '/images/miniatures/gallery/deathwing2-alpha.webp',
101113
alt: 'Ebay rescued Deathwing Terminators',
102114
wide: true
103115
},
116+
104117
{
105118
path: '/images/miniatures/gallery/intercessors-alpha.webp',
106119
alt: 'Primaris Intercessors',
@@ -124,6 +137,10 @@ export const MINIATURE_GALLERY: ImageMetadata[] = [
124137
path: '/images/miniatures/gallery/ravenwing-sergeant-alpha.webp',
125138
alt: 'Ravenwing Sergeant'
126139
},
140+
{
141+
path: '/images/miniatures/gallery/jerymiah-and-grim.webp',
142+
alt: 'Jerymiah Snagglebark and \'Grim\''
143+
},
127144
{
128145
path: '/images/miniatures/gallery/ezekiel-alpha.webp',
129146
alt: 'Grandmaster Librarian Ezekiel'

src/lib/pages/HomePage.svelte

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
<style>
2525
h1 {
2626
margin-bottom: 0.5rem;
27+
position: relative;
28+
z-index: 2;
2729
}
2830
2931
.wizard {
@@ -32,7 +34,7 @@
3234
right: 0;
3335
top: -1rem;
3436
margin: auto;
35-
z-index: -1;
37+
z-index: 1;
3638
text-align: center;
3739
animation: pop-in 360ms ease-in-out;
3840
}

src/lib/utils/post.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ const parsePinned = (pinned: boolean | undefined) => Number(pinned ?? 0);
33
// eslint-disable-next-line @typescript-eslint/no-explicit-any
44
const propIsType = (obj: any, prop: string, type: string) => typeof obj[prop] === type;
55

6-
const isDevPost = (post: Post) => (import.meta.env.DEV && post.dev) ?? false;
6+
const isDevPost = (post: Post) => post.dev ?? false;
7+
8+
const canLoadProdPost = (post: Post) => !post.dev && post.published;
79

810
export function comparePinnedPosts(p1: Post, p2: Post) {
911
return parsePinned(p2.pinned) - parsePinned(p1.pinned);
@@ -21,6 +23,12 @@ export function isPost(obj: unknown): obj is Post {
2123
);
2224
}
2325

24-
export function canLoadPost(post: unknown): boolean {
26+
export function canLoadPost(post: unknown, isEnvProd: boolean): boolean {
27+
if (isEnvProd || import.meta.env.PROD) // fallback to env
28+
{
29+
// if prod ignore dev posts
30+
return isPost(post) && canLoadProdPost(post);
31+
}
32+
// if dev - load dev posts
2533
return isPost(post) && (post.published || isDevPost(post));
2634
}

src/posts/diorama-strike-at-dawn.md

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
---
22
title: First Diorama - Strike at Dawn
33
description: I made a miniature diorama for a good friend of mine.
4-
date: 01/18/2025
4+
date: 01/18/2026
55
projectId: miniatures
66
published: true
7-
dev: true
87
icon: umbrella-beach
98
coverImage: miniatures/diorama-strike-at-dawn/diorama-backdrop.webp
109
footnotes:
@@ -67,35 +66,44 @@ The campfire is just pieces of sprue, shaved at jaunty angles to try to play int
6766

6867
I was already pleased with the outcome - it had this anticlockwise spiral moving up from the flattened area up to the edge of the cliff.
6968

70-
I wanted to draw the eye up from the campsite to the top of the cliff, and tried a few things before settling on a wee cat critter. This came from the [Frostgrave](https://www.ospreypublishing.com/uk/frostgrave-second-edition-9781472834683/) [Wizards II](https://www.northstarfigures.com/prod.php?prod=14244) sprue and really helps to tell the story of this piece. Cats tend to be associated with the night time, and I think it turns the perception of what this guy's mission might be - initially I was thinking a clandestine assassination but now perhaps he is delivering an important message, or maybe still in the darker realm of things, planting a shamanic cursed item within the Lord's abode...
69+
I wanted to draw the eye up from the campsite to the top of the cliff, and tried a few things before settling on a wee cat critter. This came from the [Frostgrave](https://www.ospreypublishing.com/uk/frostgrave-second-edition-9781472834683/) [Wizards II](https://www.northstarfigures.com/prod.php?prod=14244) sprue and really helps to tell the story of this piece. Cats tend to be associated with the night time, and I think it turns the perception of what this guy's mission might be - initially I was thinking a clandestine assassination but now perhaps he is delivering an important message. Or perhaps on the darker side of things, he intends to plant a cursed shamanic totem within the corrupt Lord's abode... although, why wait until dawn for that? wouldn't you want to break in during... ah nevermind.
7170

7271
![The cat critter surveys the valley](miniatures/diorama-strike-at-dawn/base-4.webp)
7372

7473
# Painting the base
7574

76-
I wish I had more photos of this process, but I put it together quite quickly in the end. I began with watered down browns, purples, greens and even a bit of khaki just building up thin layers and blending the hell out of them.
75+
When it came to painting, I knew I wanted to create a red OSL effect for the campfire. I'd been reading that the best way to get vibrancy was to use a light undercoat. So I took a can of bone colour (lightest spray I had) and applied a target spritz to the front of the base.
7776

78-
Then to try to achieve a moonlight glow I built up a light blue drybrush over the whole backside of the piece. I also dusted the plants with the same blue to tie them into the piece, after they were attached of course.
77+
I applied a few watered down coats of a red.orange mix. At first I wasn't too impressed with the result at first, but there is always a crap phase when painting so I soldiered on.
7978

80-
![I tried to make it look like night time..](miniatures/diorama-strike-at-dawn/diorama-5.webp)
79+
![Initially I didn't like it.](miniatures/diorama-strike-at-dawn/fire-in-progress.webp)
8180

82-
I tried to include more browns and warmer tones towards the front of the piece where the light was going to be coming from the campfire. I applied a very very thin layer of a dark red over the whole area, careful to try to leave shadows where they would be cast by the campfire. Then I painted a white over the campfire area before covering it in layers of orange, and building up to yellow. The logs themselves I tried to keep dark on the top. I tried to catch gentle bits of red under the cliff where light would flicker, and even put a tiny bit of red under the guy's hand.
81+
I wish I had more photos of this process, because it really transformed as I worked more colours onto the base. I began with watered down indigo, purple and applied more of a red brown towards the edges of the fire. I applied the colours in patches and blended them a bit by dragging my brush along the edges, whilst trying to leave distinct areas of certain colours.
8382

84-
Overall, it came out okay - I think it sells the effect I'm after. But I think if the piece had more detail I would need to do a better job of bringing contrast into the piece. We can imagine it's a cartoonish scene where there's more artificial light than in reality. Given the overall vibe I'm going for is whimsical fantasy, I'm pretty pleased!
83+
Then to try to achieve a moonlight glow on the rear side, I built up a light drybrush of pale blue over the whole backside of the piece. The next photo shows the subtle colour blending quite well.
84+
85+
![A subtle mix of colours](miniatures/diorama-strike-at-dawn/diorama-before-plants.webp)
86+
87+
I tried to include more browns and warmer tones towards the front of the piece at the edges where the light was coming from the campfire. Over time I was able to tame the initial intense blob to a nicer blend of shadow to firelight. Within the fire area itself I build up thin layers going towards orange and then yellow. The logs themselves I tried to keep dark on the top. I tried to catch gentle bits of red under the cliff where light would flicker, and even put a tiny bit of red under the guy's hand.
88+
89+
The final touch was to add some shrubs and plants. I aquired these awesome little pop-out plants from GamersGrass (I think?), which were already purple and tied into the night time aesthetic. I also added a few tufts and some realistic little bushes which are incredible and really brought that last little bit of life to the piece. I diluted some paint and washed the plants to tie them in, but the splash of green really offsets the blues and reds I think.
90+
91+
Overall, it came out pretty good considering the amount of experimentation going on. I don't think it quite sells the idea that this is midnight under a full moon, but it does tell a bit of a story. I think I could really lean in to the contrast and darked down the backside of the whole thing, and probably make the fire more intense. We can imagine it's a cartoonish scene where there's more artificial light than in reality, like in a video game with the gamma turned up! Given the overall vibe I was going for though I'd say 'whimsical fantasy' strikes again!
8592

8693
<CarouselGallery
8794
title="Strike at Dawn"
8895
imagePaths={DIORAMA_GALLERY}
8996
/>
9097

91-
My friend who this was a gift for is an artist. He has done commissions for MTG before and I think he nearly ended up doing some art for Hearthstone. So I knew his standards would be pretty high, but I think he appreciated the work that I put into this. We don't live in the same country anymore, so I'm glad I was able to give it to him before I left.
98+
My friend i gifted the piece to is an artist. He has done commissions for MTG before and I think he nearly ended up doing some art for Hearthstone which is amazing, and far beyond my artistic abilities! So knowing his standards would be pretty high was a litte nerve-wracking, but I think he appreciated the work that I put into this, and that I had made him something personal. We don't live in the same country anymore, so I'm glad I was able to give it to him before I left. The Warlocky druid forever looking down from whatever shelf he lives on.
99+
100+
![Creative packaging](miniatures/diorama-strike-at-dawn/diorama-packed.webp)
92101

93-
![All packed up!](miniatures/diorama-strike-at-dawn/diorama-packed.webp)
94102

95103
In the end I learned a lot by trying to challenge myself to go out of my comfort zone. I thoroughly enjoyed diorama building and already have ideas for more in the future, so watch this space.
96104

97-
![Actually quite like the starry background...](miniatures/diorama-strike-at-dawn/diorama-backdrop.webp)
105+
![I actually quite like the starry background](miniatures/diorama-strike-at-dawn/diorama-backdrop.webp)
98106

99-
I thought this background was corny when I was initially putting the images together, but coming back to it I kind of like it. I think next time I could paint something behind which would really add to the scene...
107+
I thought this background was corny when I was initially editing the images, but now after some time, I kind of like it. I think next time I could paint a real backdrop behind which would really add to the scene...
100108

101109
Alright, I'm off to bed. For at dawn...we strike!

src/routes/[slug]/+page.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export async function load({ params }) {
77
const file = await import(`../../posts/${params.slug}.md`);
88
const post = parsePostFile(file, params.slug);
99

10-
if (!canLoadPost(post)) {
10+
if (!canLoadPost(post, import.meta.env.PROD)) {
1111
throw new Error(`cannot load post: ${params.slug}`)
1212
}
1313

src/routes/api/posts/+server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ async function getPosts() {
1111
for (const path in paths) {
1212
const file = paths[path];
1313
const post = parsePostFile(file, path);
14-
post && canLoadPost(post) && posts.push(post);
14+
post && canLoadPost(post, import.meta.env.PROD) && posts.push(post);
1515
}
1616

1717
posts = posts.sort(

src/test/data/posts.test.valid.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"technologies": [
3131
"tech1",
3232
"tech2"
33-
]
33+
],
34+
"dev": true
3435
}
3536
]

src/test/posts/posts.test.ts

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { test, describe, expect } from 'vitest';
22
import * as fs from 'fs';
33
import path from 'path';
44
import { parsePostFile } from '$lib/utils/parse';
5+
import { canLoadPost, isPost } from '$lib/utils/post';
56

67
const iconCssPath = path.join(
78
__dirname,
@@ -65,5 +66,88 @@ describe('post validation', () => {
6566
expect(icons).toContain(`fa-${post.icon}`);
6667
});
6768
}
69+
test(`published post is not marked for dev: ${post.title}`, () => {
70+
if (post.published)
71+
{
72+
expect(post.dev).toBeFalsy();
73+
}
74+
})
6875
});
69-
});
76+
})
77+
78+
describe('post loading', () => {
79+
80+
// such a post should fail validation anyway, but for peace of mind
81+
const postPublishedAndDev = {
82+
"title": "Test",
83+
"slug": "a-valid-slug",
84+
"description": "A valid description",
85+
"published": true,
86+
"dev": true,
87+
"date": "01/04/2021"
88+
};
89+
90+
const PostDevOnly = {
91+
"title": "Test",
92+
"slug": "a-valid-slug",
93+
"description": "A valid description",
94+
"dev": true,
95+
"published": false,
96+
"date": "01/04/2021"
97+
};
98+
99+
const PostPublishedOnly = {
100+
"title": "Test",
101+
"slug": "a-valid-slug",
102+
"description": "A valid description",
103+
"published": true,
104+
"date": "01/04/2021",
105+
};
106+
107+
const PostPublishedOnlyDevFalse = {
108+
"title": "Test",
109+
"slug": "a-valid-slug",
110+
"description": "A valid description",
111+
"published": true,
112+
"dev": false,
113+
"date": "01/04/2021",
114+
};
115+
116+
const PostNoDevOrPublished = {
117+
"title": "Test",
118+
"slug": "a-valid-slug",
119+
"description": "A valid description",
120+
"date": "01/04/2021",
121+
"published": false,
122+
};
123+
124+
test("test posts are valid", () => {
125+
expect(isPost(postPublishedAndDev)).toBe(true);
126+
expect(isPost(PostDevOnly)).toBe(true);
127+
expect(isPost(PostPublishedOnly)).toBe(true);
128+
expect(isPost(PostNoDevOrPublished)).toBe(true);
129+
expect(isPost(PostPublishedOnlyDevFalse)).toBe(true);
130+
})
131+
132+
test("when in PROD post with 'dev' is not loaded", () => {
133+
expect(canLoadPost(postPublishedAndDev, true)).toBe(false);
134+
expect(canLoadPost(PostDevOnly, true)).toBe(false);
135+
});
136+
137+
test("when in PROD post with 'published' and not 'dev' is loaded", () => {
138+
expect(canLoadPost(PostPublishedOnly, true)).toBe(true);
139+
expect(canLoadPost(PostPublishedOnlyDevFalse, true)).toBe(true);
140+
});
141+
142+
test("when not in PROD post with 'dev' or 'published' is always loaded", () => {
143+
expect(canLoadPost(postPublishedAndDev, false)).toBe(true);
144+
expect(canLoadPost(PostDevOnly, false)).toBe(true);
145+
expect(canLoadPost(PostPublishedOnly, false)).toBe(true);
146+
expect(canLoadPost(PostPublishedOnlyDevFalse, false)).toBe(true);
147+
});
148+
149+
test("post without 'dev' or 'published' is never loaded", () => {
150+
expect(canLoadPost(PostNoDevOrPublished, false)).toBe(false);
151+
expect(canLoadPost(PostNoDevOrPublished, true)).toBe(false);
152+
})
153+
})
75.1 KB
Loading

0 commit comments

Comments
 (0)