=== TitanCart Lite ===
Contributors: titancart
Tags: ecommerce, shop, store, cart, products
Requires at least: 6.0
Tested up to: 7.1
Requires PHP: 8.0
Stable tag: 0.2.16
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

A self-hosted eCommerce engine for WordPress. Own tables, own REST API, own admin. No extra plugins. No page-builder bloat.

== Description ==

TitanCart is a complete storefront in one plugin: catalog, cart, checkout, orders, customers, shipping, tax and reporting. It runs on its own database tables and its own REST API rather than bending WordPress posts and meta into a shopping cart, which is why it stays fast as a catalog grows.

No license key is required. TitanCart Lite is free and GPL, and it never contacts a remote server.

= What you get =

* **Products** — simple and variable products, categories, product filters, attributes, image galleries, digital downloads.
* **Cart and checkout** — a real cart session, guest checkout, coupon codes, order notes.
* **Payments** — Stripe, plus cash on delivery, bank transfer and cheque.
* **Shipping** — flat rate, free shipping, and table-based rates with zones and conditions.
* **Tax** — full tax classes, zones and rate rules. Not a stripped-down version; tax is a legal requirement, not an upsell.
* **Orders** — order management, statuses, invoices, fulfilment and shipment tracking.
* **Customers** — accounts, address book, order history, customer groups.
* **Reviews** — product reviews with moderation.
* **Wishlists**, **sitemap**, **SEO** output (meta tags, canonical URLs, Open Graph, JSON-LD product schema), **GDPR** tools and **age verification**.
* **Import and export** — CSV import and export, including a WooCommerce migration tool.
* **Prism** — a free companion storefront theme built for TitanCart, available as a free download from the TitanCart marketplace at market.titancart.io.

= Built to be portable =

TitanCart's cart, checkout, order and pricing logic have no WordPress function calls inside them. WordPress is a thin hosting layer over a self-contained engine. That is an architectural choice, not marketing: it is what keeps the query count low and the upgrade path open.

= Privacy and external services =

TitanCart Lite makes **no outbound connections of any kind** on its own. It contains no license check, no update checker, no analytics, no telemetry, and no remote code installer. Updates arrive through WordPress.org like any other plugin.

A small number of features contact a third party only after **you** configure them, using credentials you supply. Each is documented in the External services section below. None is enabled by default.

= Source code =

The admin interface, `admin/build/titancart-admin.js`, is hand-written JavaScript and **is itself the source code**: there is no build step, no transpiler, no JSX, no bundler and no minification anywhere in this plugin. The directory name is historical. The same is true of every other JavaScript and CSS file shipped — what you read in the ZIP is exactly what the developer wrote and maintains.

== Installation ==

1. In your WordPress admin, go to Plugins → Add New and search for "TitanCart".
2. Click **Install Now**, then **Activate**.
3. Follow the setup prompt, or go to **TitanCart → Settings** to configure your store, currency, shipping and tax.
4. Optionally install the free **Prism** storefront theme, available from the TitanCart marketplace at market.titancart.io.

No account, key or sign-up is required.

== External services ==

TitanCart Lite connects to the following external services. Every connection is **off by default** and happens only after the site owner configures the feature with their own credentials.

**Stripe (payment processing)**

