Getting started
KahunaCart adds native ecommerce to Grav 2.0. This page takes you from a fresh install to a completed test order.
Before you begin
- Grav 2.0 or later. KahunaCart was built for the latest Grav 2.0 version, and it's not compatible with Grav 1.7.
- The Admin plugin (admin2) 2.0 or later, as KahunaCart utilizes Admin2's modern SPA interface.
- The API plugin 1.0 or later. Every admin screen and admin action goes through it. This is a hard dependency.
- PHP 8.3+ with PDO. SQLite works out of the box. MySQL 8+, MariaDB 10.6+, and PostgreSQL 14+ are supported.
- The Email plugin, only for order confirmation emails and abandoned-cart reminders. It is not a declared dependency. Without it, those email jobs fail with
Email plugin is not available. - Grav's scheduler, required for emails, download grants, expired stock holds, and cart cleanup. See Troubleshooting if these never run.
Install KahunaCart
-
1
Install the license you received when you purchased KahunaCart on your Grav site. A valid license is needed to be able to install KahunaCart.
-
2
Install from Admin or via GPM (
bin/gpm install kuhunacart) in the CLI on your Grav site. -
3
SqlLite is default and automatically gets configured. If you wish to use MySQL or PostgreSQL, you must first configure KahunaCart to use it, and then apply the schema yourself. The default migration policy does not auto-migrate a server database.
BASHbin/plugin kahunacart migrate -
4
Check the result.
BASHbin/plugin kahunacart status
status prints the database engine, any pending migration steps, the job queue counts, and every registered payment provider. A clean install lists the built-in offline provider and nothing else.
Where KahunaCart stores things
| Thing | Default location | Config key |
|---|---|---|
| SQLite database | user/data/kahunacart/db/kahunacart.sqlite |
database.sqlite.path |
| Downloadable files | user/data/kahunacart/files |
downloads.path |
| Storefront routes | /shop and everything under it |
route |
| Admin screen | Admin sidebar → KahunaCart (/plugin/kahunacart) |
— |
| Plugin config | user/config/plugins/kahunacart.yaml |
— |
KahunaCart creates both data directories on first use and writes a deny-all .htaccess and an empty index.html into each. This protects Apache only.
Warning
nginx and Caddy ignore .htaccess. Run the check in Troubleshooting, and consider moving both directories outside the document root.
Your first product
A product needs a title. Every other field has a default. The price lives on the variant, not on the product. Every product gets one default variant, and a single-price product never shows a variant picker.
| Field | Default | What it does |
|---|---|---|
| Type | physical |
physical or digital. Digital products skip shipping and are the ones that can carry downloadable files. |
| Status | draft |
Only published products appear on the storefront. |
| Slug | Derived from the title | The public URL segment, as in /shop/product/my-widget. |
| Price | — | Set on the default variant. |
- In the admin sidebar, click KahunaCart.
- Go to Products → New.
- Enter a Title.
- Set Price on the default variant.
- Set Status to published.
- Click Save.
The product is live at {route}/product/{slug}. No cache clear is needed.
To create the same product over the API:
curl -X POST https://example.com/api/kahunacart/products \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"title":"My Widget","status":"published","type":"physical","variant":{"price":"19.99","sku":"WID-1"}}'
variant.price is a decimal string in the store currency, converted to minor units server-side. See Money conventions.
Your first sale
You do not need a payment provider to test a sale. The base plugin ships the offline provider and enables it by default. It places the order with payment status pending, and you mark it paid by hand when the money arrives.
- Visit
/shopand open your product. - Add it to the cart, go to
/shop/cart, then click Checkout. - Enter an email address and a billing address.
- Pick Bank Transfer as the payment method and place the order.
- In the admin, go to Orders and open the new order.
- Click Mark paid.
The order's payment status is now paid.
Note
Step 4 lands the customer on the receipt at /shop/order/{hash}. That hash is the customer's only handle on their order, so it is long and random, and the page is not linked from anywhere.
The admin sidebar badge counts completed orders still awaiting payment. To take real money, install one of the payment providers.
Turn off the offline payment method
Set offline.enabled to false. The offline provider stops registering itself and Bank Transfer disappears from checkout.
Related
- Configuration — every config key, and the database options.
- Products and catalog — variants, stock, categories, digital files.
- Storefront — routes, template overrides, Twig functions, buy buttons in your own pages.
- Payment providers — Stripe, Polar, PayPal, and the offline method.