The question comes up almost every time someone looks at Slim Minima seriously. "Where are the plugins? How do I add a payment button, a booking widget, a quote form?"
Here is the honest answer up front. There is no plugin marketplace. There is no one-click install for Stripe or Cal.com. You extend Slim Minima by writing code, often with an AI agent doing most of the typing. That is not a gap I forgot to fill. It is the whole idea.
Forms are already built in and need no code. Booking is usually a five-minute embed. Payments are a small custom block plus a server action. None of it requires a plugin store, but you (or your agent) own the code.
Plugins are how WordPress got slow, insecure, and unpredictable. I wrote more about that in why WordPress does not work well in the AI age. Slim Minima takes the opposite bet: a small core, no dynamic plugin loader, and extensions that are just TypeScript and React files you can read. The tradeoff is real, and I will be specific about it at the end.
Let me walk through the three cases people actually ask about.
Forms: already built in, no code needed
This is the easy one, because forms ship with the CMS.
You do not write any code to add a contact form, a quote request, a newsletter signup, or a "book a call" enquiry. You build the form once in the admin panel, then drop it on any page.
Here is the flow:
- Go to
/admin/contactsand define a reusable form. Forms are stored in settings, so there is no database migration to run. - Add fields. The field types are text, email, tel, textarea, and select. Each field can be required, and select fields take your own options.
- Open the page you want it on, drop in the
contact-formblock, and pick the form you built. - Publish.
What happens when someone submits is worth understanding, because it is built to be safe by default.
- The form posts to
/api/contact, which is rate-limited to 8 submissions per IP per 10 minutes. - There is a honeypot field named
website. If a bot fills it, the request silently succeeds and the data is dropped. (If you ever build your own form, never name a real fieldwebsiteor you will throw away genuine submissions.) - The receiver email address is never in the page HTML. It is validated through an HMAC-SHA256 signed token, so nobody can rewrite the form to mail themselves your leads.
- Every submission is stored in the database, even if you have not configured email yet. You will not lose enquiries because SMTP was not set up.
- If you have configured SMTP, the submission is also emailed to you. Email is optional and uses Nodemailer.
- Submissions are capped at 40 fields and 5000 characters per field, and the HTML is sanitized.
So for forms, the answer is: there is nothing to add. It is in the box.
Booking: embed a tool, or build a small form
Slim Minima does not have its own calendar or scheduling engine. For booking, you connect an existing tool. There are two realistic routes.
Option A: embed Cal.com (the fast path)
For most people this is the right call. Cal.com is open source, has a free tier, and gives you an embed snippet. Calendly works the same way.
- Set up your event type in Cal.com and copy its embed code.
- On the page where you want booking, drop in the built-in
html-embedblock. - Paste the embed snippet and publish.
That is the whole job. You get availability, time zones, confirmations, and reminders from a tool built for it, with no code. When a scheduling provider already solves the hard parts, embedding it beats rebuilding it.
Option B: a small booking-form custom block
If you do not want a third-party iframe, you can build a booking-form block that posts the requested time to your own calendar tool's API. This is custom-block territory, the same path as payments below. It is more work and you own the integration, so only take it if the embed genuinely does not fit. For most small sites, the embed wins.
Ecommerce and payments: a custom block plus a server action
This is where you write real code. I want to be clear about scope before the steps.
Slim Minima is not a store platform. There is no inventory engine, no cart, no order management, no tax tables. If you are selling a real catalog with hundreds of SKUs, variants, and stock levels, use a tool built for that. Shopify and WooCommerce exist for good reasons, and I would point you to them without hesitation.
But a lot of "I need ecommerce" is actually "I want to sell three things." A digital download. A consulting package. A deposit. For that, a single Stripe checkout block is plenty.
Here is the code path for adding a Stripe checkout button.
- Build a custom block, for example
product-cardorstripe-checkout. A block is one file:src/blocks/<name>/index.tsx, default-exportingdefineBlock<Props>({...}). - Register it. Import your block in
src/blocks/registry.tsand add it to theALLarray. That single edit makes the palette, the settings form, Zod validation, the REST API, and the public renderer all pick it up. No other wiring. - Add the server side. Put a server action in
src/app/admin/actions.tsor, more commonly for payments, an API route undersrc/app/api/(for examplesrc/app/api/checkout/route.ts). This is where you call the Stripe SDK to create a Checkout Session and return the URL. - Integrate Stripe. Follow the Stripe Checkout docs, put your keys in environment variables, and use Stripe-hosted checkout (simplest) or Stripe Elements if you want the form on your own page.
- Wire it up. Drop your block on a page, set the price and product name in its fields, and the Render output links to your checkout route.
A minimal sketch of the block, to show the shape rather than the full thing:
// src/blocks/stripe-checkout/index.tsx
import { z } from "zod";
import { defineBlock } from "@/blocks/define";
export default defineBlock({
type: "stripe-checkout",
label: "Stripe checkout button",
description: "A button that starts a Stripe Checkout session.",
icon: "credit-card",
schema: z.object({
productName: z.string(),
priceId: z.string(),
buttonLabel: z.string(),
}),
defaults: {
productName: "Consulting call",
priceId: "",
buttonLabel: "Buy now",
},
fields: [
{ kind: "text", name: "productName", label: "Product name" },
{ kind: "text", name: "priceId", label: "Stripe price ID" },
{ kind: "text", name: "buttonLabel", label: "Button label" },
],
Render: ({ priceId, buttonLabel }) => (
<form action="/api/checkout" method="POST" className="cms-checkout">
<input type="hidden" name="priceId" value={priceId} />
<button type="submit">{buttonLabel}</button>
</form>
),
});
The Render function is pure and synchronous: no hooks, no async. The actual Stripe call lives in the /api/checkout route, where you read the priceId, create a Checkout Session with the Stripe SDK, and redirect. Style the button with cms-* classes and CSS variables in globals.css, and keep the background-only card style (no borders).
A booking-form custom block follows the exact same pattern: a block file, a registry entry, and a route under src/app/api/ that posts to your calendar tool. The block system is the same whether you are taking a payment or a booking. If you want a fuller walkthrough of building real client features on this, I covered it in building a client-ready website with Slim Minima.
The honest tradeoff
So why do it this way instead of a plugin store?
You get control. The code is yours, you can read every line, and nothing dynamically loads third-party PHP into your runtime. Because there is no plugin loader, there is no plugin-driven attack surface, which is part of why the security model stays simple. There is no plugin bloat slowing the site down. And the MIT license means you keep the code and the database forever.
The cost is equally plain. You, or an AI agent, write the code. There is no button that adds Stripe for you. If you cannot write a small Next.js API route and are not comfortable directing an agent to do it, the payment case will be harder for you than installing a WordPress plugin.
That is the deal, and I would rather state it than dress it up. I explained the reasoning in why I built Slim Minima.
This is also exactly the kind of work AI agents are good at. "Add a Stripe checkout block that creates a Checkout Session for a given price ID" is a well-scoped prompt, and the block system is designed so the agent only has to touch two or three files.
Who this suits, and who should skip it
This approach fits you if:
- You want forms now, with zero code. (Everyone gets this.)
- You sell a handful of products or services, not a large catalog.
- You are comfortable writing a small amount of code, or directing an AI agent to.
- You value owning the code and keeping the site fast and cheap.
Look elsewhere if:
- You are running a real store with inventory, variants, and order management. Use Shopify or WooCommerce.
- You need a checkout live today and cannot write or commission any code.
- You need real-time features. Slim Minima is built for content and marketing sites, not write-heavy or real-time apps.
Frequently asked questions
Does Slim Minima have a plugin marketplace? No. There is no plugin marketplace and no one-click install. Forms are built in, and other features (payments, booking, custom blocks) are added with TypeScript and React code. This is deliberate: no plugin loader means no plugin-driven attack surface and no plugin bloat.
How do I add a contact form to Slim Minima?
You do not need code. Build a reusable form in /admin/contacts, then drop the contact-form block onto any page and select your form. Submissions are rate-limited, protected by a honeypot field, stored in the database, and emailed via SMTP if you have configured it.
Can I take payments with Stripe on Slim Minima?
Yes, for a small number of products. You build a custom block (such as a checkout button), add an API route under src/app/api/ that calls the Stripe SDK to create a Checkout Session, and wire the block onto a page. For a large catalog with inventory, use a dedicated store platform like Shopify instead.
What is the easiest way to add booking to a Slim Minima site?
Embed a scheduling tool. Set up an event type in Cal.com or Calendly, copy the embed snippet, and paste it into the built-in html-embed block on any page. No code required. Building your own booking-form block is possible but more work.
Do I need to be a developer to extend Slim Minima? For forms and embeds, no. For payments and custom blocks, you need to write a small amount of code or direct an AI agent to do it. The block system is designed so an agent usually only edits two or three files to add a feature.
My verdict
If you need forms, you already have them, so stop looking and use the contact-form block. If you need booking, embed Cal.com through the html-embed block and move on. If you need to sell a few things, write a small Stripe checkout block and an API route, or have an agent do it.
If you need a full store with inventory and orders, do not force it onto Slim Minima: reach for Shopify or WooCommerce and keep your content site separate. The line is simple: small and owned, write the code; large and operational, use the dedicated tool.

