Skip to content

Commit 80bd86f

Browse files
committed
feat: new thumbs
1 parent 5a3a017 commit 80bd86f

16 files changed

Lines changed: 635 additions & 3 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Fezcodex
22

3-
![Fezcodex Card](public/images/fezcodex-card.png)
3+
![Fezcodex Card](public/images/fezcodex-card-2.png)
44

55
### What is this?
66
Imagine you have a giant digital toy box. Inside, you keep the cool things you've built, the stories you've written, and a diary of all the interesting things you've learned. Fezcodex is that toy box. It is a special website that works like a personal museum on the internet. It is not just a boring page; it has moving parts, secret "Easter eggs," and little mini-apps like a sound mixer and a knowledge graph.

landing.jpg

-536 KB
Binary file not shown.

public/images/fezcodex-card-2.png

199 KB
Loading

src/pages/apps/github-thumbnail/GithubThumbnailGeneratorPage.jsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@ const THEME_OPTIONS = [
7676
{ value: 'boldMinimal', label: 'CLASSIFIED_DOC' },
7777
{ value: 'luxe', label: 'LUXE_ART' },
7878
{ value: 'urbanRogue', label: 'URBAN_ROGUE' },
79+
{ value: 'newModernAbstract', label: 'NEW_MODERN_ABSTRACT' },
80+
{ value: 'cubic', label: 'CUBIC_BLOCKS' },
81+
{ value: 'darkDeco', label: 'DARK_ART_DECO' },
82+
{ value: 'artNouveau', label: 'ART_NOUVEAU' },
83+
{ value: 'cyberGlitch', label: 'CYBER_GLITCH' },
84+
{ value: 'stellarMap', label: 'STELLAR_MAP' },
85+
{ value: 'jungle', label: 'JUNGLE_VINES' },
86+
{ value: 'dithered', label: 'RETRO_DITHERED' },
87+
{ value: 'abstractNonsense', label: 'ABSTRACT_NONSENSE' },
88+
{ value: 'needForSpeed', label: 'NEED_FOR_SPEED' },
7989
];
8090

