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
2 changes: 1 addition & 1 deletion .github/labels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,4 @@

- name: 'size: XL'
color: 'FAEAEA'
description: 'Diff 500+ lines — consider splitting'
description: 'Diff 500+ lines — consider splitting'
51 changes: 34 additions & 17 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,52 +5,69 @@ All notable changes to Attyre will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Current Version [v2026.04.26] - 2026-04-26 *(automated fixes by Claude Code)*
## Current Version [v2026.05.11]

### Fixed (v2026.04.26)
### Fixed

- **Category validation error now visible**: `add-item` and `item-detail` forms were missing the `category-error` element, so the "Category is required" message was silently swallowed — error paragraph now rendered correctly under the category select.
- **Crop button re-usable after first crop**: After applying a crop in the add-item form, the replacement preview button had no event listener attached, making subsequent crops impossible — listener is now re-wired via a recursive helper after each crop.
- **localStorage quota errors surfaced**: `saveItems` was catching `QuotaExceededError` silently; it now re-throws so callers can alert the user when storage is full.
- **Mobile app shell invisible on older phones**: `.app-shell` used `height: 100dvh` with no fallback — `dvh` is unsupported on iOS < 16 and Chrome < 108, causing the shell to collapse to zero height and render nothing. Added `height: 100vh` fallback immediately before the `dvh` line.
- **Initial page never renders on slow mobile connections**: `app.js` registered a `DOMContentLoaded` listener unconditionally, but ES modules are fetched asynchronously — on real phones the event can fire before the module loads, leaving `#app` permanently empty. Now guards with a `document.readyState` check so `renderPage()` always runs.
- **PWA `start_url` mismatch on iOS**: `manifest.json` had `"start_url": "/"` while the app uses hash routing — launching from the iOS home screen landed on a bare static file. Changed to `"/index.html#/"`.

### Changed (v2026.04.26)
### Added

- **PWA manifest colours corrected**: `theme_color` was a leftover placeholder purple (`#6C63FF`) — updated to the app's actual gold (`#C9A96E`); `background_color` updated to match light-mode page background (`#F5F0E8`); placeholder screenshot SVGs updated to match; `start_url` corrected from `/index.html` to `/`.
- **Skip-to-content link**: Keyboard/switch-access users can now press Tab on any page to reveal a "Skip to main content" link that jumps focus directly to the `#app` region.
- **Global `:focus-visible` ring**: All interactive elements (buttons, links, item cards, calendar days) now show a visible gold focus outline when navigated by keyboard. Accessibility mode uses a thicker blue outline.
- **`prefers-reduced-motion` support**: All CSS transitions and animations are suppressed when the OS "Reduce Motion" setting is enabled.
- **Screen reader page announcements**: A hidden `aria-live` region announces the page title on every navigation and announces when accessibility mode is toggled on/off.
- **Wardrobe filter result announcements**: Screen readers are told how many items match the current filters (or "No items match your filters") whenever filters change.
- **Calendar date announcements**: Selecting a calendar day announces the date and whether an outfit is planned for that day.
- **Calendar keyboard navigation**: Calendar day cells now have `tabindex="0"` and respond to Enter/Space for selection, plus full ARIA grid semantics (`role="grid"`, `role="gridcell"`, `aria-selected`).
- **Item cards are focusable buttons**: Item cards changed from `<div>` to `<button>` — screen readers now announce them with the correct role and keyboard users get Enter/Space activation for free.
- **Outfit selector `aria-pressed` state**: When picking items for a calendar day, each card reflects its selected state via `aria-pressed` so screen readers can track selection without relying on visual-only border/background changes.
- **Form error linkage**: Name and category inputs in the add-item form are now connected to their inline error messages via `aria-describedby`.

### Technical Improvements (v2026.04.26)
### Changed

- **SRI hashes added to CDN scripts**: `integrity` + `crossorigin="anonymous"` attributes added to all three CDN tags (lz-string, Cropper.js JS and CSS) to guard against CDN compromise.
- **APP_VERSION CI regex tightened**: Deploy-preview workflow regex now enforces the strict `YYYY.MM.DD` format instead of accepting any sequence of digits and dots.
- **Label-sync workflow fixed**: Added `pip install pyyaml` step before the YAML parse step, which would otherwise fail with `ModuleNotFoundError` since `yaml` is not in Python's standard library.
- **LZString null check corrected**: `getItems` fallback now checks `=== null` instead of falsy, correctly handling the edge case where LZString returns an empty string.
- **Accessibility mode improvements**: Beyond the existing color swap, accessibility mode now also increases the base font size to 16 px, strengthens border contrast, and thickens nav icon strokes for better legibility.

---

## Prior Release [v2026.04.24] - 2026-04-24
## Prior Releases [v2026.04.24] - 2026-04-24

### Added (Current Version)
### Added

