Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ The API accepts a source image up to 10 MB and 40 million decoded pixels. Extrac

ColorCraft has no accounts or cloud synchronization. Source-image bytes and unsaved changes remain session-only. Browser history stores the active view and Review tab, not palette data. Export generation runs in the browser.

ColorCraft JSON import is also browser-only. It accepts ColorCraft portable
schema versions 1 and 2, validates the complete file before changing the
workspace, and leaves an imported palette unsaved until **Save palette** is
selected.
ColorCraft JSON import is also browser-only. New exports use portable schema
version 3 with document-local color keys. Imports accept versions 1, 2, and 3,
validate the complete file before changing the workspace, and leave an imported
palette unsaved until **Save palette** is selected. CSS and Tailwind exports
include semantic role tokens for assigned colors.

![Named and reordered ColorCraft palette](./docs/assets/screenshots/palette-organization-light.png)

Expand Down
11 changes: 7 additions & 4 deletions docs/api-contracts.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ request fields are rejected.
### Portable palette boundary

ColorCraft JSON import and export are browser-side portable-format contracts,
not backend API endpoints. Portable schema version 2 uses
not backend API endpoints. Portable schema version 3 uses
`format: "colorcraft-palette"`, supports optional Unicode color names and exact
order, and excludes internal workspace IDs. The importer also accepts portable
schema version 1. Backend endpoint request and response schemas are unchanged;
analysis and suggestion requests still contain only HEX, RGB, and HSL.
order, assigns deterministic document-local keys, and excludes internal
workspace IDs. Role assignments reference the portable keys. The importer also
accepts portable schema versions 1 and 2 and maps their HEX roles to the first
matching color. Backend endpoint request and response schemas are unchanged;
analysis and suggestion requests still contain only HEX, RGB, and HSL, never
IDs, names, portable keys, or roles.

The default base URL is `http://127.0.0.1:4100`. FastAPI provides interactive
OpenAPI documentation at `/docs` and the OpenAPI document at `/openapi.json`.
Expand Down
33 changes: 20 additions & 13 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,20 +99,23 @@ geometric suggestion approaches for each base color. `commonAssociations` and
the palette automatically. The user must select **Add**.

The frontend gives each active palette color a stable internal ID and optional
name. Selection and reordering use the ID; backend requests are canonicalized
to HEX, RGB, and HSL only. The frontend fingerprints the current palette. A palette color change
invalidates the displayed suggestion results.
name. Selection, reordering, and role assignments use the ID. Backend requests
are canonicalized to HEX, RGB, and HSL only. The frontend fingerprints the
current palette. A palette color change invalidates the displayed suggestion
results.

## Export flow

The frontend generates every export without an API request:

- CSS custom properties
- Portable ColorCraft JSON schema version 2
- Portable ColorCraft JSON schema version 3
- Tailwind theme colors
- SVG swatch sheet

CSS and Tailwind comments replace line breaks and the `*/` sequence in the
CSS emits base `--color-*` values and assigned `--role-*` aliases. Tailwind
emits base keys and assigned `role-*` semantic keys. SVG annotates each row with
its assigned roles. Comments replace line breaks and the `*/` sequence in the
palette name. SVG output escapes `&`, `<`, `>`, `"`, and `'`. Each swatch label
uses black or white according to the higher measured contrast ratio. Download
uses an object URL and revokes the URL after the browser starts the download.
Expand All @@ -124,17 +127,21 @@ Export does not create or update a saved palette record.
The current source-image preview, analysis, suggestions, and unsaved changes
remain in memory. The URL records the active application view and Review tab.

Saved palette records use schema version 2 in the browser's `colorcraft`
Saved palette records use schema version 3 in the browser's `colorcraft`
IndexedDB database. Saved colors contain internal IDs and optional names. The
frontend validates each record before use. It migrates schema-version-1 and
legacy version-0 or unversioned records with deterministic color IDs. It rejects
malformed records and unknown future schema versions.
frontend validates each record before use. Version-3 roles reference those IDs.
It migrates schema-version-2 HEX roles and schema-version-1, version-0, or
unversioned records. A legacy role maps to the first matching color in palette
order; missing matches are pruned. It rejects malformed records and unknown
future schema versions.

