Penguin CangCang

Inspiration

Penguin CangCang, or 胖滚儿藏藏, began with two things that are important to me: sewing and my cat.

胖滚儿 is a black-and-white cow cat whose coloring resembles a little penguin. The project name combines that visual association with the idea of carefully storing and discovering the materials hidden throughout a maker’s home.

The practical problem came from my own growing collection of fabrics, lace, elastic, ribbons, thread, buttons, hardware, tools, and unfinished sewing projects. Information about these materials was scattered across storage boxes, photographs, purchase records, spreadsheets, labels, and memory.

Even after organizing the physical objects, I still struggled to answer simple questions:

  • Do I already own a suitable material?
  • How much is actually left?
  • Where exactly is it stored?
  • Is it reserved for another project?
  • Did two similar-looking materials come from different purchases?
  • What happened to the remaining fabric after part of it was cut?
  • Am I about to buy something I already own?

Generic inventory applications usually represent an item as a name and a quantity. Sewing supplies are more complicated. A single fabric style can have several purchase batches, and each batch can be divided into multiple remnants stored in different places. Thread can move from a large spool to smaller bobbins. Buttons may initially be counted approximately. Materials may be reserved, consumed, released, split, merged, converted, or corrected as projects progress.

I created Penguin CangCang to model those real physical relationships instead of forcing them into a flat spreadsheet.

What It Does

Penguin CangCang is a privacy-first, local-first inventory and project-planning system for home sewists and makers.

Its central data model separates three concepts:

Item Style
└── Purchase Batch
    └── Physical Stock Unit

For example, “black silk crepe” is an item style. Fabric purchased from two shops at different times becomes two purchase batches. Each remaining piece becomes a separate physical stock unit with its own quantity, dimensions, condition, photograph, and storage location.

This structure preserves shared product information without losing the history or identity of individual physical pieces.

The planned product connects:

  • a photo-driven material library;
  • hierarchical storage locations;
  • quantities, availability, and reservations;
  • immutable inventory events;
  • sewing projects and material boards;
  • shortages and purchase lists;
  • inventory audits and discrepancy handling;
  • import, export, backup, and recovery;
  • offline use and secure cross-device synchronization.

The basic availability relationship is:

[

\text{available quantity}

\text{total quantity}

\text{reserved quantity} ]

For split, merge, and conversion operations, the system must preserve material instead of silently creating or losing it:

[

\sum Q_{\text{before}}

\sum Q_{\text{after}} ]

These rules are especially important when fabric is cut into remnants or thread is transferred from a large spool to smaller bobbins.

How I Built It

I designed Penguin CangCang as a TypeScript monorepo, with separate applications and reusable packages for the web client, API, background processing, shared types, domain logic, database access, synchronization, interface components, and import/export workflows.

The target deployment model uses an owner-controlled Windows computer as the home server. Other devices—including an iPhone, Mac, and Windows browsers—connect securely over HTTPS on the same local network.

The architecture is designed around:

  • React and Vite for the web application;
  • Fastify for the API;
  • PostgreSQL for authoritative structured data;
  • Drizzle ORM and explicit SQL migrations;
  • a background worker for media processing;
  • IndexedDB and an outbox for future offline operations;
  • Docker Compose for local deployment;
  • Caddy for local HTTPS;
  • Vitest, TypeScript, ESLint, and build gates for verification.

The current working implementation focuses on the system foundation. It includes:

  • the TypeScript monorepo structure;
  • shared domain contracts;
  • PostgreSQL migration infrastructure;
  • workspace and membership foundations;
  • role-aware access foundations;
  • a category domain with hierarchical relationships;
  • lifecycle states and category merging;
  • stable identifiers;
  • database-enforced invariants;
  • automated type-checking, linting, tests, and build verification.

I used GPT-5.6 as a product-design, modeling, and review partner. It helped translate an unstructured physical storage problem into explicit domain concepts, database invariants, edge cases, and testable engineering contracts.

I used Codex to inspect the real penguin-cangcang repository, implement narrowly scoped changes, run migrations and tests, and verify that the implementation matched the agreed contracts.

Rather than asking one AI system to generate the entire application at once, I separated the work into planning, implementation, independent audit, correction, and validation.

Challenges I Faced

Modeling physical reality

The first major challenge was realizing that “item plus quantity” was not enough.