- **Responsive App Shell**: Added a full desktop sidebar + mobile topbar/bottom-nav navigation system for clearer routing and faster access to core pages.
- **New Stats Page**: Introduced a dedicated stats view (`#/stats`) with category/season/warmth breakdowns, usage insights, and most-worn/never-worn analysis.
- **Expanded Wardrobe Filtering**: Added weather-tag filter chips on wardrobe browsing in addition to text, category, and season filters.

### Changed (Current Version)
### Changed

- **Visual Redesign (v2)**: Reworked the global interface with a warm theme, updated typography, refreshed cards, buttons, alerts, and page layouts.
- **Home Experience**: Redesigned quick actions, outfit inspiration, saved outfit preview, and usage highlights for better at-a-glance insights.
- **Suggest Workflow**: Improved city input UX, loading/error states, weather card presentation, and ranked suggestion display.
- **Calendar Planning UX**: Rebuilt month navigation and date selection with richer day states (today/selected/has-outfit) and streamlined outfit assignment.
- **Component Refresh**: Updated item cards with SVG category icons and improved fallback rendering when images are unavailable.
- **PWA manifest colours corrected**: `theme_color` was a leftover placeholder purple (`#6C63FF`) — updated to the app's actual gold (`#C9A96E`); `background_color` updated to match light-mode page background (`#F5F0E8`); placeholder screenshot SVGs updated to match; `start_url` corrected from `/index.html` to `/`.

### Technical Improvements (Current Version)
### Technical Improvements

- **Router Enhancements**: Added `stats` route integration and synchronized active-state handling across sidebar and bottom navigation.
- **Mode Initialization Cleanup**: Simplified dark/accessibility mode application and favicon switching logic on startup and route renders.
- **Codebase Structure Updates**: Refactored page modules (`home`, `wardrobe`, `suggest`, `calendar`) for cleaner rendering flow and reusable UI behavior.
- **Version Bump**: Updated app constant to `APP_VERSION = '2026.04.24'` for this release.
- **Github Workflows**: Added Github Workflows for Pull Requests and Issues.
- **SRI hashes added to CDN scripts**: `integrity` + `crossorigin="anonymous"` attributes added to all three CDN tags (lz-string, Cropper.js JS and CSS) to guard against CDN compromise.
- **APP_VERSION CI regex tightened**: Deploy-preview workflow regex now enforces the strict `YYYY.MM.DD` format instead of accepting any sequence of digits and dots.
- **Label-sync workflow fixed**: Added `pip install pyyaml` step before the YAML parse step, which would otherwise fail with `ModuleNotFoundError` since `yaml` is not in Python's standard library.
- **LZString null check corrected**: `getItems` fallback now checks `=== null` instead of falsy, correctly handling the edge case where LZString returns an empty string.

### Fixed

- **Category validation error now visible**: `add-item` and `item-detail` forms were missing the `category-error` element, so the "Category is required" message was silently swallowed — error paragraph now rendered correctly under the category select.
- **Crop button re-usable after first crop**: After applying a crop in the add-item form, the replacement preview button had no event listener attached, making subsequent crops impossible — listener is now re-wired via a recursive helper after each crop.
- **localStorage quota errors surfaced**: `saveItems` was catching `QuotaExceededError` silently; it now re-throws so callers can alert the user when storage is full.

## Prior Release [v1.5.0] - 2026-03-10
## [v1.5.0] - 2026-03-10

### Added (v1.5.0)

Expand Down
67 changes: 0 additions & 67 deletions CLAUDE.md

This file was deleted.

15 changes: 7 additions & 8 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
Attyre
Copyright (c) 2026 Aether Assembly (Aster, Ollie, Milo)
Copyright (c) 2026 AetherAssembly (Aster, Ollie, Milo)

This project is currently licensed under the GNU Affero General Public
License v3.0 (AGPLv3). Aether Assembly is in the process of finalizing
License v3.0 (AGPLv3). AetherAssembly is in the process of finalizing
a custom organization-wide license. Until that license is in effect,
the AGPLv3 governs your use of this software.

In line with AetherAssembly's intended licensing direction:

- Personal use is free and unrestricted.
- Commercial use requires a written commercial agreement with
AetherAssembly. Contact support@aetherassembly.org.
AetherAssembly. Contact [support@aetherassembly.org](mailto:support@aetherassembly.org).
- Forks and modifications must remain publicly available under
the same license. You may not privatize or relicense a fork.
- Attribution to Aether Assembly must be maintained in all
- Attribution to AetherAssembly must be maintained in all
copies, forks, and derivative works.