The internal saved schema and portable JSON schema are separate contracts.
Portable JSON version 2 includes `format: "colorcraft-palette"`, optional names,
ordered colors, extraction metadata, and HEX-based roles, but excludes internal
IDs. Import also accepts the prior portable JSON version 1. Parsing and
validation run in the browser before workspace state changes.
Portable JSON version 3 includes `format: "colorcraft-palette"`, optional names,
ordered colors, extraction metadata, and deterministic document-local color
keys. Role assignments reference those keys and internal IDs remain excluded.
Import also accepts portable versions 1 and 2, whose HEX roles map to the first
matching color. Parsing and validation run in the browser before workspace
state changes.

Source-image bytes are not part of a saved palette record. See
[Persistence and privacy](./persistence-and-privacy.md).
Expand Down
10 changes: 8 additions & 2 deletions docs/color-analysis.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,14 @@ color changes.

## Export accuracy and escaping

JSON export uses `schemaVersion: 1`. JSON includes ordered colors, normalized
color values, optional population, color-role metadata, and role assignments.
JSON export uses portable `schemaVersion: 3`. JSON includes deterministic
document-local color keys, ordered normalized colors, optional extraction
metadata and names, per-color role metadata, and key-based role assignments.
Internal workspace IDs are excluded.

CSS emits base palette properties plus assigned `--role-*` aliases. Tailwind
emits base palette keys plus assigned `role-*` semantic keys. SVG rows annotate
assigned roles.

CSS and Tailwind output sanitize palette names used in comments. SVG output
escapes XML-sensitive characters. Each SVG swatch compares measured contrast
Expand Down
23 changes: 13 additions & 10 deletions docs/persistence-and-privacy.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,31 @@ The frontend uses:
## Saved palette records

The `colorcraft` IndexedDB database contains the `palettes` object store. A
schema-version-2 record contains:
schema-version-3 record contains:

- Record ID and palette name
- Created and updated timestamps
- Manual or image source type
- Optional source filename
- 1–10 ordered normalized palette colors with stable internal IDs and optional names
- Optional population and `pixelCount`
- Color-role assignments
- Color-role assignments that reference stable internal color IDs

The frontend validates each record with Zod. It can migrate a schema-version-1,
version-0, or unversioned record to the current shape.
The frontend validates each record with Zod. It can migrate a schema-version-2,
schema-version-1, version-0, or unversioned record to the current shape.
Legacy colors receive deterministic IDs, so repeatedly opening a migrated
record does not create a false modified state. Listing the Library does not
rewrite records. The next save writes schema version 2.
rewrite records. Version-2 and older HEX roles map to the first matching color
in palette order; missing matches are discarded. The next save writes schema
version 3.
The frontend ignores malformed records and unknown future schema versions.

Portable ColorCraft JSON is not an IndexedDB record. Portable schema version 2
uses `format: "colorcraft-palette"` and excludes internal IDs. Import supports
portable versions 1 and 2, reads at most 1 MB, validates the complete file
locally, and does not send its contents to the API. An imported palette remains
session-only until the user selects **Save palette**.
Portable ColorCraft JSON is not an IndexedDB record. Portable schema version 3
uses `format: "colorcraft-palette"` and deterministic document-local keys while
excluding internal IDs. Import supports portable versions 1, 2, and 3, reads at
most 1 MB, validates the complete file locally, and does not send its contents
to the API. An imported palette remains session-only until the user selects
**Save palette**.

## Source images

