Skip to content

Commit 623765d

Browse files
jakeefrclaude
andcommitted
feat: add Product Hunt badge and thumbnail
- Add Product Hunt featured badge to README below badges block - Add assets/producthunt-thumbnail.png (240x240) - Add scripts/gen_producthunt_thumbnail.py Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent de99c70 commit 623765d

3 files changed

Lines changed: 110 additions & 0 deletions

File tree

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@
2020

2121
</div>
2222

23+
<div align="center">
24+
25+
[![Product Hunt](https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=1123233&theme=dark&t=1776146492351)](https://www.producthunt.com/products/prism-24?utm_source=badge-featured&utm_medium=badge&utm_campaign=badge-prism-d6c1f55c-6f43-456f-bf84-790dbc1ad4ae)
26+
27+
</div>
28+
2329
---
2430

2531
## The problem

assets/producthunt-thumbnail.png

5.63 KB
Loading
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
"""Generate a 240x240 Product Hunt thumbnail for PRISM.
2+
3+
Run: python scripts/gen_producthunt_thumbnail.py
4+
Output: assets/producthunt-thumbnail.png
5+
"""
6+
from __future__ import annotations
7+
8+
import math
9+
from pathlib import Path
10+
11+
from PIL import Image, ImageDraw, ImageFont
12+
13+
14+
def glow_polygon(draw: ImageDraw.ImageDraw, pts: list, color: tuple) -> None:
15+
r, g, b = color
16+
draw.polygon(pts, fill=(r, g, b, 10))
17+
draw.polygon(pts, outline=(r, g, b, 13), width=14)
18+
draw.polygon(pts, outline=(r, g, b, 36), width=6)
19+
draw.polygon(pts, outline=(r, g, b, 242), width=2)
20+
21+
22+
def glow_line(
23+
draw: ImageDraw.ImageDraw,
24+
p0: tuple,
25+
p1: tuple,
26+
color: tuple,
27+
wide: int = 12,
28+
mid: int = 5,
29+
) -> None:
30+
r, g, b = color
31+
draw.line([p0, p1], fill=(r, g, b, 18), width=wide)
32+
draw.line([p0, p1], fill=(r, g, b, 45), width=mid)
33+
draw.line([p0, p1], fill=(r, g, b, 220), width=2)
34+
35+
36+
def main() -> None:
37+
W, H = 240, 240
38+
BG = (13, 17, 23)
39+
BLUE = (88, 166, 255)
40+
41+
img = Image.new("RGBA", (W, H), (*BG, 255))
42+
draw = ImageDraw.Draw(img, "RGBA")
43+
44+
# --- Triangle ---
45+
# apex top-center, base roughly at y=132
46+
apex = (120, 18)
47+
bl = (62, 134)
48+
br = (178, 134)
49+
glow_polygon(draw, [apex, bl, br], BLUE)
50+
51+
# Apex dot
52+
ax, ay = apex
53+
draw.ellipse((ax - 6, ay - 6, ax + 6, ay + 6), fill=(*BLUE, 20))
54+
draw.ellipse((ax - 3, ay - 3, ax + 3, ay + 3), fill=(*BLUE, 230))
55+
56+
# --- Incoming white beam (left edge → left face midpoint) ---
57+
left_mid = ((apex[0] + bl[0]) // 2, (apex[1] + bl[1]) // 2) # ~(91, 76)
58+
beam_start = (0, left_mid[1])
59+
draw.line([beam_start, left_mid], fill=(255, 255, 255, 13), width=14)
60+
draw.line([beam_start, left_mid], fill=(255, 255, 255, 25), width=6)
61+
draw.line([beam_start, left_mid], fill=(255, 255, 255, 180), width=2)
62+
63+
# --- Refracted rays from right-face exit point ---
64+
exit_pt = ((apex[0] + br[0]) // 2, (apex[1] + br[1]) // 2) # ~(149, 76)
65+
66+
rays = [
67+
((248, 81, 73), (240, 28)), # red – up-right
68+
((209, 134, 22), (240, 52)), # orange
69+
((210, 153, 34), (240, 76)), # yellow – near horizontal
70+
((63, 185, 80), (240, 100)), # green
71+
((88, 166, 255), (240, 122)), # blue
72+
((188, 140, 255), (240, 142)), # violet – down-right
73+
]
74+
for color, end in rays:
75+
glow_line(draw, exit_pt, end, color)
76+
77+
# --- Text ---
78+
font_bold = ImageFont.truetype(r"C:\Windows\Fonts\consolab.ttf", 38)
79+
font_tag = ImageFont.truetype(r"C:\Windows\Fonts\consola.ttf", 13)
80+
81+
# "PRISM"
82+
prism_text = "PRISM"
83+
bb = draw.textbbox((0, 0), prism_text, font=font_bold)
84+
tw = bb[2] - bb[0]
85+
draw.text(((W - tw) // 2, 152), prism_text, font=font_bold, fill=(230, 237, 243, 255))
86+
87+
# "session intelligence"
88+
tag_text = "session intelligence"
89+
bb2 = draw.textbbox((0, 0), tag_text, font=font_tag)
90+
tw2 = bb2[2] - bb2[0]
91+
draw.text(((W - tw2) // 2, 201), tag_text, font=font_tag, fill=(139, 148, 158, 255))
92+
93+
# --- Save ---
94+
out = Image.new("RGB", (W, H), BG)
95+
out.paste(img, mask=img.split()[3])
96+
97+
out_path = Path(__file__).parent.parent / "assets" / "producthunt-thumbnail.png"
98+
out.save(str(out_path), optimize=True)
99+
size_kb = out_path.stat().st_size // 1024
100+
print(f"Saved {out_path} ({W}x{H}, {size_kb} KB)")
101+
102+
103+
if __name__ == "__main__":
104+
main()

0 commit comments

Comments
 (0)