8191
const GithubThumbnailGeneratorPage = () => {

src/pages/apps/github-thumbnail/themes.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,17 @@ import { luxe } from './themes/luxe';
5959

6060
import { urbanRogue } from './themes/urbanRogue';
6161

62+
import { newModernAbstract } from './themes/newModernAbstract';
63+
import { cubic } from './themes/cubic';
64+
import { darkDeco } from './themes/darkDeco';
65+
import { artNouveau } from './themes/artNouveau';
66+
import { cyberGlitch } from './themes/cyberGlitch';
67+
import { stellarMap } from './themes/stellarMap';
68+
import { jungle } from './themes/jungle';
69+
import { dithered } from './themes/dithered';
70+
import { abstractNonsense } from './themes/abstractNonsense';
71+
import { needForSpeed } from './themes/needForSpeed';
72+
6273
export const themeRenderers = {
6374
modern,
6475
brutalist,
@@ -118,4 +129,14 @@ export const themeRenderers = {
118129
boldMinimal,
119130
luxe,
120131
urbanRogue,
132+
newModernAbstract,
133+
cubic,
134+
darkDeco,
135+
artNouveau,
136+
cyberGlitch,
137+
stellarMap,
138+
jungle,
139+
dithered,
140+
abstractNonsense,
141+
needForSpeed,
121142
};
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { wrapText } from '../utils';
2+
3+
export const abstractNonsense = (ctx, width, height, scale, data) => {
4+
const { primaryColor, secondaryColor, bgColor, repoOwner, repoName, description } = data;
5+
6+
ctx.save();
7+
8+
// Crazy random shapes
9+
for(let i=0; i<50; i++) {
10+
const type = Math.floor(Math.random() * 3);
11+
ctx.fillStyle = i % 3 === 0 ? primaryColor : (i % 3 === 1 ? secondaryColor : bgColor);
12+
ctx.globalAlpha = Math.random() * 0.8 + 0.2;
13+
14+
ctx.beginPath();
15+
const x = Math.random() * width;
16+
const y = Math.random() * height;
17+
const size = Math.random() * 200 * scale;
18+
19+
if (type === 0) {
20+
ctx.arc(x, y, size, 0, Math.PI * 2);
21+
} else if (type === 1) {
22+
ctx.rect(x, y, size, size);
23+
} else {
24+
ctx.moveTo(x, y);
25+
ctx.lineTo(x + size, y + size/2);
26+
ctx.lineTo(x, y + size);
27+
}
28+
ctx.fill();
29+
}
30+
31+
// Overlay gradient to make text readable
32+
const grd = ctx.createLinearGradient(0, 0, 0, height);
33+
grd.addColorStop(0, 'rgba(0,0,0,0.4)');
34+
grd.addColorStop(1, 'rgba(0,0,0,0.8)');
35+
ctx.fillStyle = grd;
36+
ctx.fillRect(0, 0, width, height);
37+
38+
ctx.restore();
39+
40+
const padding = 80 * scale;
41+
42+
// Text with a slight skew
43+
ctx.save();
44+
ctx.translate(padding, padding + 110 * scale);
45+
ctx.rotate(-0.05);
46+
47+
ctx.fillStyle = primaryColor;
48+
ctx.font = `bold ${30 * scale}px "Impact", "Arial Black", sans-serif`;
49+
ctx.fillText(`${repoOwner} /`, 0, -90 * scale);
50+
51+
ctx.fillStyle = '#ffffff';
52+
ctx.font = `bold ${90 * scale}px "Impact", "Arial Black", sans-serif`;
53+
ctx.fillText(repoName, 0, 0);
54+
ctx.restore();
55+
56+
ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
57+
ctx.font = `${32 * scale}px "Impact", "Arial Black", sans-serif`;
58+
wrapText(ctx, description, padding, padding + 220 * scale, width - padding * 2, 45 * scale);
59+
};
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { wrapText } from '../utils';
2+
3+
export const artNouveau = (ctx, width, height, scale, data) => {
4+
const { primaryColor, secondaryColor, bgColor, repoOwner, repoName, description } = data;
5+
6+
ctx.save();
7+
// Flowing, organic lines
8+
ctx.strokeStyle = primaryColor;
9+
ctx.lineWidth = 8 * scale;
10+
ctx.lineCap = 'round';
11+
12+
ctx.beginPath();
13+
ctx.moveTo(0, height * 0.5);
14+
ctx.bezierCurveTo(width * 0.2, height * 0.2, width * 0.3, height * 0.8, width * 0.5, height * 0.5);
15+
ctx.bezierCurveTo(width * 0.7, height * 0.2, width * 0.8, height * 0.8, width, height * 0.5);
16+
ctx.stroke();
17+
18+
ctx.strokeStyle = secondaryColor;
19+
ctx.lineWidth = 4 * scale;
20+
ctx.beginPath();
21+
ctx.moveTo(0, height * 0.6);
22+
ctx.bezierCurveTo(width * 0.2, height * 0.3, width * 0.3, height * 0.9, width * 0.5, height * 0.6);
23+
ctx.bezierCurveTo(width * 0.7, height * 0.3, width * 0.8, height * 0.9, width, height * 0.6);
24+
ctx.stroke();
25+
26+
// Organic frame
27+
ctx.strokeStyle = primaryColor;
28+
ctx.lineWidth = 12 * scale;
29+
ctx.strokeRect(40 * scale, 40 * scale, width - 80 * scale, height - 80 * scale);
30+
31+
// Corner flourishes
32+
const drawFlourish = (x, y, flipX, flipY) => {
33+
ctx.save();
34+
ctx.translate(x, y);
35+
ctx.scale(flipX ? -1 : 1, flipY ? -1 : 1);
36+
ctx.fillStyle = bgColor; // Using bgColor for the inner flourish
37+
ctx.globalAlpha = 0.9;
38+
ctx.strokeStyle = secondaryColor;
39+
ctx.lineWidth = 4 * scale;
40+
ctx.beginPath();
41+
ctx.arc(40 * scale, 40 * scale, 40 * scale, Math.PI, Math.PI * 1.5);
42+
ctx.stroke();
43+
ctx.fill();
44+
ctx.restore();
45+
};
46+
drawFlourish(40 * scale, 40 * scale, false, false);
47+
drawFlourish(width - 40 * scale, 40 * scale, true, false);
48+
drawFlourish(40 * scale, height - 40 * scale, false, true);
49+
drawFlourish(width - 40 * scale, height - 40 * scale, true, true);
50+
ctx.restore();
51+
52+
// Text
53+
const padding = 100 * scale;
54+
ctx.fillStyle = primaryColor;
55+
ctx.font = `italic ${30 * scale}px "Georgia", serif`;
56+
ctx.fillText(`${repoOwner} /`, padding, padding + 20 * scale);
57+
58+
ctx.fillStyle = secondaryColor;
59+
ctx.font = `bold ${80 * scale}px "Georgia", serif`;
60+
ctx.fillText(repoName, padding, padding + 110 * scale);
61+
62+
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
63+
ctx.font = `italic ${32 * scale}px "Georgia", serif`;
64+
wrapText(ctx, description, padding, padding + 180 * scale, width - padding * 2, 45 * scale);
65+
};
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { wrapText } from '../utils';
2+
3+
export const cubic = (ctx, width, height, scale, data) => {
4+
const { primaryColor, secondaryColor, bgColor, repoOwner, repoName, description } = data;
5+
6+
ctx.save();
7+
const cubeSize = 100 * scale;
8+
for(let x = -cubeSize; x < width + cubeSize; x += cubeSize * 1.5) {
9+
for(let y = -cubeSize; y < height + cubeSize; y += cubeSize * 1.5) {
10+
const offsetX = ((y / (cubeSize * 1.5)) % 2 === 0) ? cubeSize * 0.75 : 0;
11+
12+
const px = x + offsetX;
13+
const py = y;
14+
15+
// Top face
16+
ctx.fillStyle = primaryColor;
17+
ctx.beginPath();
18+
ctx.moveTo(px, py);
19+
ctx.lineTo(px + cubeSize * 0.866, py + cubeSize * 0.5);
20+
ctx.lineTo(px, py + cubeSize);
21+
ctx.lineTo(px - cubeSize * 0.866, py + cubeSize * 0.5);
22+
ctx.fill();
23+
24+
// Left face
25+
ctx.fillStyle = secondaryColor;
26+
ctx.beginPath();
27+
ctx.moveTo(px - cubeSize * 0.866, py + cubeSize * 0.5);
28+
ctx.lineTo(px, py + cubeSize);
29+
ctx.lineTo(px, py + cubeSize * 2);
30+
ctx.lineTo(px - cubeSize * 0.866, py + cubeSize * 1.5);
31+
ctx.fill();
32+
33+
// Right face
34+
ctx.fillStyle = bgColor;
35+
ctx.globalAlpha = 0.5; // Since bgColor is also background, we make it transparent to blend
36+
ctx.beginPath();
37+
ctx.moveTo(px, py + cubeSize);
38+
ctx.lineTo(px + cubeSize * 0.866, py + cubeSize * 0.5);
39+
ctx.lineTo(px + cubeSize * 0.866, py + cubeSize * 1.5);
40+
ctx.lineTo(px, py + cubeSize * 2);
41+
ctx.fill();
42+
ctx.globalAlpha = 1.0;
43+
}
44+
}
45+
ctx.restore();
46+
47+
// Dim background slightly for text
48+
ctx.fillStyle = 'rgba(0, 0, 0, 0.6)';
49+
ctx.fillRect(0, 0, width, height);
50+
51+
const padding = 80 * scale;
52+
ctx.fillStyle = primaryColor;
53+
ctx.font = `bold ${30 * scale}px "JetBrains Mono"`;
54+
ctx.fillText(`${repoOwner} /`, padding, padding + 20 * scale);
55+
56+
ctx.fillStyle = '#ffffff';
57+
ctx.font = `bold ${80 * scale}px "Inter", sans-serif`;
58+
ctx.fillText(repoName, padding, padding + 110 * scale);
59+
60+
ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
61+
ctx.font = `${32 * scale}px "Inter", sans-serif`;
62+
wrapText(ctx, description, padding, padding + 180 * scale, width - padding * 2, 45 * scale);
63+
};
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { wrapText } from '../utils';
2+
3+
export const cyberGlitch = (ctx, width, height, scale, data) => {
4+
const { primaryColor, secondaryColor, bgColor, repoOwner, repoName, description } = data;
5+
6+
ctx.save();
7+
// Glitch bands
8+
for(let i=0; i<30; i++) {
9+
const y = Math.random() * height;
10+
const h = Math.random() * 20 * scale;
11+
const x = Math.random() * width;
12+
const w = Math.random() * width;
13+
14+
ctx.fillStyle = Math.random() > 0.5 ? primaryColor : secondaryColor;
15+
ctx.globalAlpha = Math.random() * 0.5;
16+
ctx.fillRect(x, y, w, h);
17+
}
18+
19+
// Draw some code-like text using bgColor
20+
ctx.fillStyle = bgColor;
21+
ctx.globalAlpha = 0.3; // since bgColor might be dark, we make it an overlay block
22+
ctx.fillRect(0,0,width,height);
23+
24+
ctx.fillStyle = primaryColor;
25+
ctx.globalAlpha = 0.4;
26+
ctx.font = `${14 * scale}px monospace`;
27+
for(let i=0; i<100; i++) {
28+
ctx.fillText(Math.random().toString(36).substring(2), Math.random() * width, Math.random() * height);
29+
}
30+
ctx.restore();
31+
32+
const padding = 80 * scale;
33+
34+
// Title with glitch effect
35+
const titleY = padding + 110 * scale;
36+
ctx.font = `900 ${80 * scale}px "JetBrains Mono", monospace`;
37+
38+
// Cyan shadow
39+
ctx.fillStyle = primaryColor;
40+
ctx.fillText(repoName, padding - 5 * scale, titleY);
41+
42+
// Magenta shadow
43+
ctx.fillStyle = secondaryColor;
44+
ctx.fillText(repoName, padding + 5 * scale, titleY);
45+
46+
// Main white text
47+
ctx.fillStyle = '#ffffff';
48+
ctx.fillText(repoName, padding, titleY);
49+
50+
ctx.fillStyle = primaryColor;
51+
ctx.font = `bold ${30 * scale}px "JetBrains Mono"`;
52+
ctx.fillText(`${repoOwner} /`, padding, padding + 20 * scale);
53+
54+
ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
55+
ctx.font = `${32 * scale}px "JetBrains Mono"`;
56+
wrapText(ctx, description, padding, padding + 180 * scale, width - padding * 2, 45 * scale);
57+
};
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { wrapText } from '../utils';
2+
3+
export const darkDeco = (ctx, width, height, scale, data) => {
4+
const { primaryColor, secondaryColor, bgColor, repoOwner, repoName, description } = data;
5+
6+
ctx.save();
7+
// Art deco lines
8+
ctx.strokeStyle = primaryColor;
9+
ctx.lineWidth = 4 * scale;
10+
11+
for (let i = 0; i < 5; i++) {
12+
const offset = (i * 20 + 20) * scale;
13+
ctx.strokeRect(offset, offset, width - offset * 2, height - offset * 2);
14+
}
15+
16+
// Geometric center pieces
17+
ctx.fillStyle = secondaryColor;
18+
ctx.beginPath();
19+
ctx.moveTo(width / 2, 0);
20+
ctx.lineTo(width / 2 + 100 * scale, 100 * scale);
21+
ctx.lineTo(width / 2, 200 * scale);
22+
ctx.lineTo(width / 2 - 100 * scale, 100 * scale);
23+
ctx.fill();
24+
25+
ctx.fillStyle = bgColor;
26+
ctx.globalAlpha = 0.8;
27+
ctx.beginPath();
28+
ctx.moveTo(width / 2, height);
29+
ctx.lineTo(width / 2 + 100 * scale, height - 100 * scale);
30+
ctx.lineTo(width / 2, height - 200 * scale);
31+
ctx.lineTo(width / 2 - 100 * scale, height - 100 * scale);
32+
ctx.fill();
33+
ctx.globalAlpha = 1.0;
34+
35+
ctx.strokeStyle = secondaryColor;
36+
ctx.stroke();
37+
38+
ctx.restore();
39+
40+
// Dark background for text box
41+
ctx.fillStyle = 'rgba(0, 0, 0, 0.8)';
42+
const boxWidth = width * 0.7;
43+
const boxHeight = height * 0.5;
44+
const bx = (width - boxWidth) / 2;
45+
const by = (height - boxHeight) / 2;
46+
ctx.fillRect(bx, by, boxWidth, boxHeight);
47+
ctx.strokeStyle = primaryColor;
48+
ctx.strokeRect(bx, by, boxWidth, boxHeight);
49+
50+
ctx.textAlign = 'center';
51+
ctx.fillStyle = primaryColor;
52+
ctx.font = `bold ${24 * scale}px "Courier New", Courier, monospace`;
53+
ctx.fillText(`${repoOwner}`.toUpperCase(), width / 2, by + 60 * scale);
54+
55+
ctx.fillStyle = secondaryColor;
56+
ctx.font = `bold ${64 * scale}px "Courier New", Courier, monospace`;
57+
ctx.fillText(repoName.toUpperCase(), width / 2, by + 140 * scale);
58+
59+
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
60+
ctx.font = `${28 * scale}px "Courier New", Courier, monospace`;
61+
ctx.textAlign = 'left';
62+
// wrapText wraps from left, so we pass appropriate left coordinate
63+
wrapText(ctx, description, bx + 40 * scale, by + 220 * scale, boxWidth - 80 * scale, 40 * scale);
64+
};

0 commit comments

Comments
 (0)