Expand Down
7 changes: 4 additions & 3 deletions docs/screenshot-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ cd frontend
corepack pnpm@9.15.9 review:screenshots
```

It creates 16 fixture-driven PNGs under `.tmp/ui-review`: empty Create in both themes with the JSON import affordance, extraction progress, image and named/reordered manual palettes, selected and modified states, four Review surfaces, Export, Library, two mobile surfaces, and an API error. Network-dependent extraction is mocked; analysis uses fixed palette data.
It creates 16 fixture-driven PNGs under `.tmp/ui-review`: empty Create in both themes with the JSON import affordance, extraction progress, image and named/reordered manual palettes, selected and modified states, four Review surfaces, semantic-token Export, Library, two mobile surfaces, and an API error. The Contrast fixture assigns distinct roles to named duplicate-HEX colors. Network-dependent extraction is mocked; analysis uses fixed palette data.

`.tmp` is intentionally ignored. Review those files locally for clipping, hierarchy, contrast, focus, error placement, and responsive behavior. Temporary test artifacts must not be linked from documentation.

When a screenshot is representative and stable, copy only that file to `docs/assets/screenshots`, give it a semantic name, and reference it from documentation. Curated images are reviewable product documentation; the complete temporary set is disposable diagnostic output.

The current curated set shows light Create with JSON import, a named and
reordered palette, dark Review Overview, dark role-based Contrast, dark
Suggestions, dark Library, and mobile Create. The Review images document the
reordered palette, dark Review Overview, dark role-based Contrast, semantic
role export, dark Suggestions, dark Library, and mobile Create. The Review
images document the
metadata-derived network status, three-way temperature evidence, typed contrast
checks, and qualified suggestion language. Regenerate the set only when a
deliberate interface change makes an existing image inaccurate.
6 changes: 4 additions & 2 deletions docs/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,15 @@ gate.

## Test scope

- Persistence tests cover validation, migration, update identity, sorting,
- Persistence tests cover version-3 validation, legacy HEX-role migration,
duplicate-role remapping, update identity, sorting,
rename, duplicate, and delete.
- Frontend tests cover navigation, palette state, stale analysis, Save states,
Review, Export, and API contract validation.
- Backend tests cover upload defenses, extraction, relationship analysis,
suggestions, contrast, metadata, readiness, configuration, and launcher
supervision.
- Browser tests cover create, save, analyze, role assignment, export, reopen,
- Browser tests cover create, save, analyze, stable duplicate-color role
assignment, semantic export, portable round trips, reopen,
delete, and representative accessibility states.
- Documentation tests verify local Markdown links and curated screenshot names.
8 changes: 5 additions & 3 deletions docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,11 @@ unsupported schema or format, contains unknown fields, or has inconsistent
color or role data.

**Recovery:** Export the palette again from ColorCraft when possible. Confirm
that the file is a single ColorCraft palette using portable schema version 1 or
2. ColorCraft validates the complete file and does not partially import invalid
colors or roles.
that the file is a single ColorCraft palette using portable schema version 1,
2, or 3. Version-3 role references must point to unique valid portable color
keys. ColorCraft validates the complete file and does not partially import
invalid colors or roles. In version 1 or 2, a role associated with a duplicate
HEX value maps to the first matching color in palette order.

## Browser history does not restore a palette

Expand Down
23 changes: 16 additions & 7 deletions docs/user-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ The palette can contain at most 10 colors.
3. If the current palette has unsaved or modified work, confirm whether to
discard it.

Import runs entirely in the browser. ColorCraft accepts portable schema version
1 and version 2 files, validates the whole file before changing the workspace,
Import runs entirely in the browser. ColorCraft accepts portable schema
versions 1, 2, and 3, validates the whole file before changing the workspace,
and never imports arbitrary JSON. The imported palette retains its name, color
order, optional color names, extraction metadata when present, and valid role
assignments. It has no source image and remains **Unsaved** until you select
Expand Down Expand Up @@ -155,6 +155,11 @@ The current color-role labels are:
- **Border**
- **Focus indicator**

Roles are bound to the selected palette color, not its HEX value. Renaming,
reordering, or editing that color preserves the assignment. Duplicate HEX
colors remain separate choices. Removing a color clears only roles assigned to
that color.

Text checks show AA and AAA text thresholds. **Border against surface** is a
non-text component check with a 3:1 threshold. Focus-indicator checks use 3:1
for the selected adjacent-color pair.
Expand Down Expand Up @@ -197,17 +202,21 @@ stated in percentage points.

Named colors produce safe ASCII keys in CSS and Tailwind output and visible
labels in SVG. Unnamed colors keep the `palette-1`, `palette-2` numeric pattern.
ColorCraft JSON schema version 2 preserves Unicode names, exact order,
extraction metadata, and roles. It does not contain internal workspace IDs.
ColorCraft JSON schema version 3 preserves Unicode names, exact order,
extraction metadata, and unambiguous role ownership. Each color receives a
document-local key such as `color-1`; the file does not contain internal
workspace IDs.
4. Select **Copy** or **Download**.

**Copy** places the generated text on the clipboard. **Download** creates an
exported file through the browser. Export does not create or update a saved
palette record.

Role assignments currently reference HEX values. Duplicate colors with the same
HEX value therefore share a role association even when their internal IDs or
names differ.
CSS output adds assigned `--role-*` aliases that reference base `--color-*`
tokens. Tailwind output adds assigned `role-*` keys, and SVG rows identify their
assigned roles. Imported version-1 and version-2 files still use HEX role
references. When duplicate HEX values make those older files ambiguous,
ColorCraft maps the role to the first matching color in palette order.

For SVG output, ColorCraft measures each swatch against black and white. It uses
the text color with the higher contrast ratio.
Expand Down
4 changes: 3 additions & 1 deletion docs/writing-style.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ contents, clipboard contents, or unrelated palette data in user-facing errors.
| non-text component contrast check | A contrast-role check that applies the 3:1 color threshold to a component boundary or state. | Do not claim complete component accessibility. |
| focus-indicator color contrast check | A 3:1 check for one focus-indicator and adjacent-color pair. | Size, area, thickness, visibility, and focused-versus-unfocused appearance remain outside the calculation. |
| color role | A semantic interface role assigned to a palette color. | Current labels are Page background, Surface, Primary text, Secondary text, Primary action, Action text, Border, and Focus indicator. |
| role assignment | The association between a palette color and a color role. | Do not use for an unassigned palette color. |
| role assignment | The association between a stable palette color identity and a color role. | Do not describe an active role as a HEX association or expose the internal ID. |
| contrast-role check | A typed contrast test between two meaningful assigned color roles. | Identify whether the check is text, non-text component, or focus-indicator color contrast. |
| all-pairs text contrast matrix | The advanced matrix that applies text thresholds to every palette color pair. | Keep separate from typed contrast-role checks. |
| suggestion approach | One method that proposes colors from a base color. | Current API approaches include complementary, triadic, analogous, split-complementary, tetradic, rectangular, monochromatic, double-complementary, and shades and tints. |
Expand All @@ -205,6 +205,8 @@ contents, clipboard contents, or unrelated palette data in user-facing errors.
| export format | One supported representation of the current palette. | Current labels are CSS custom properties, JSON, Tailwind theme colors, and SVG swatch sheet. |
| exported file | A file that the browser creates from the current palette. | Do not imply that ColorCraft stores the file. |
| ColorCraft JSON | The portable, single-palette JSON format that ColorCraft exports and imports in the browser. | Distinguish its schema version from the IndexedDB saved-palette schema and backend API schemas. |
| portable color key | A deterministic document-local color reference such as `color-1` in ColorCraft JSON version 3. | Do not call it an internal workspace ID. |
| semantic role token | An assigned `--role-*` CSS alias or `role-*` Tailwind key generated from a color role. | Keep it separate from the base palette token. |
| imported palette | A validated ColorCraft JSON palette activated in the current session. | State that it remains unsaved until **Save palette** is selected. |
| copy | Place generated export text on the system clipboard. | Do not use as a synonym for export or download. |
| download | Save generated export data as a local file through the browser. | Do not use as a synonym for copy. |
Expand Down
Loading
Loading