The system must distinguish a reusable material definition from its purchase history and from the physical pieces that currently exist. It must also represent:

  • continuous materials measured by length or area;
  • integer-counted supplies;
  • indivisible tools;
  • approximate quantities;
  • partial spools;
  • fabric remnants;
  • work-in-progress components.

The three-level model—item style, purchase batch, and physical stock unit—became the foundation for handling these differences.

Protecting inventory history

A current quantity does not explain how the system arrived there.

Directly overwriting a number would make it difficult to understand consumption, replenishment, reservations, reversals, transfers, and audit discrepancies. Important changes therefore need to be represented as explicit inventory events.

Planned operations include:

  • replenishment;
  • reservation;
  • release;
  • consumption;
  • splitting;
  • merging;
  • conversion;
  • calibration;
  • reversal.

These operations must be transactional, idempotent where necessary, and auditable.

Enforcing multi-record database invariants

Some rules cannot be protected by a simple column constraint.

Examples include:

  • ensuring an active workspace retains an active administrator;
  • preventing cycles in a category hierarchy;
  • protecting immutable identifiers;
  • validating lifecycle transitions;
  • safely merging categories across related records.

Implementing these rules required careful use of PostgreSQL constraints, deferred triggers, deterministic locking, stable error contracts, migration rollback scripts, and transaction-level tests.

One independent audit found that an early category validation design could return the wrong constraint error when multiple deferred trigger events were queued in the same transaction. Normal tests passed, but the transaction-level behavior was still incorrect.

Fixing this taught me that passing unit tests is not the same as proving a database invariant.

Cross-platform reproducibility

The project is developed and verified across Windows and macOS.

Even migration checksum verification exposed differences caused by line endings and byte handling across operating systems. I had to define the checksum contract using validated UTF-8 content and normalized line endings, then confirm that the same repository state passed type checking, linting, tests, and builds on both platforms.

Offline synchronization without silent data loss

A future offline client should allow users to continue recording materials when the home server is unavailable. However, inventory cannot safely use a simple last-write-wins strategy.

The design therefore separates ordinary field edits from inventory commands.

Independent field changes may sometimes be merged, while conflicting edits to the same field require visible user review. Inventory operations use idempotency keys and are revalidated by the server so that network retries cannot accidentally consume or replenish stock twice.

What I Learned

The most important lesson was that a trustworthy inventory system is not mainly a catalog. It is a history of physical state transitions.

I also learned that local-first does not simply mean placing a database file on every device. A reliable local-first system still needs:

  • an authoritative transaction boundary;
  • explicit synchronization rules;
  • visible conflict handling;
  • durable backups;
  • recovery procedures;
  • predictable behavior when the host is unavailable.

The engineering process also taught me that AI-assisted development becomes more dependable when responsibilities are separated:

  1. define product boundaries and long-term invariants;
  2. translate them into testable contracts;
  3. give the implementation agent a narrow scope;
  4. audit the result independently;
  5. repair discovered gaps;
  6. rerun the complete verification gates.

GPT-5.6 was most useful for turning messy real-world requirements into structured models and identifying hidden edge cases.

Codex was most useful for working directly with the repository, applying focused changes, and running repeatable checks against the actual implementation.

Accomplishments I Am Proud Of

I am proud that Penguin CangCang does not treat privacy, reliability, migration safety, and offline behavior as features to add later.

The foundation already accounts for:

  • stable identifiers that are not silently reused;
  • reversible database migrations;
  • explicit lifecycle states;
  • transactional domain invariants;
  • cross-platform verification;
  • separation of structured data from photographs and attachments;
  • a future-proof item, batch, and stock-unit model;
  • a staged development process that does not present unfinished features as complete.

The project is still under active development, but its architecture is intended to support a real personal material library rather than only a demonstration dataset.

What Is Next

The next development stages will expand the foundation into:

  • hierarchical physical locations;
  • item styles and purchase batches;
  • physical stock units;
  • immutable inventory events;
  • photo-assisted material entry;
  • search and filtering;
  • offline synchronization;
  • sewing projects and material reservations;
  • shortage and purchase planning;
  • inventory audits;
  • import and export;
  • backup and recovery.

Later versions may add OCR, visual similarity search, automatic photo segmentation, natural-language material selection, and smarter project recommendations without sacrificing user ownership or inventory integrity.

My goal is for Penguin CangCang to become the bridge between a maker’s physical collection and the projects they want to create: private, searchable, dependable, and useful at the exact moment a material is needed.

Built With

Share this project:

Updates