For the full AGPLv3 license text, see:
https://www.gnu.org/licenses/agpl-3.0.html
Click here for the full [AGPLv3 license text](https://www.gnu.org/licenses/agpl-3.0.html).

For commercial licensing inquiries:
support@aetherassembly.org
https://forms.gle/T4i7GGzaT3HUrffm9
[support@aetherassembly.org](mailto:support@aetherassembly.org)
[Form](https://forms.gle/T4i7GGzaT3HUrffm9)
12 changes: 6 additions & 6 deletions Privacy-Policy.html
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,14 @@
</script>

<h1>Privacy Policy</h1>
<p class="subtitle">Last updated: April 2026 &nbsp;·&nbsp; Attyre by Aether Assembly &nbsp;·&nbsp; <a href="https://attyre.aetherassembly.org">attyre.aetherassembly.org</a></p>
<p class="subtitle">Last updated: May 2026 &nbsp;·&nbsp; Attyre by AetherAssembly &nbsp;·&nbsp; <a href="https://attyre.aetherassembly.org">attyre.aetherassembly.org</a></p>

<div class="callout">
<strong>Short version:</strong> Attyre collects nothing. Your wardrobe data never leaves your device. There are no accounts, no servers, no tracking, and no third-party data sharing of any kind.
</div>

<h2>1. Who We Are</h2>
<p>Attyre is a free, browser-based wardrobe management app developed and maintained by Aether Assembly — a small team consisting of Aster, Ollie, and Milo. You can reach us at <a href="mailto:support@aetherassembly.org">support@aetherassembly.org</a> or via our <a href="https://forms.gle/T4i7GGzaT3HUrffm9">contact form</a>.</p>
<p>Attyre is a free, browser-based wardrobe management app developed and maintained by AetherAssembly — a small team consisting of Aster, Ollie, and Milo. You can reach us at <a href="mailto:support@aetherassembly.org">support@aetherassembly.org</a> or via our <a href="https://forms.gle/T4i7GGzaT3HUrffm9">contact form</a>.</p>

<h2>2. Data We Do Not Collect</h2>
<p>We do not collect, store, transmit, or process any personal data on our servers — because we don't have any servers. Specifically, we do not collect:</p>
Expand All @@ -148,7 +148,7 @@ <h2>3. Data Stored on Your Device</h2>
<li>Your clothing items (names, categories, tags, warmth levels, notes)</li>
<li>Any photos you attach to items (stored as base64 data URLs)</li>
<li>Saved outfit combinations and calendar plans</li>
<li>App preferences (dark mode, colorblind mode)</li>
<li>App preferences (dark mode, accessibility mode)</li>
</ul>
<p>This data is entirely under your control. You can export it, delete it, or wipe it at any time from the Settings page. Clearing your browser's cache or localStorage will permanently delete all Attyre data — there is no cloud backup.</p>

Expand All @@ -158,7 +158,7 @@ <h2>4. Third-Party APIs</h2>
<li><strong>OpenStreetMap Nominatim</strong> (<a href="https://nominatim.openstreetmap.org" target="_blank" rel="noopener">nominatim.openstreetmap.org</a>) — converts a city name to coordinates. Subject to the <a href="https://operations.osmfoundation.org/policies/nominatim/" target="_blank" rel="noopener">Nominatim Usage Policy</a>.</li>
<li><strong>Open-Meteo</strong> (<a href="https://open-meteo.com" target="_blank" rel="noopener">open-meteo.com</a>) — fetches current temperature for those coordinates. Subject to the <a href="https://open-meteo.com/en/terms" target="_blank" rel="noopener">Open-Meteo Terms</a>.</li>
</ul>
<p>Both are free, open services with no affiliation to Aether Assembly. Their own privacy policies apply to any data they may collect from API requests.</p>
<p>Both are free, open services with no affiliation to AetherAssembly. Their own privacy policies apply to any data they may collect from API requests.</p>
<p>If you do not use the Suggest Outfit feature, no outbound requests are made at all.</p>

<h2>5. Children's Privacy</h2>
Expand All @@ -168,7 +168,7 @@ <h2>6. Your Rights</h2>
<p>Since we hold no data about you, there is nothing to request, correct, or delete on our end. To manage or delete your own data, use the Export and Import tools in the app's Settings page, or clear your browser's localStorage directly.</p>

<h2>7. Support</h2>
<p>Attyre is actively maintained by Aether Assembly. Support is provided for the current release and the two most recent major versions. For help, questions, or to report an issue:</p>
<p>Attyre is actively maintained by AetherAssembly. Support is provided for the current release and the two most recent major versions. For help, questions, or to report an issue:</p>
<ul>
<li>Email: <a href="mailto:support@aetherassembly.org">support@aetherassembly.org</a></li>
<li>Contact form: <a href="https://forms.gle/T4i7GGzaT3HUrffm9">forms.gle/T4i7GGzaT3HUrffm9</a></li>
Expand All @@ -181,7 +181,7 @@ <h2>9. Contact</h2>
<p>Questions or concerns? Reach us at <a href="mailto:support@aetherassembly.org">support@aetherassembly.org</a> or via our <a href="https://forms.gle/T4i7GGzaT3HUrffm9">contact form</a>.</p>

<footer>
&copy; 2026 Aether Assembly &nbsp;·&nbsp; Attyre &nbsp;·&nbsp; <a href="index.html">Back to App</a>
&copy; 2026 AetherAssembly &nbsp;·&nbsp; Attyre &nbsp;·&nbsp; <a href="index.html">Back to App</a>
</footer>

</div>
Expand Down
Loading