AstroBaaS

Catalogue & product data

Product Management

Free — GPL coresize XLplanned, not built

Generated from docs/plan/core/product-management/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.

Core CMS feature for creating, editing, and deleting products. This is the foundational CRUD interface for the product catalog, including name, description, pricing, categories, images, and SEO metadata. Every merchant uses this; it is the primary way merchants build and maintain their storefront.

The problem

Merchants need to create, edit, and delete products; this is the core CMS function.

What it does

  • Create product: POST /products with name, description, price, images, categories, tags, status (draft/published)
  • Edit product: PUT /products/:id, partial updates allowed (only changed fields required)
  • Delete product: DELETE /products/:id (soft delete; product marked as deleted, not removed from storage)
  • Restore product: PUT /products/:id/restore — restore a soft-deleted product to ‘published’ or ‘draft’ state
  • Bulk edit: PATCH /products/bulk with product IDs and fields to update across multiple products (e.g., change category or price)
  • Search products: GET /products?name=shirt&category=tops&status=published, with pagination (100 per page default)
  • List products: GET /products, ordered by creation date (newest first), show summary view (id, name, price, status, featured, image)
  • Admin product form: WYSIWYG description editor, image uploader with reordering, category picker, tag input, price fields, SEO fields (slug, meta title, meta description)
  • Product preview: inline preview showing how product appears on storefront (name, image, price, short description, ‘Add to Cart’ button)
  • Revision history: track all changes (who, when, what changed) for audit purposes
  • Publish/unpublish: product status controls visibility (draft = not visible to storefront, published = visible)
  • Scheduling: schedule a product to go live at a future date (sale_starts_at, publish_scheduled_at)
  • Bulk import: CSV import with validation (name, sku, price, categories, etc.), preview import before committing
  • Bulk export: export products to CSV or JSON for backup or migration

What it deliberately does NOT do

Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.

  • Product recommendations or AI-driven upselling — that’s merchandising plugin territory
  • Multi-language product descriptions — i18n is handled separately (product.i18n field for overrides only)
  • Product versioning or rollback — audit log shows what changed, not revert capability
  • Advanced scheduling (publish to specific regions on different dates) — single global schedule only
  • Automatic product duplication from templates — manual creation only

Data model

Core Product model with fields: id (string, PK), name (string, max 255), slug (string, unique, max 128), sku (string, nullable, max 64), description (text), short_description (string, max 500), price_cents (integer), images (array of {src, alt}), categories (array of category IDs), tags (array of strings), featured (boolean), position (integer for ordering), status (‘draft’ | ‘published’), created_at, updated_at, deleted_at (nullable for soft delete), created_by (user_id), updated_by (user_id).

API

  • POST /products — create product {name, description, price_cents, status, …}
  • GET /products/:id — retrieve full product details
  • GET /products — list products with filters, pagination, search
  • PUT /products/:id — update product (partial)
  • DELETE /products/:id — soft delete product
  • PUT /products/:id/restore — restore soft-deleted product
  • PATCH /products/bulk — bulk update {ids: […], updates: {…}}
  • POST /products/import — bulk import from CSV, return preview and validation errors
  • GET /products/export — export products as CSV or JSON
  • GET /products/:id/revisions — audit log of changes

Every route added here must also appear in src/pages/openapi.json.ts — a test fails the build if it does not.

Admin

Product management admin page with: (1) Products list (sortable, filterable, searchable, with bulk action checkboxes), (2) Create button → form with name, description (WYSIWYG), price, categories, tags, images, status, SEO fields, (3) Product edit page (same form, shows existing data, save/preview/delete buttons), (4) Bulk edit modal (select fields to update across selected products), (5) Import page (CSV uploader, preview, commit button), (6) Export button (CSV/JSON), (7) Revision history panel (view changes over time).

The seam — why this is core

Core owns the entire product schema, CRUD API, and admin UI. This is foundational infrastructure. Paid tier could own advanced features: AI-powered product descriptions, product recommendations, multi-region scheduling, version control with rollback.

Core owns the interface + honest product editor; product CRUD is the foundational infrastructure.

Dependencies

  • user-auth (core; created_by, updated_by tracking)
  • audit-log (core; revision history)
  • category-management (core; products link to categories)
  • image-storage (core; product images)

Acceptance checks

Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.

  • POST /products with {name: ‘Blue Shirt’, price_cents: 1500, status: ‘draft’} creates product and returns {id: ‘prod_abc123’, status: ‘draft’, created_at: ‘2026-09-03T10:00:00Z’}.
  • PUT /products/prod_abc123 with {price_cents: 1200} updates price; description and other fields remain unchanged.
  • GET /products?status=draft&name=shirt returns only draft products with ‘shirt’ in name.
  • DELETE /products/prod_abc123 sets deleted_at timestamp; product no longer appears in GET /products (unpublished).
  • PUT /products/prod_abc123/restore sets deleted_at to null; product reappears as ‘draft’.
  • PATCH /products/bulk with {ids: [‘prod_abc123’, ‘prod_xyz789’], updates: {featured: true}} sets featured=true for both products.
  • POST /products/import with CSV file shows preview: ‘100 products to import, 5 validation errors (duplicate SKUs)’ before commit.
  • GET /products/:id/revisions returns [{updated_at: ’…’, updated_by: ‘user_123’, changes: {price_cents: [1500, 1200]}}] showing price change.

Risks

Bulk updates applied incorrectly can change prices or categories for hundreds of products. If deleted_at is not respected in storefront queries, deleted products appear on the shop. Import CSV with wrong column mappings can populate fields with garbage data. No version control means a merchant cannot undo an accidental bulk delete.

Commercial context

Suggested pricefree (core)
Rival anchorShopify: included; Magento: included

The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.


Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full catalogue and ../../AI-GUIDE.md for how to work on this repository.