Nano Cart
A flat-file PHP product catalogue framework for static client sites. Sells fixed-price products through hosted checkout links (Stripe Payment Link, PayPal, Square, Gumroad, Ko-fi, or any URL). Drops in at /shop/. No database, no framework, no scope creep. JSON files, hand-written PHP, and a portable admin you upload only when you need it.
The problem Nano Cart solves
Many small client sites need to sell a fixed catalogue of 20 to 50 products: a potter, a print-maker, a jewellery designer, an author, a consultant, a gallery. Setting them up with Shopify is overkill (a hosted platform with monthly fees for 30 fixed-price items), and WooCommerce drags in WordPress + MySQL + ongoing plugin patching that the static-site brief was specifically built to avoid. Nano Cart exists for that exact gap. The host site stays static; Nano Cart slots a small product catalogue into it that links each item out to a Stripe Payment Link, PayPal hosted checkout, Square, Gumroad, Ko-fi, or any processor-hosted URL. It is deliberately not a general-purpose e-commerce platform: no variants, no quantity selectors, no multi-item cart, no inventory. It does one thing - serve a small fixed catalogue with strong SEO output and one-click external checkout - and tries to do it well in around 5,750 lines of hand-written code.
Free under MIT · paid licence removes the footer
Nano Cart is free under MIT. It ships with a small Powered by Nano Cart. Developed by Digital Fracture. footer on the pages it renders. For commercial work, agency client deliverables, or simply a cleaner footer, purchase a perpetual per-domain licence.
Single domain
- One licensed domain
- Footer attribution removed
- Perpetual — never expires
- Ed25519 cryptographic verification
- Localhost / dev domains free
Agency 3-pack
- Three licensed domains
- £23 per site
- Manage client portfolio cleanly
- Perpetual — never expires
- Best for small studios
Agency unlimited
- Unlimited domains, one agency
- All current + future client projects
- Perpetual — never expires
- Best value for active studios
Licences are verified with an Ed25519-signed token bound to your domain. Need a custom arrangement for a larger studio? Get in touch.
How it works
Six design choices that define the whole project.
JSON files are the database
One product = one .json file in /products/. One category = one file in /categories/. No MySQL, no SQLite, no setup wizard for a database connection. Backups are a folder copy.
External checkout, your choice
Each product links to a Stripe Payment Link, PayPal hosted checkout, Square, Gumroad, Ko-fi, or any URL. Nano Cart renders its own buy button as a plain <a href>. No SDKs, no embed code, no JavaScript on the shop page.
Drops in at /shop/
The reader-facing code sits permanently inside the client's webroot at /shop/. It renders the homepage, category pages, and product pages with full SEO metadata on every page.
Admin is portable, not permanent
The admin folder is identical for every deployment. Upload it via SFTP when you want to edit, remove it afterwards. No persistent admin = drastically reduced attack surface on client sites.
One-click web installer
An install.php script auto-detects your hosting layout (cPanel, addon domains, standard), creates the outside-webroot config directory, writes bootstrap.php for you, and hands off to the setup wizard. No editing PHP config files by hand.
Full image manager built in
Multi-image drag-and-drop upload, drag-to-reorder gallery, alt-text editing, subfolder support. EXIF orientation applied, source dimension cap, three size variants generated in JPEG and WebP automatically.
Architecture in one diagram
The whole system in three layers - what stays on the client server permanently, what only exists during editing, and what sits above the webroot.
+-----------------------------------------------------------------+ | CLIENT SITE (permanent) | | | | /public_html/shop/ | | |-- products/ <-- JSON files (the "database") | | |-- categories/ <-- JSON files | | |-- media/ <-- uploaded images + variants | | |-- assets/ <-- nano-cart.css, nano-cart.js | | |-- core.php <-- parser, renderer, helpers | | |-- index.php <-- shop homepage | | |-- category.php <-- category page | | |-- product.php <-- product page | | |-- template.php <-- per-site HTML wrapper | | |-- bootstrap.php <-- per-site config paths | | |-- licence.php <-- Ed25519 footer verification | | +-- sitemap.xml <-- regenerated on save | | | | /shop-config/ <-- OUTSIDE webroot | | |-- config.json <-- password hash, licence, settings | | +-- rate-limit.json <-- login attempt tracking | +-----------------------------------------------------------------+ +-----------------------------------------------------------------+ | UNIVERSAL PORTABLE ADMIN (ephemeral) | | | | Uploaded to /public_html/shop/admin/ when editing. | | Removed afterwards. Identical for every deployment. | | Contains zero site-specific data. | +-----------------------------------------------------------------+
Who Nano Cart is for
Nano Cart is built for web developers and agencies who maintain static sites for clients and need to sell a small, fixed catalogue without taking on a database, a CMS, or a hosted platform. Suitable shops: a potter selling 30 hand-thrown pieces through Stripe Payment Links, a jewellery designer with 50 one-off pieces and PayPal checkout, an author selling signed editions and merch with Gumroad, a consultant offering fixed-price service packages with Calendly enquiry, a gallery cataloguing artworks for sale with a contact-form enquiry action. The tool assumes operators are fluent with SFTP - it is not aimed at non-technical end users. For a non-technical shop owner who needs a hosted dashboard, full variants, and inventory tracking, Shopify is the right answer.
Not for you if you sell variant-heavy retail (clothing in sizes/colours, use Shopify), need a catalogue over ~150 SKUs (use WooCommerce), want a multi-item shopping cart (use Big Cartel or Gumroad), or sell subscriptions (use Lemon Squeezy). Nano Cart's smallness is the product.
SEO baked in, not bolted on
Every shop page ships with the technical SEO most WooCommerce sites need three plugins to achieve.
Full metadata pass
Custom <title> and meta description from product fields, canonical URL computed at render time, and a clean <head> with no plugin-style noise.
Open Graph & Twitter Cards
Product pages unfurl correctly on Facebook, LinkedIn, X, Slack, and Discord without any extra configuration. Primary product image and alt text propagate automatically.
JSON-LD Product & BreadcrumbList
Every product page emits valid Product structured data with name, image, brand, sku, and offers. Plus BreadcrumbList on category and product pages.
Clean URLs via .htaccess
No ?product=42. Products live at /shop/<category>/<sku>/ with the SKU authoritative. Max two hierarchy levels, max three breadcrumb segments.
XML sitemap, regenerated
The sitemap is rewritten on every admin save, with drafts excluded automatically. Submit once to Google Search Console, forget about it.
Lazy images with proper alt
Every <img> ships with loading="lazy" and descriptive alt text from the image manager. Admin enforces non-empty alt at upload time. WebP variants served via <picture>.
Semantic HTML5 structure
Pages render with <article>, <figure>, <picture>, and proper heading hierarchy. Search crawlers and screen readers get the structure they expect, no <div> soup.
Mobile-first by design
Templates designed for a 375px viewport. Sticky buy button on scroll. Scroll-snap image gallery. Tap targets at least 44px. Lighthouse SEO score 100 on real product pages.
Why not Shopify, WooCommerce, or Big Cartel?
All three are excellent for shops that need them. Shopify is a full hosted e-commerce platform with monthly fees, ideal for variant-heavy retail; for 30 fixed-price items it is overkill. WooCommerce requires WordPress + MySQL + ongoing plugin patching, which is exactly what the static-site brief was built to avoid. Big Cartel is a hosted option closer in spirit (small shops, no variants) but it's a subscription with limits on item count and your shop lives on their domain. Nano Cart deliberately stays smaller than all of them, runs in the operator's own webroot at /shop/, and uses external checkout links so the visitor never has to trust a multi-tenant cart. When the admin is removed, only flat JSON files and images remain on the server.
Side-by-side
| Nano Cart | Shopify | WooCommerce | Big Cartel | |
|---|---|---|---|---|
| Database | None | Hosted | MySQL required | Hosted |
| Monthly fee | None (perpetual licence) | From $39 | None (self-hosted) | From $9.99 |
| Drop-in to existing site | Yes (/shop/) | No - replaces site | No - replaces site | No - your shop on their domain |
| Variants / inventory | No (intentional) | Yes | Yes | Limited |
| Codebase size | ~5,750 lines | Hosted (huge) | ~50,000+ lines | Hosted |
| Backup | rsync the folder | Vendor lock-in | DB dump + files | Vendor lock-in |
What a product looks like on disk
One product = one JSON file. The sku field is the URL slug. checkout_url points to wherever you want the buy button to send the visitor.
/products/pot-001.json
{
"sku": "pot-001",
"title": "Hand-thrown stoneware mug",
"short_description": "Deep cobalt glaze on natural stoneware, 350ml.",
"long_description": "Each mug is thrown on the wheel...",
"category": "pottery",
"price_display": "£32.00",
"checkout_url": "https://buy.stripe.com/abc123",
"images": [
{ "file": "main", "alt": "Mug, side view", "is_primary": true },
{ "file": "alt-1", "alt": "Mug, top view", "is_primary": false }
],
"featured": true,
"hero_featured": true,
"image_width": "500",
"image_height": "auto",
"image_fit": "contain",
"status": "published"
}
Product fields
sku- product identifier, used as filename and URL slug,[a-z0-9-]+only.title- product name, used in<h1>and as card title.short_description- meta description and card preview, around 150 characters.long_description- Markdown source for the product page body.category- slug of an existing category. One category per product.price_display- free-form text (£25.00,POA,From £40). No parsing.checkout_url- HTTPS URL to your external payment processor.images- array of{file, alt, is_primary}entries managed by the image manager.featured/hero_featured- flags for homepage placement.image_width/image_height/image_fit- per-product display sizing.status-publishedordraft. Drafts are hidden from listings, sitemap, and JSON-LD.
Categories have a similar small JSON file under /categories/ with slug, name, description (Markdown), optional banner image, sort order, and per-category image fitting.
Security model
Concrete protections - no marketing words about being "secure", just the actual mechanisms.
Admin removed when not in use
The admin folder is uploaded via SFTP to edit, then deleted. There is no persistent admin URL to brute-force, scrape, or scan with WordPress wordlists.
Password and licence outside webroot
The bcrypt password hash, the licence key, and rate-limit state live in a folder above public_html/. Even with a misconfigured Apache, nothing serves them over HTTP.
Exponential-backoff rate limiting
Failed logins per IP add a response delay: 0 seconds for the first 5, then 2, 4, 8, and 16 seconds at higher thresholds. Never a hard lockout (which would be a DoS vector). Brute force is impractical; the legitimate operator can always log in eventually.
External checkout, no PCI scope
Nano Cart never sees or stores payment data. The buy button is a plain <a href> to the operator's external payment processor (Stripe, PayPal, etc). All card handling stays with the processor.
Uploaded images re-encoded
Every upload is verified with finfo (magic bytes), EXIF-stripped via re-encoding through GD, and capped at a configurable source width. /media/ has PHP execution disabled by .htaccess.
HTTPS-only sessions, CSRF on POST
Admin sessions use HttpOnly Secure SameSite=Strict cookies. Every POST form includes a CSRF token validated on the server before the action runs.
Requirements & backups
- PHP 8.1 or later
- Apache with
mod_rewrite(for clean URLs) - HTTPS (the admin login requires it, and the buy-button flow assumes a secure context)
- SFTP access to the client site (for deploying the frontend and uploading the admin)
- GD extension (built into most PHP installs); Imagick supported as a fallback
- libsodium (built into PHP 8.1+) for licence verification
Tested on shared hosting (cPanel-style). No special privileges are required.
Backups are a folder copy
JSON files in /products/ and /categories/, plus uploaded media in /media/, are the only persistence - there is no database to dump and restore. A simple cron + rsync line on a backup machine handles it for any number of client sites:
# Daily 03:00 backup of one client's shop content and config 0 3 * * * rsync -az -e "ssh -p 22" \ user@clientsite.com:/home/clientuser/public_html/shop/ \ /backups/clientname/shop/ 5 3 * * * rsync -az -e "ssh -p 22" \ user@clientsite.com:/home/clientuser/shop-config/ \ /backups/clientname/config/
Adapt to your preferred target, cloud sync, restic, tarballs, anything works because all state is files.
Roadmap
Where the project is now, and where it's going.
v1.0:Production release
Frontend, admin, full image manager, web installer, Ed25519 licence verification. Around 5,750 lines of hand-written code, 250 KB on disk.
v1.0.x:Patch releases
Bug reports and security issues from early adopters. No new features, just fixes. Format stays compatible with v1.0.0.
v1.1+:Possible additions
Based on real-adopter feedback. On the maybe-list: optional product collections (cross-category groupings), homepage block layouts, multi-language support via per-locale JSON files. No commitment.
Forward-compatible 1.x
An installation set up under format 1.0 should remain readable by all 1.x admin versions without manual migration. Adding fields is a minor bump; renaming or removing requires a major version and a migration path.
Shaped by real adopters
v1.1 priorities will come from real client deployments, not a wish-list. Bug reports and feature suggestions are welcome via GitHub Issues. The "Possible additions" list is a starting point, not a promise.
Pairs with Nano CMS
Nano Cart shares a design philosophy and a licence keypair with Nano CMS. Same flat-file storage, same removable admin pattern, same licence model. Run one or both on the same site without conflict.
Explicitly not planned: product variants (size, colour), quantity selectors, multi-item shopping cart, inventory tracking, search, filtering, pagination, tax engines, shipping rules, subscriptions, plugin system, theme system, comments. Feature requests for these will be politely declined. The small surface area is the product.
Try Nano Cart
v1.0.0 is shipped and live. Download from GitHub, deploy to a client site in under 10 minutes via the web installer, and replace WooCommerce-style overkill on small fixed-catalogue shops.
View on GitHub Get in Touch