* What it is: card payment processing by Stripe, Inc.
* What it is used for: charging customers at checkout when the store owner has created a Stripe payment method with their own API keys.
* What data is sent, and when: when a Stripe method is enabled, the checkout page loads Stripe's `Stripe.js` from `js.stripe.com` (a Stripe requirement for PCI compliance) and card details entered by the customer go **directly from the customer's browser to Stripe** — they never touch the store's server. The server then exchanges payment intents/confirmations with Stripe's API (order amount, currency, and the payment reference).
* Terms and privacy: [Stripe Services Agreement](https://stripe.com/legal/ssa), [Stripe Privacy Policy](https://stripe.com/privacy).

**Google reCAPTCHA (spam and abuse protection)**

* What it is: Google's reCAPTCHA v2/v3 service.
* What it is used for: protecting the login, registration, checkout, review and contact surfaces from bots — only if the store owner enables the reCAPTCHA feature and supplies their own site key and secret.
* What data is sent, and when: on pages with a protected form, Google's `api.js` loads from `www.google.com` in the visitor's browser (Google's script collects the signals it uses for its bot score — see its privacy policy); on submit, the server sends the response token, the site secret and the visitor's IP address to Google's `siteverify` endpoint to obtain the verdict.
* Terms and privacy: [Google Terms of Service](https://policies.google.com/terms), [Google Privacy Policy](https://policies.google.com/privacy).

**Google Maps Places (address autocomplete)**

* What it is: the Google Maps JavaScript API with the Places library.
* What it is used for: suggesting street addresses as a customer types on the checkout and account address forms — only if the store owner turns on **Address autocomplete** in checkout settings and supplies their own Google Maps API key. Off by default; nothing loads without the key.
* What data is sent, and when: on the checkout and account pages only, the visitor's browser loads `maps.googleapis.com/maps/api/js` (keyed with the owner's API key) and sends the characters typed into the address field to Google to receive suggestions. The store's server never contacts Google for this feature.
* Terms and privacy: [Google Maps Platform Terms](https://cloud.google.com/maps-platform/terms), [Google Privacy Policy](https://policies.google.com/privacy).

**YouTube and Vimeo (product video embeds)**

* What it is: the public video players of YouTube (Google) and Vimeo.
* What it is used for: showing a product video on the product page when the store owner has pasted a YouTube or Vimeo link into that product's video field. No video is embedded unless the owner adds one.
* What data is sent, and when: the product page renders a thumbnail from `img.youtube.com` and, when the visitor clicks play, an embedded player from `www.youtube.com` or `player.vimeo.com` in the visitor's browser; those providers receive the visitor's request as with any embedded video. In the admin product editor, a thumbnail preview is fetched from `img.youtube.com` for the link the owner entered. Videos hosted on the store's own server are played directly and involve no third party.
* Terms and privacy: [YouTube Terms of Service](https://www.youtube.com/t/terms), [Google Privacy Policy](https://policies.google.com/privacy), [Vimeo Terms of Service](https://vimeo.com/terms), [Vimeo Privacy Policy](https://vimeo.com/privacy).

**Remote images during CSV import**

* What it is: standard HTTP downloads performed by WordPress itself.
* What it is used for: when the store owner runs a product CSV import whose rows contain image URLs, WordPress downloads those images into the media library.
* What data is sent, and when: an HTTP GET to each image URL **the owner provided in their own file**, at import time only.

The product page's optional share buttons are ordinary links to Facebook, X, Pinterest and LinkedIn share pages; nothing is loaded from those sites and no request is made unless the visitor clicks one.

No other external connections exist in TitanCart Lite. Payment gateways beyond Stripe (PayPal, Square, Authorize.net), live carrier shipping rates (USPS, FedEx), social sign-in (Google, Facebook, Apple) and the TitanCart extensions catalog are features of TitanCart Pro, are **not present in this plugin's code**, and are documented in the Pro edition's own materials.

== Frequently Asked Questions ==

= Do I need a license key? =

No. TitanCart Lite is free, GPL-licensed, and fully functional without a key. It never asks for one and never phones home.

= Will it work alongside WooCommerce? =

TitanCart does not use, extend or depend on WooCommerce, and it stores nothing in WooCommerce's tables. Running both at once is not recommended simply because two storefronts on one site confuses customers, not because they conflict technically. There is a built-in WooCommerce importer to migrate your catalog across.

= Does it slow my site down? =

TitanCart uses its own indexed tables instead of `wp_postmeta`, so catalog queries do not scale with your meta table. The admin is a single-page app that loads once and then talks to a REST API.

= What is the difference between Lite and Pro? =

Lite is a complete, working store: products, cart, checkout, Stripe, shipping, tax, orders, customers, reviews, import/export and SEO. Pro adds promotions and discount rules, loyalty rewards, gift cards, product bundles and options, email campaigns, returns (RMA), advanced reporting, additional payment gateways, live carrier shipping rates, the external REST API, and the first-party extension suite.

Everything in Lite stays in Lite. Pro is additional capability, never a paywall in front of something that used to be free.

= Where is my data stored? =

In your own database, in tables prefixed `wp_tc_`. Nothing is stored off-site. Uninstalling is a clean removal.

== Screenshots ==

1. The storefront, running the free Prism theme (available from the TitanCart marketplace).
2. Product catalog in the TitanCart admin.
3. The product editor.
4. Order management and fulfilment.
5. Checkout.
6. Store settings.

== Changelog ==

= 0.2.16 =
* Admin: fixed an intermittent "Page Error" (insertBefore NotFoundError) in the Payment Gateways editor and other admin screens. Root cause: WordPress's emoji replacement script rewrites emoji characters inside the admin app's text into images behind React's back. The emoji script is no longer loaded on TitanCart admin screens (the same approach WordPress core uses for the block editor). Front-end and other admin pages are unaffected.
* Invoice and packing-slip print documents now load their styles as static stylesheets through the core styles API (wp_register_style / wp_add_inline_style / wp_print_styles) instead of embedded style blocks.
* Every intentionally public REST route now declares the literal __return_true permission callback with an inline justification comment at the registration site (anonymous storefront reads, guest cart/checkout session operations, token-as-credential links, moderated guest write-ins, signature-verified gateway webhooks/returns).
* Import: the CSV column help text for images no longer uses URL-shaped example strings.
* Fresh installs: activation now stamps the schema/migration state directly instead of replaying 63 historical migrations on first load. Fixes noisy database errors, a page-creation error before WordPress's rewrite system is ready, and a translations-loaded-too-early notice on brand-new installs (found testing on WordPress Playground). Existing sites are unaffected — migrations remain the upgrade path.
* Fresh installs: default fulfillment/gift-card statuses, reward-point earning rules, and return reasons are now seeded at activation; a stale email-template seeder that silently failed on every fresh install was removed (templates seed on first access, as designed).
* The reviewer/architecture notes document now ships in the package at docs/WPORG-REVIEWER-NOTES.md.
* WooCommerce import: variable products now import their variation values from each variation's own attribute data, so stores whose global attribute terms are missing or incomplete (some CSV-imported catalogs) no longer produce unlinked variations with an empty option selector. Attribute names fall back to a readable label ("Color") instead of the raw taxonomy slug, re-running the import repairs previously broken imports in place, and imported variable products now display as a single product card on the storefront by default (each variation keeps its own product code, price and stock). The single card is titled with the original product's name ("Hoodie") rather than a variation's name ("Hoodie — Blue / Yes"); re-running the import fills this in for groups created by an earlier version, without overwriting a name you have set yourself.
* Attribute choices and assigned attribute values now list correctly on SQLite-backed sites (WordPress Playground, WP-CLI/Plugin Check SQLite environments): the shared ordering clause used MySQL-only syntax (IF(), a MySQL collation name) that SQLite rejects, which emptied choice lists across the product editor, storefront filters and product-page selectors on those environments. The clause now uses standard SQL.

= 0.2.15 =
* Attributes: each attribute now has a "Sort Choices" setting — Manual order (default, unchanged for existing stores) or Alphabetical A–Z. The chosen order applies everywhere choices are listed: product editor, variation generator, storefront filters, product-page selectors and product-card swatches. Alphabetical sorting is collation-aware and case-insensitive, and never rewrites your manual order, so switching back restores it.
* Attributes: one-click "Sort A–Z now" on the Choices tab rewrites the manual order alphabetically.
* Attributes: duplicate choice names are flagged in the editor.
* Attributes: deleting a duplicate choice now moves its product assignments, variation combinations and group combinations to the copy you keep (and carries its swatch colour over if the survivor has none). Deleting a choice with no same-name sibling cleans up its orphaned assignments instead of leaving dangling references.
* Attributes: swatch hex colors are accepted with or without the leading "#" and stored in a canonical form.
* Admin: payment-gateway editor resilience improvement (self-healing render boundary).

= 0.2.14 =
* Review-feedback release (round 2). Every global function, hook, option, transient, constant, AJAX action, cron hook, nonce, script handle and localized JavaScript object now carries the `titancart_` / `TITANCART_` prefix (database table names keep their `wp_tc_` prefix — no data migration). Inline scripts and styles are emitted through `wp_add_inline_script()` / `wp_add_inline_style()` with no output buffering. All public REST routes use a named permission callback and the per-order downloads route verifies ownership in its permission callback. Tree-wide input sanitization and output escaping pass. Migration DDL and IN-list queries converted to prepared placeholder patterns. Site Backup (dump/restore) is no longer part of TitanCart Lite. CSV import resolves local images from the WordPress uploads directory. External services section expanded (Google Maps address autocomplete, YouTube/Vimeo video embeds).

= 0.2.13 =
* Review-feedback release: all inline scripts and styles converted to the WordPress enqueue API (payment SDKs are now conditional wp_enqueue_script calls from their provider origins); tree-wide input-sanitization pass (validated client-IP capture, sanitized user-agent/nonce/token reads); REST permission audit — the per-order downloads route now requires login in its permission_callback and the PayPal capture endpoint is bound to the order's secret key; a dedicated External services readme section; upload path now derives solely from wp_upload_dir(); REST URLs built with rest_url(); admin menu moved below Plugins.

= 0.2.12 =
* Internationalization: translator comments added to every translatable string with placeholders, numbered placeholders throughout, and full gettext-extractor compatibility.

= 0.2.11 =
* Security hardening: output escaping tightened across storefront templates and admin notices; JSON-LD structured data is now breakout-proof encoded.
* Code quality: database query annotations completed for coding-standards compliance.

= 0.2.10 =
* Security and standards hardening pass: safer file operations, safe redirects, timezone-correct date handling, locally bundled icon fonts (no CDN), and a gated logging seam.

= 0.2.9 =
* Initial WordPress.org release.

== Upgrade Notice ==

= 0.2.16 =
Fixes the intermittent admin "Page Error" crash. Safe upgrade — no data changes.

= 0.2.15 =
Attribute choice sorting (Manual / A–Z), duplicate-choice warnings and "#"-optional hex colors. Safe upgrade — default behaviour unchanged.

= 0.2.14 =
Prefix and standards release from plugin review feedback. Site Backup is removed from Lite. Recommended for all users.

= 0.2.13 =
Standards and security hardening from plugin review feedback. Recommended for all users.

= 0.2.12 =
Internationalization polish release. Recommended for all users.

= 0.2.11 =
Security hardening release. Recommended for all users.
