Web development conventions for Adynato projects. Covers image optimization with img4web, asset management, component patterns, styling, and performance best practices...
Use this skill for all Adynato web projects and frontend development.
When adding images or visual assets to any Adynato project, use adynato/img4web.
# Install globally
npm install -g @adynato/img4web
# Or use npx
npx @adynato/img4web <input> [options]
# Basic optimization
npx @adynato/img4web ./src/images
# With specific output formats
npx @adynato/img4web ./image.png --formats webp,avif
# Generate responsive sizes
npx @adynato/img4web ./hero.jpg --sizes 640,1024,1920
# Watch mode during development
npx @adynato/img4web ./src/images --watch
| Use Case | Max Width | Formats | Quality |
|---|---|---|---|
| Hero/Banner | 1920px | WebP, AVIF, fallback JPG | 80-85 |
| Content Images | 1200px | WebP, AVIF | 80 |
| Thumbnails | 400px | WebP | 75 |
| Icons/Logos | Original | SVG preferred, else PNG | Lossless |
| OG Images | 1200x630 | PNG or JPG | 90 |
Always use responsive images with modern format fallbacks:
// Next.js
import Image from 'next/image'
<Image
src="/images/hero.webp"
alt="Descriptive alt text"
width={1920}
height={1080}
priority // for above-fold images
placeholder="blur"
blurDataURL={blurDataUrl}
/>
<!-- Plain HTML with picture element -->
<picture>
<source srcset="/images/hero.avif" type="image/avif">
<source srcset="/images/hero.webp" type="image/webp">
<img src="/images/hero.jpg" alt="Descriptive alt text" loading="lazy">
</picture>
public/
βββ images/
β βββ blog/
β β βββ [post-slug]/
β β βββ cover.webp
β β βββ cover.avif
β β βββ *.webp
β βββ og/
β β βββ [page-slug].png
β βββ icons/
β β βββ *.svg
β βββ hero/
β βββ *.webp
βββ fonts/
β βββ *.woff2
βββ videos/
βββ *.mp4
PascalCase.tsx (e.g., Button.tsx, NavBar.tsx)camelCase.ts (e.g., formatDate.ts)useCamelCase.ts (e.g., useAuth.ts)types.ts or [feature].types.ts// components/Button.tsx
import { type ReactNode } from 'react'
interface ButtonProps {
children: ReactNode
variant?: 'primary' | 'secondary'
onClick?: () => void
}
export function Button({ children, variant = 'primary', onClick }: ButtonProps) {
return (
<button
className={`btn btn-${variant}`}
onClick={onClick}
>
{children}
</button>
)
}
Prefer named exports over default exports:
// Good
export function Button() { ... }
export function Input() { ... }
// Avoid
export default function Button() { ... }
Before deploying any web project:
priority or fetchpriority="high"loading="lazy"// Use consistent ordering: layout, spacing, sizing, typography, colors, effects
<div className="flex items-center gap-4 p-4 w-full text-sm text-gray-700 bg-white rounded-lg shadow-md">
Always support dark mode:
<div className="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100">