How to write payment terms clients actually read
Five lines that cut late payments without sounding strict, with examples you can copy.
Blog
Three recent articles as framed cards with a cover, topic tag, excerpt and an author row with date.
3 framed cards · topic tag · author + date footer · hover lift
Practical advice on getting paid, from people who send a lot of invoices.
Five lines that cut late payments without sounding strict, with examples you can copy.
What’s normal, what’s legal and how to bring it up with a client you want to keep.
Bill the same client every month without lifting a finger, with prorating built in.
type Post = { title: string; excerpt: string; tag: string; href: string; cover: string; author: string; date: string; dateTime: string };
const posts: Post[] = [
{ title: "How to write payment terms clients actually read", excerpt: "Five lines that cut late payments without sounding strict, with examples you can copy.", tag: "Guides",
href: "/blog/payment-terms", cover: "/blog/payment-terms.jpg", author: "Ingrid Solberg", date: "Oct 8, 2026", dateTime: "2026-10-08" },
{ title: "Late fees: when to charge them and how much", excerpt: "What’s normal, what’s legal and how to bring it up with a client you want to keep.", tag: "Getting paid",
href: "/blog/late-fees", cover: "/blog/late-fees.jpg", author: "Samir Haddad", date: "Sep 29, 2026", dateTime: "2026-09-29" },
{ title: "What’s new: recurring invoices for retainers", excerpt: "Bill the same client every month without lifting a finger, with prorating built in.", tag: "Product",
href: "/blog/recurring-invoices", cover: "/blog/recurring.jpg", author: "Felix Navarro", date: "Sep 17, 2026", dateTime: "2026-09-17" },
];
const initials = (name: string) => name.split(" ").map((w) => w[0]).join("").slice(0, 2);
export function BlogCardsWithAuthors() {
return (
<section aria-labelledby="blog-cards-title" className="bg-surface px-5 py-16 font-sans sm:px-10 sm:py-20">
<div className="mx-auto max-w-6xl">
<div className="flex flex-wrap items-end justify-between gap-4">
<div className="max-w-xl">
<h2 id="blog-cards-title" className="text-3xl font-semibold tracking-tight text-fg sm:text-4xl">From the blog</h2>
<p className="mt-4 text-base text-fg-muted sm:text-lg">Practical advice on getting paid, from people who send a lot of invoices.</p>
</div>
<a href="/blog" className="inline-flex h-9 items-center rounded border border-border-strong bg-bg px-3.5 text-sm font-medium text-fg transition hover:bg-surface">View all posts</a>
</div>
<div className="mt-10 grid gap-4 md:grid-cols-3">
{posts.map((p) => (
<a key={p.href} href={p.href} className="group grid grid-rows-[auto_1fr_auto] overflow-hidden rounded-xl border border-border bg-bg transition hover:border-border-strong hover:shadow-xl">
<img src={p.cover} alt="" className="aspect-video w-full bg-primary-soft object-cover" />
<div className="grid content-start gap-2.5 p-[22px]">
<span className="w-fit rounded-full bg-surface-2 px-2 py-0.5 text-xs font-medium text-fg-muted">{p.tag}</span>
<h3 className="text-[17px] font-semibold leading-snug tracking-tight text-fg group-hover:underline group-hover:underline-offset-4">{p.title}</h3>
<p className="text-sm leading-relaxed text-fg-muted">{p.excerpt}</p>
</div>
<div className="flex items-center gap-2.5 border-t border-border px-[22px] py-3.5 text-[13px]">
<span className="grid size-7 place-items-center rounded-full bg-primary-soft text-[11px] font-medium text-primary-soft-fg" aria-hidden>{initials(p.author)}</span>
<span className="font-medium text-fg">{p.author}</span>
<time dateTime={p.dateTime} className="ml-auto whitespace-nowrap text-fg-subtle">{p.date}</time>
</div>
</a>
))}
</div>
</div>
</section>
);
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.