Use when adding technology logos to pages — fetching SVG/PNG logos from icon sources, validating them, and embedding with proper theme support and CSS styling.
Add recognizable technology logos to documentation pages. Logos appear as centered rows with labels, styled consistently across dark/light themes.
| Source | URL Pattern | Best for |
|---|---|---|
| vectorlogo.zone | https://www.vectorlogo.zone/logos/{slug}/{slug}-ar21.svg | Full logos with icon + text (2:1 ratio). First choice. |
| gilbarbara/logos | https://cdn.jsdelivr.net/gh/gilbarbara/logos/logos/{name}.svg | Full-color logos. Good fallback. |
| Official project sites | Varies — check /brand, /press, or navbar logo | When above sources fail or return wrong logo. |
| Simple Icons | https://cdn.simpleicons.org/{slug} |
| Last resort. Monochrome only — user prefers full-color. |
vectorlogo.zone slugs use underscores: apache_kafka, apache_spark, amazon_s3.
For AWS services: amazon_ec2, amazon_rds, amazon_redshift, amazon_kinesis.
Use the -ar21.svg variant (2:1 aspect ratio with icon + text). Avoid -icon.svg (icon only, no text).
<span> label below each logo regardless of text in the logo itself-dark.svg variant with inverted text colorsAfter downloading, always verify:
# Check file is valid SVG (not HTML 404)
head -c 10 logo.svg # Must start with <svg or <?xml
# Check file size — very small (<100 bytes) usually means error
wc -c logo.svg
# Check colors won't be invisible on white background
grep 'fill="#FFFFFF"' logo.svg # White fills = invisible on white bg
If a logo has white text (fill="#FFFFFF"), change it to dark:
sed -i '' 's/fill="#FFFFFF"/fill="#1e1e1e"/g' logo.svg
Every logo needs a -dark.svg variant for dark theme. Store both in public/images/logos/.
Step 1: Identify what needs changing. SVG logos have three kinds of color:
| Element | How to find | Dark mode action |
|---|---|---|
| Dark text (brand name) | fill="#231f20", fill="#1e1e1e", fill="black", or no fill at all (SVG defaults to black) | Change to #e8e8ea |
| Brand colors (icons, accents) | Bright fills like #FF694A, #29b5e8, #e25a1c | Keep as-is — they pop on dark backgrounds |
| Dark brand elements | Very dark fills like #430a1d, #0721a0, #4040b2 | Lighten to a brighter variant of the same hue |
Step 2: Check for ALL unfilled paths. This is the most common mistake. Paths without any fill attribute or style="fill:..." render as black by default — invisible on dark backgrounds.
# Find paths with no fill (these default to black!)
grep '<path' logo.svg | grep -v 'fill\|style' | head -5
# Also check <use> elements — they inherit fill from the referenced element
grep '<use' logo.svg | head -5
Fix strategies for unfilled paths (in order of preference):
fill="#e8e8ea" to the root <svg> element. This sets the default for ALL unfilled elements while explicit fills on icon paths override it. This is the safest approach because it catches paths, <use> refs, and text elements at once.
<svg fill="#e8e8ea" xmlns="...">
fill="#e8e8ea" to the specific <g> group containing text pathspath:not([fill]){fill:#e8e8ea} (but CSS won't affect <use> elements)Step 3: Handle text separately from logo icon. The text (brand name) and logo icon are often in different SVG groups or use different fill colors. Identify which paths are text vs icon before replacing colors. Be careful with multi-tone icons — e.g., Terraform's logo has both #5c4ee5 (bright purple) and #4040b2 (dark purple) as intentional brand colors forming a 3D parallelogram. Don't lighten icon fills just because they look dark — check if they're part of the brand's color scheme first.
# Copy original as starting point
cp logo.svg logo-dark.svg
# Replace dark text fills with light (common patterns)
sed -i '' 's/fill="#231f20"/fill="#e8e8ea"/g' logo-dark.svg # near-black
sed -i '' 's/fill="#1e1e1e"/fill="#e8e8ea"/g' logo-dark.svg # dark gray
sed -i '' 's/fill="black"/fill="#e8e8ea"/g' logo-dark.svg # explicit black
sed -i '' 's/fill:#0d0d0d/fill:#e8e8ea/g' logo-dark.svg # style-based dark
# For AWS service logos: dark navy text → light
sed -i '' 's/fill="#232F3E"/fill="#e8e8ea"/g' logo-dark.svg
Step 4: Verify the dark version. Check that brand colors were NOT accidentally changed:
# Compare fills between original and dark
diff <(grep -oE 'fill="[^"]*"|fill:[^;}"]+' logo.svg | sort -u) \
<(grep -oE 'fill="[^"]*"|fill:[^;}"]+' logo-dark.svg | sort -u)
| Category | Examples | Dark mode approach |
|---|---|---|
| Dark text only | Kafka, MSK, Spark, dbt, Prefect, Scala, Delta Lake | Simple fill replacement |
| Dark text + colored icon | Airflow, Neo4j, BigQuery, Flink, Redis | Replace dark fills only, preserve brand colors |
fill="black" or no fill | Mage, CSV, XML, Presto, JSON | Add explicit fill="#e8e8ea" to unfilled paths |
| Style-based fills | Flink (style="fill:#0d0d0d"), NumPy | Use sed on fill: not fill= |
| AWS service logos | EBS, Glue, RDS, Redshift, S3, VPC, EMR | Replace #232F3E (AWS dark navy) → #e8e8ea |
| Already bright/colorful | Snowflake, Databricks, EC2, Kinesis | Copy as-is (still create the -dark.svg file) |
| Multi-tone icon + unfilled text | Terraform (dark+bright purple icon, black text) | Add fill="#e8e8ea" to root <svg> — unfilled text inherits it, explicit icon fills override it |
| Slightly dark brand colors | Java blue #4e7896 | Lighten subtly (#7ab0d4) — not full white, just brighter |
| PNGs | Hudi, Oozie | Cannot edit fills — use CSS filter: brightness(1.6) in dark mode |
Some logos (e.g., Flink, Terraform) have text as paths in a distinct <g> group at the end of the file. These paths often have no fill attribute, making them invisible on dark backgrounds. Always check the last 30 lines of the SVG for text groups:
tail -30 logo.svg # Look for <g> with letter-shaped <path> elements
Logos may appear small in their container due to excess whitespace in the SVG canvas.
# Check dimensions and viewBox
grep -oE 'viewBox="[^"]*"|width="[^"]*"|height="[^"]*"' logo.svg | head -3
Tighten the viewBox to remove padding around the actual content:
# Find the transform that positions the content
grep -oE 'transform="matrix\([^)]+\)"' logo.svg | head -3
# Calculate rendered bounds from transform: x = val * scale + tx, y = val * scale + ty
# Then set viewBox to tightly wrap the content
Start conservatively, then tighten. Crop a few pixels at a time. Aggressive crops will cut off content (e.g., the last letter of "Snowflake" or the Python icon tail). It's better to have slight padding than to clip the logo. After each change, visually verify in the review page before committing.
Critical: Remove fixed width and height attributes when adding a viewBox crop. Fixed dimensions override the viewBox scaling — the SVG won't actually zoom in.
# WRONG — fixed dimensions prevent viewBox from working:
# <svg width="120" height="60" viewBox="3 11 114 42">
# RIGHT — viewBox alone, SVG scales to fill container:
# <svg viewBox="3 11 114 42">
# Remove fixed dimensions
sed -i '' 's/width="120" height="60" //' logo.svg
Square logos (e.g., 560x560 or 24x24) appear tiny in wide containers. Two approaches:
viewBox="70 80 420 400" (worked for Dagster)viewBox="-6 0 36 24" — gives a wider aspect ratio so the icon fills the container heightAfter modifying any SVG dimensions or viewBox, copy the change to the dark variant:
cp logo.svg logo-dark.svg
# Then re-apply dark color changes if the dark version had modifications
Place logos in public/images/logos/. Every logo needs two <img> tags — one for light, one for dark. CSS handles show/hide based on [data-theme].
<div class="tech-logos">
<div class="tech-logo">
<img src="/data-engineering-specialization-website/images/logos/name.svg" alt="Display Name" class="logo-light" /><img src="/data-engineering-specialization-website/images/logos/name-dark.svg" alt="Display Name" class="logo-dark" />
<span>Display Name</span>
</div>
<!-- more logos... -->
</div>
For PNG logos without a dark SVG variant, use brightness filter:
<img src=".../hudi.png" alt="Apache Hudi" class="logo-light" /><img src=".../hudi.png" alt="Apache Hudi" class="logo-dark" style="filter: brightness(1.6)" />
Placement: After introductory text or comparison tables, before detailed content.
For a single logo floating beside text (e.g., a section introducing one technology).
The <img> with float: right must come BEFORE the content it floats beside in the HTML output. In markdown, this means the <img> tag must be on its own line with blank lines both above AND below it. Without the blank line after, markdown wraps the img and text into a single <p> element, which breaks the float — the logo sinks to the bottom instead of floating at the top-right.
Pattern A: Under a bold subtitle — logo goes BEFORE the title so it floats beside both title and text:
<img class="tech-logo-aside logo-light" src="..." alt="..." /><img class="tech-logo-aside logo-dark" src="..." alt="..." />
**Section Title**
Short description — 1 to 2 sentences max.
---
Longer content continues here, safely below the floated logo.
Use this when there's a **Bold Title** subsection (e.g., **Apache Kafka**, **Terraform**). The logo floats beside the title AND the short paragraph together, which looks natural.
Pattern B: Under a ## heading — logo goes right after the heading:
## 1.4.4 dbt (Data Build Tool)
<img class="tech-logo-aside logo-light" src="..." alt="..." /><img class="tech-logo-aside logo-dark" src="..." alt="..." />
Short description — 1 to 2 sentences max.
---
Longer content continues here.
Use this when the section starts with a numbered ## heading and there's no bold subtitle below it.
Always class="tech-logo-aside logo-light" — both classes required. tech-logo-aside enables the float + styling. logo-light/logo-dark enables theme switching. Missing tech-logo-aside causes both logos to show inline (the #1 bug).
Blank line after the <img> tag is mandatory — without it, markdown wraps img + text into a single <p>, breaking the float. The logo will appear at the bottom-right instead of top-right.
Short text beside the logo — keep the paragraph next to the logo to 1–2 sentences. Use --- divider before longer content. The <hr> has clear: both in CSS, which forces content below it to drop under the logo.
Never remove the blank line between img and text — this was tried and broke every single aside logo on the site. The blank line is what makes markdown render the img as a standalone block element that can float.
| Mistake | What happens | Fix |
|---|---|---|
class="logo-light" without tech-logo-aside | Both light and dark logos show inline, no float | Add tech-logo-aside to class |
No blank line after <img> tag | Logo sinks to bottom-right, doesn't align with text | Always have blank line after img |
| Long paragraph (3+ lines) beside the logo | Text wraps awkwardly around the float | Shorten to 1-2 sentences, put rest after --- |
Logo after **Bold Title** instead of before it | Logo only floats beside the text paragraph, not the title — visual gap | Put <img> BEFORE **Bold Title** |
Missing --- divider after the short paragraph | Float continues into longer content below, overlapping | Always add --- to clear the float |
Reusable SVG paths (<use>) with no fill — e.g., letter "A" in "Apache" rendering black | Shared path in <defs> inherits no fill | Add explicit fill to the referenced path |
| Class | Layout | Use case |
|---|---|---|
.tech-logos | Centered flex row, wrapping | Multiple logos side by side |
.tech-logo | Column with image + label | Each logo within .tech-logos |
.tech-logo-aside | Float right, 80px tall | Single logo beside section text |
.logo-light | Shown in light theme, hidden in dark | Light variant of a logo |
.logo-dark | Shown in dark theme (no white bg), hidden in light | Dark variant of a logo |
The CSS in global.css handles the toggling:
.logo-light visible (white bg card), .logo-dark hidden.logo-dark visible (transparent bg), .logo-light hiddenAll AWS service logos must use the same visual style: architecture-icon format — gradient square with rounded corners + white icon inside + service name text on the right.
viewBox="0 0 120 48"
Left half (0–60): gradient square icon, right-aligned toward center
Right half (60–120): service name text, left-aligned toward center
Icon: translate(10, 0) scale(0.1875) on 256×256 original → 48×48 rendered
Right edge at x≈58, leaving 2px gap from center
Text: x="62", text-anchor="start", font-size="8.5", font-weight="600"
Single-line: y="27" | Two-line: y="20" and y="32"
The icon and text are aligned toward each other at the container center — icon pushed right in its half, text pushed left in its half. This eliminates awkward whitespace between them.
| Category | Gradient start | Gradient end | Services |
|---|---|---|---|
| Compute | #C8511B | #F7981F | EC2, Lambda |
| Storage | #1B660F | #6CAE3E | S3, EBS |
| Database | #2E27AD | #527FFF | RDS |
| Analytics | #4D27A8 | #A166FF | Glue, Redshift, VPC, EMR, Kinesis, MSK |
| Management | #B0084D | #FF4F8B | CloudWatch |
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 48">
<defs>
<linearGradient x1="0%" y1="100%" x2="100%" y2="0%" id="lg-SERVICE">
<stop stop-color="#GRADIENT_START" offset="0%"/>
<stop stop-color="#GRADIENT_END" offset="100%"/>
</linearGradient>
</defs>
<g transform="translate(10, 0) scale(0.1875)">
<rect fill="url(#lg-SERVICE)" x="0" y="0" width="256" height="256" rx="30" ry="30"/>
<!-- White icon paths here (fill="#FFFFFF" or stroke="#FFFFFF") -->
</g>
<text x="62" y="27" font-family="Helvetica, Arial, sans-serif"
font-size="8.5" fill="#232F3E" font-weight="600"
text-anchor="start">Amazon SERVICE</text>
</svg>
For two-line names (e.g., Amazon Redshift, Amazon CloudWatch):
<text x="62" y="20" ...>Amazon</text>
<text x="62" y="32" ...>Redshift</text>
Simply replace the text fill color:
cp service.svg service-dark.svg
sed -i '' 's/fill="#232F3E"/fill="#e8e8ea"/g' service-dark.svg
The gradient square and white icon are already fine on dark backgrounds.
When adding a new AWS logo or modifying existing ones:
rx="30" ry="30" rounded cornerstext-anchor="start", font-size="8.5"viewBox="0 0 120 48" — no fixed width/height attributes#232F3E → #e8e8ea text swaplogo-light and logo-dark img tags in content HTML# Download multiple logos in parallel
for slug in apache_kafka apache_spark apache_flink; do
curl -sL "https://www.vectorlogo.zone/logos/${slug}/${slug}-ar21.svg" \
-o "public/images/logos/$(echo $slug | sed 's/.*_//').svg" &
done
wait
# Validate all at once
for f in public/images/logos/*.svg; do
if head -c 5 "$f" | grep -q "<svg\|<?xml"; then
echo "OK: $f"
else
echo "BAD: $f"
fi
done
Generate logo-review.html at project root to review all logos in a grid with dark/light toggle. Open with open logo-review.html. Regenerate after adding new logos.
The review page should:
-dark.svg variants on transparent/dark card backgrounds (no white pill).logo-light / .logo-dark with display:none toggled by [data-theme]| Mistake | Fix |
|---|---|
| Logo has white text on white card | Change fill="#FFFFFF" to fill="#1e1e1e" |
| Downloaded HTML 404 instead of SVG | Check head -c 10 — must start with <svg |
| Wrong company (e.g., Delta Airlines vs Delta Lake) | Verify logo visually; check <title> element in SVG |
| Using generic AWS logo for specific service | Use -ar21.svg variant or find service-specific icon |
| Icon-only logo without text | Use -ar21 variant from vectorlogo.zone |
| Missing base path prefix | All src paths must start with /data-engineering-specialization-website/ |
| PNG logos from official sites are huge | They still work — CSS constrains display size |
Dark mode: unfilled <path> elements invisible | SVG default fill is black — grep for paths without fill or style and add explicit fill="#e8e8ea" |
Dark mode: only changed fill="..." but missed style="fill:..." | Some SVGs use inline styles — sed both fill="#xxx" and fill:#xxx patterns |
Dark mode: text in separate <g> group at end of SVG with no fill | Check tail -30 logo.svg for letter-shaped paths; add fill to the group |
| viewBox crop doesn't zoom the logo | Remove fixed width and height attributes — they override viewBox scaling |
| Logo appears tiny in container (square SVGs) | Widen the viewBox: viewBox="-6 0 36 24" for a 24x24 icon, or crop to content area for large squares |
| Forgot to update dark copy after viewBox/dimension change | Always cp logo.svg logo-dark.svg then re-apply dark color changes |
| viewBox crop too aggressive — clipped logo text | Start conservative, visually verify, then tighten. Better to have padding than to clip |
| Used wrong logo for a technology (e.g., MySQL logo for SQL, Kafka logo for MSK) | Check <title> in SVG, verify visually. Generic concepts (SQL) need custom icons, not product logos |
| Dark mode: lightened a multi-tone icon fill thinking it was text | Understand the logo structure first — e.g., Terraform's dark purple is intentional brand shading, not text |
Dark mode: CSS path:not([fill]) missed <use> elements | Prefer fill="#e8e8ea" on root <svg> — it cascades to everything without an explicit fill |
| PNG logos look bad in dark mode | Apply CSS filter: brightness(1.6) on the dark-mode <img> element |
| Languages/standards without official logos (SQL, CSV, XML) | Create a simple SVG with a representative icon + text, matching the visual style of other logos |
| AWS logos use inconsistent styles (some ar21, some architecture-icon) | All AWS logos must use architecture-icon style. See "AWS Service Logos" section for template and specs |
| Text centered in full container overlaps the icon | Split container into left (icon) and right (text) halves. Align icon right and text left toward the center — no gap |
| Text gets cropped at container edge | Reduce font-size (8.5 works well) and use text-anchor="start" at x=62, not text-anchor="middle" at center |
Only added light <img> tag, forgot dark variant | Every logo reference in content needs TWO img tags: class="logo-light" and class="logo-dark". Batch with sed |
| Changed logo SVGs but didn't update content HTML | After creating dark variants, update all content files: sed to add class="logo-light" + dark <img> tag |
Aside logo missing tech-logo-aside class — shows both light/dark inline | Must be class="tech-logo-aside logo-light", not just class="logo-light". Without tech-logo-aside, no float and no theme toggle. This is the #1 mistake when converting row logos to aside logos. |
| Row-to-aside conversion forgot to change the HTML structure | Row logos use <div class="tech-logo"><img class="logo-light">. Aside logos use <img class="tech-logo-aside logo-light"> directly — no wrapping div, class goes on the <img> itself. |