Images & Media — Formats, Uploads, and Optimization
Complete guide to images in Dax Pro: supported formats, optimal dimensions, uploading through Decap CMS, using external image URLs, alt text, lazy loading, and the pitfalls that break layouts or slow down pages.
Why Images Matter More Than You Think
Images are the single biggest contributor to page weight on most content sites. A site that renders in 50 milliseconds of HTML can become a 3-second page if the hero image is unoptimized. A gallery of 20 photos at 2 MB each becomes a 40 MB page load that visitors abandon before the first image appears.
Dax Pro is built to be fast. It ships zero JavaScript runtime, sub-second build times, and Lighthouse 100 by default. But it cannot compensate for images that are too large, wrong format, or incorrectly referenced. Image discipline is the difference between a site that stays fast as you add content and a site that gradually slows down with every post.
This chapter covers everything you need to know about images in Dax Pro:
1. Supported formats — what works and what does not
2. Optimal dimensions — the sizes that look sharp without bloating pages
3. Compression — how to reduce file size without losing quality
4. Uploading via Decap CMS — the visual workflow
5. Using external URLs — Unsplash, your own CDN, other sources
6. Alt text — the accessibility and SEO requirement
7. Lazy loading — how Dax Pro handles it automatically
8. Where images live — the public/images/ folder and its rules
9. Common mistakes — the patterns that break layouts or slow pages
By the end, you will know exactly how to add any image to any part of your site, at the right size, in the right format, with the right metadata.
Supported Formats
Dax Pro does not restrict image formats — any format the browser understands works. But four formats cover 99% of use cases, and each has a clear best use.
JPEG (.jpg, .jpeg)
Best for: photographs, complex images with many colors, gradients, anything with smooth transitions.
Why: JPEG compression is designed for photographic content. A 1200×630 photo saved as JPEG at 80% quality is typically 100–200 KB. The same photo saved as PNG would be 1–3 MB.
When to avoid: images with text or sharp edges. JPEG compression creates artifacts around text that make it look fuzzy.
PNG (.png)
Best for: screenshots, logos, icons, images with transparency, images with text and sharp edges.
Why: PNG is lossless — every pixel is preserved. Text stays crisp, sharp edges stay sharp, transparency works.
When to avoid: photographs. PNG files of photographs are 5–10 times larger than JPEG for the same visual quality.
WebP (.webp)
Best for: almost everything. WebP is the modern replacement for both JPEG and PNG.
Why: WebP achieves the same visual quality as JPEG at 25–35% smaller file size, and the same quality as PNG at 25–50% smaller. It supports transparency and animation. It is supported by every modern browser (Chrome, Firefox, Safari 14+, Edge).
When to avoid: when you need to support very old browsers (IE 11, Safari 13 and earlier). For most sites in 2026, WebP is the default choice.
SVG (.svg)
Best for: logos, icons, illustrations, anything that can be described as vector shapes.
Why: SVG is resolution-independent — it looks sharp at any size. It is also text-based, so it compresses extremely well and can be edited in a text editor.
When to avoid: photographs or any image with fine detail that cannot be represented as simple shapes.
The Decision Tree
Choose a format in this order:
1. Is it a logo, icon, or simple illustration? → SVG
2. Is it a screenshot, image with text, or needs transparency? → WebP (or PNG if WebP not possible)
3. Is it a photograph or complex image? → WebP (or JPEG if WebP not possible)
Dax Pro's default: WebP. The theme ships with WebP images for logos, hero images, and feature images. Use WebP unless you have a specific reason not to.
Optimal Dimensions
Every image in Dax Pro has a display size. The image should be provided at 1× or 2× the display size (never smaller, rarely larger).
Hero image
Display size: 640 × 360 pixels on desktop (large layout), 400 × 225 on mobile
Optimal file size: 1280 × 720 pixels
Why 2×: on high-density screens (Retina, 4K), the image is rendered at 2× the CSS pixel size. A 640-pixel-wide display needs a 1280-pixel-wide image to look sharp.
Format: WebP
Typical file size: 60–120 KB
OpenGraph / social image
Display size: 1200 × 630 pixels (standard for Twitter, Facebook, LinkedIn)
Optimal file size: 1200 × 630 pixels (exact match — this is the maximum most platforms display)
Format: JPEG (for photos) or WebP (for graphics)
Typical file size: 100–200 KB
The OpenGraph image is what appears when the page is shared on social media. It is configured in _data/metadata.yaml (image field) and can be overridden per post (image in the post frontmatter).
Post featured image
Display size: 400 × 225 pixels (listing card thumbnail) and 1200 × 675 pixels (post page cover)
Optimal file size: 1200 × 675 pixels
Format: WebP or JPEG
Typical file size: 80–150 KB
The featured image appears in two places: as a thumbnail on /posts/ and the homepage Insights section, and as a large cover at the top of the post page. Providing it at 1200 pixels wide works for both.
Homepage section images
Display size: 600–800 pixels wide, variable height
Optimal file size: 1200 × 675 pixels (or 800 × 450 for smaller cards)
Format: WebP or JPEG
Typical file size: 80–150 KB
Inline images in post body
Display size: up to 760 pixels wide (the prose content width)
Optimal file size: 1200–1500 pixels wide
Format: WebP or JPEG
Typical file size: 80–200 KB
Logo and favicon
Logo: SVG, any size (scales infinitely)
Favicon: 32 × 32 pixels (.ico) or 512 × 512 pixels (.png or .webp)
Favicons are often displayed at 16 × 16, 32 × 32, or 48 × 48 pixels depending on context. Providing a 512 × 512 source ensures the browser can downscale without loss.
A rule that scales
When in doubt: provide the image at 2× the largest display size.
- A card that displays at 400 pixels → provide at 800 pixels
- A hero that displays at 640 pixels → provide at 1280 pixels
- A cover that displays at 1200 pixels → provide at 2400 pixels
- Image field — a button that says Choose an image or an image thumbnail
- Click it
- A media library opens
hero-dotnet-enterprise.webp✓IMG_20260512_143022.jpg✗ (meaningless, hard to find later)
The file size scales roughly linearly, so 2× dimensions typically produce 3–4× file size. That is acceptable — the quality gain on high-density screens is worth it.
Never provide larger than 2×. A 4000-pixel image displayed at 400 pixels wastes 90% of the bandwidth. The browser downsamples but the file still downloads.
Compression
An uncompressed image is 3–10 times larger than a compressed one. Compression is the single highest-impact optimization.
Tools
TinyPNG (tinypng.com) — for PNG and JPEG. Free for images under 5 MB. Drag-and-drop. Reduces file size 60–80% with no visible quality loss.
Squoosh (squoosh.app) — for any format. Google's image compression tool. Converts to WebP. Drag-and-drop, choose quality, download. The most versatile tool.
ImageOptim — macOS app. Batch process a folder. Excellent for PNG and JPEG.
Sharp — command-line tool. For developers. npm install -g sharp-cli, then sharp -i input.jpg -o output.webp --quality 80.
cwebp — WebP-specific CLI. cwebp -q 80 input.jpg -o output.webp. Faster than Sharp for WebP only.
Quality settings
JPEG: 75–85. Below 75 produces visible artifacts. Above 85 produces large files with minimal gain.
WebP: 75–85. WebP's quality scale is roughly equivalent to JPEG's — 80 WebP looks like 80 JPEG, but at half the file size.
PNG: lossless by definition. Use pngquant or TinyPNG for lossy PNG (reduces colors), or convert to WebP.
Target file sizes
| Image type | Target size |
|---|---|
| Hero image | 100–150 KB |
| OpenGraph image | 150–250 KB |
| Post featured image | 100–200 KB |
| Homepage section image | 100–200 KB |
| Inline image | 100–300 KB |
| Thumbnail | 30–60 KB |
| Logo (SVG) | 5–20 KB |
| Favicon | 5–20 KB |
If any image is above its target, compress it. If it is above 500 KB, compress it again — that image is dominating the page weight.
Uploading via Decap CMS
The Decap CMS media library is the visual workflow for uploading images.
Step 1: Open the media library
When you are editing a post or a page with an image field, look for the image picker:
The media library shows all images currently in public/images/. If it is empty, no images have been uploaded yet.
Step 2: Upload a new image
1. Click Upload in the top-right of the media library
2. Choose a file from your computer
3. The image uploads to public/images/ with a name derived from its original filename
4. The library shows the new image at the top
5. Click the image to select it
6. The image field updates with the path (/images/your-image.webp)
Step 3: Adjust alt text (if the field supports it)
Some image fields have a separate alt text field. If so, fill it in. If not, the post's title is used as a fallback alt text — not ideal but functional.
Step 4: Publish
Click Publish. The image path is saved to the frontmatter. On the next build, the image renders.
File naming: Decap CMS preserves the uploaded filename. my-photo.jpg becomes /images/my-photo.jpg. Rename files before uploading to keep paths clean:
Overwriting: if you upload a file with the same name as an existing file, Decap CMS overwrites the existing one. This is usually fine, but be careful — if two posts share the same image path, overwriting the image updates both.
Where uploaded files go
Decap CMS writes uploads to the path configured in public/admin/config.yml:
media_folder: "public/images"
public_folder: "/images"
media_folder — the actual folder on diskpublic_folder — the URL path used in frontmatterUploads go to public/images/. The path in frontmatter becomes /images/filename.webp. On build, public/images/ is copied to site/images/, and the URL /images/filename.webp resolves correctly.
Do not change media_folder or public_folder unless you understand how the build pipeline copies files. Changing one without the other breaks all image links.
Using External URLs
You do not have to upload images to public/images/. You can reference any external URL.
Unsplash (recommended for stock images)
Unsplash (unsplash.com) provides free images for commercial use. Every image has a direct URL.
To use an Unsplash image:
1. Find an image on Unsplash
2. Click Download or right-click the image and copy the image URL
3. The raw URL looks like https://images.unsplash.com/photo-1451187580459-43490279c0fa
4. Append query parameters to resize and optimize:
?w=1200&q=80&auto=format&fit=crop
w=1200 — width in pixelsq=80 — quality (80 is good for web)auto=format — serve WebP when the browser supports itfit=crop — crop to the requested aspect ratioFull URL:
https://images.unsplash.com/photo-1451187580459-43490279c0fa?w=1200&q=80&auto=format&fit=crop
Paste into the image field. No upload. No local file. Unsplash's CDN serves the image at the requested size.
Advantages:
Disadvantages:
Other external URLs
Any URL that serves an image works. Examples:
https://cdn.example.com/images/hero.webphttps://res.cloudinary.com/yourcloud/image/upload/w_1200/hero.jpghttps://raw.githubusercontent.com/user/repo/main/image.jpg (not recommended — slow, not designed for production)https://i.imgur.com/abc123.jpg (not recommended for production)For production sites, prefer either:
1. public/images/ (uploaded via Decap CMS)
2. A dedicated CDN (Cloudinary, Cloudflare Images, Bunny CDN)
External image URLs from random free image hosts are unreliable. They may disappear, change their URL structure, or add rate limits. Self-host or use a paid CDN for images that appear on your site permanently.
Alt Text
Every element should have an alt attribute. Alt text serves two purposes:
1. Accessibility — screen readers read alt text aloud to blind and low-vision users
2. SEO — search engines use alt text to understand image content
Dax Pro's default behavior:
image) — alt is the post title. This works but is not specific.
) — alt comes from the Markdown alt text.image_alt field in the frontmatter, or an empty string.Writing good alt text:

with alt text describing a gradient is not helpful — an empty alt is better: 
.Adding alt text in Markdown:
Adding alt text in frontmatter:
image: "https://images.unsplash.com/photo-1234567890?w=1200&q=80&auto=format&fit=crop"
image_alt: "A developer's desk with a laptop, notebook, and coffee"
Alt text is required for featured images. Dax Pro's templates use the post title as a fallback, but a dedicated image_alt is better for SEO and accessibility. If the image field has an adjacent alt field, use it.
Lazy Loading
Dax Pro automatically applies loading="lazy" to images below the fold and fetchpriority="high" to the hero image (above the fold).
What loading="lazy" does: the browser defers loading the image until it is about to enter the viewport. Images below the fold do not block the initial page render. The page becomes interactive faster.
What fetchpriority="high" does: the browser loads the image with high priority, ensuring it appears as fast as possible.
Where Dax Pro applies these:
fetchpriority="high", no lazy loadingloading="lazy"loading="lazy"fetchpriority="high" (it is above the fold on the post page)You do not need to configure lazy loading. It works automatically. If you edit a template and add an tag, add loading="lazy" yourself unless the image is above the fold.
Where Images Live
All local images live in public/images/. This folder is copied to site/images/ on every build. The public URL is /images/filename.ext.
Structure:
public/
└── images/
├── dax-primary-logo.webp
├── hero-main.webp
├── og-default.jpg
├── favicon.ico
└── posts/
├── why-static-sites-win.webp
├── blazor-vs-dax.webp
└── decap-cms-guide.webp
Subfolders are fine. Organize images by type, date, or topic:
images/posts/ — featured images for blog postsimages/services/ — featured images for servicesimages/homepage/ — homepage section imagesimages/og/ — OpenGraph imagesThe URL includes the subfolder: /images/posts/why-static-sites-win.webp.
Do not use spaces in filenames. /images/my image.webp breaks in URLs. Use hyphens: /images/my-image.webp.
Do not use uppercase in filenames. /images/Hero.WebP is case-sensitive on Linux servers but not Windows. Use lowercase: /images/hero.webp.
Do not put images outside public/. Files outside public/ are not copied to site/. If you put an image in images/ (root) instead of public/images/, it does not appear on the built site.
Common Image Mistakes
Mistake 1: Providing images at original resolution.
A 4000×3000 photo from a phone camera is 4–8 MB. Displayed at 640×360, it wastes 95% of the bandwidth. Resize before uploading.
Mistake 2: Using PNG for photographs.
A photograph saved as PNG is 5–10× larger than the same photograph as JPEG. Screenshots and graphics are fine as PNG; photographs should be JPEG or WebP.
Mistake 3: Not compressing.
An uncompressed 1280×720 WebP is 500 KB. Compressed at quality 80, it is 80 KB. The visual difference is invisible; the file size difference is 6×.
Mistake 4: Spaces or uppercase in filenames.
/images/My Image.webp breaks. Use /images/my-image.webp.
Mistake 5: Missing alt text.
Featured images have a fallback (post title), but inline images with empty alt text fail accessibility audits. Always provide alt text for content images.
Mistake 6: Hotlinking from unreliable sources.
https://example.com/some-image.jpg may disappear tomorrow. Upload important images to public/images/ or a CDN you control.
Mistake 7: Images outside public/.
A file at images/hero.webp (root level) is not copied to site/. Only public/ contents are copied. Put images in public/images/.
Mistake 8: Forgetting image_alt in frontmatter.
The image_alt field in the frontmatter is used for the featured image's alt text. Without it, the post title is used — which is not always descriptive.
Mistake 9: Using an inline image URL that returns HTML, not an image.
Some URLs (like Google Image search results) are HTML pages, not image files. https://example.com/photo may return an HTML page. Use the direct image URL, usually ending in .jpg, .png, .webp, or .svg.
Mistake 10: Not testing the image on mobile.
An image that looks great on a 1920-pixel desktop may be too small on a phone at 2× density. Always check the mobile view (resize the browser or use DevTools' device emulation).
Mistake 11: Favicon is too large or wrong format.
A 5000×5000 favicon is 50 KB that the browser downloads on every page. Favicons should be 32×32 or 512×512. Use .ico (universal) or .png. WebP favicons work in modern browsers but not all.
Mistake 12: Using the same image for everything.
A single hero image reused on every page is not a bug, but it is a missed opportunity for visual variety. Each page benefits from a specific image.
Verifying Images Work
After adding an image:
1. Rebuild — dotnet run -- build
2. Open the page — navigate to the page in a browser
3. Confirm the image renders — no broken icon, no blank space
4. Check the file size — open DevTools' Network tab, find the image request, confirm it is under 300 KB
5. Check the URL — the image request URL is /images/..., not a 404
6. Check mobile — resize the browser to 375 pixels wide, confirm the image scales correctly
7. Check alt text — view source, find the tag, confirm alt is populated
8. Check lazy loading — for below-fold images, confirm loading="lazy" is in the source
If the image does not render:
/images/filename.webp must match the actual file at public/images/filename.webppublic/ — files outside public/ are not copiedIf the image renders but the page is slow:
What You Have Now
After this chapter, you can:
public/images/Images are the visual layer of your site. When they are fast, sized correctly, and described well, the site feels professional. When they are slow, oversized, or missing alt text, the site feels broken — even if everything else is perfect.
The next chapter is SEO — how Dax Pro generates sitemaps, robots.txt, OpenGraph tags, and JSON-LD structured data automatically, and what you need to do to make search engines and social platforms index your site correctly.