# Locator Style System

Verified against local source and public read-only REST responses on 2026-10-16.
Authority, user-invoked updates, cache refresh, and Settings History clarified by Lance on 2026-10-18; these clarifications are identified below separately from the initial code inspection.
Primary process description: https://internal.storelocatorplus.com/slp-style-system/.
Resolve source paths through `SLP_SaaS/Vendors/JetBrains/local.env`; plugin paths below are relative to `$WORDPRESS_CODE_DIR/wp-content/plugins/`.

## Ownership and publishing

- Lance confirmed the current authoritative source is the Locator Style custom posts and their custom fields on the WordPress-based REST API server. Git assets are generative sources and backups for now. When local assets and server values differ, use the server as the current baseline; do not overwrite it based solely on Git contents.
- `style-gallery-service` owns the gallery custom post type and service responses. It also stores style source assets, but these are separate delivery concerns.
- `store-locator-plus` owns the React Style panel, activation, SmartOptions application, and WordPress frontend styling.
- `myslp-dashboard` owns SaaS embed delivery of the saved CSS/settings. Its source is in the plugins tree and its SaaS runtime is an mu-plugin.
- The article reports production running gallery-service commit `a0c9e15e261507f2df2af6b274a074f783fd9330`, with the older “Store Locator Plus Premier Service” label. This deployed commit was not independently verified. Do not assume current local service code is deployed.
- Per the article, publishing currently means manually creating/editing a Locator Style post on `storelocatorplus.com`, pasting compiled CSS into its `css` custom field, and entering the other settings individually. Updating local assets or deploying plugin code alone does not publish those post-meta values.

## Source assets and build

`style-gallery-service/assets/styles/<StyleName>/` contains `settings.json`, `stylesheet.scss`, and generated `stylesheet.css` / `stylesheet.min.css` (maps vary). Existing directories include Default, Bennett, Bobbitt, Directory, and Feeding America - San Diego.

`settings.json` uses a `CustomFields` object with scalar option values; it is a source/export representation. The existing service PHP does not import these JSON files or automatically publish this directory. REST metadata instead uses arrays of values for each key.

Shared SCSS lives in `assets/saas/`, including `slp/_locator_style_components.scss`; “saas” is the actual directory spelling. Styles may import `../../saas/slp/locator_style_components`. `#style_name` and `#style_version` rules provide inspection markers, not a release manifest or update protocol.

`SLP_SaaS/.idea/watcherTasks.xml` has enabled expanded and minified SCSS watchers invoking the core plugin's Yarn `sass:css` / `sass:css:min` scripts. Verify watcher scope and execution before manually duplicating builds. Compilation does not update gallery posts or customer saved settings.

## Gallery API and card listing

- Standard post endpoint: `https://storelocatorplus.com/wp-json/wp/v2/slp_style_gallery/`; individual style: append its numeric post ID.
- Service source: `style-gallery-service/include/module/stylegallery/SLP_Service_StyleGallery.php` registers the public `slp_style_gallery` post type with REST support and title, editor, custom fields, revisions, thumbnail, and comments.
- `include/module/rest/SLP_Service_REST.php` adds read-only REST fields `custom_fields` and `css`. `custom_fields` comes from all post meta, including unrelated WordPress/editor/SEO metadata. It is not a clean settings manifest.
- The `css` response accepts a direct custom-field array (first entry contains CSS), or the older file-backed object containing `date` and `content`. File fallback uses `css_file` or `default` to read `style-gallery-service/css/<slug>.min.css`; this is separate from `assets/styles/`.
- `store-locator-plus/src/components/style/LocatorStyles.tsx` requests up to 100 posts, selecting `id,slug,title,modified,featured_media,content,yoast_head_json.og_image`. It supports title ascending or modified descending and has no pagination loop.
- `StyleCard.tsx` renders post content as HTML. Card imagery depends on both a featured-media ID and the first Yoast Open Graph image URL; it does not independently resolve the media ID. Account/add-on requirements are described in prose in sampled card content.
- Lance clarified that interaction with the Style panel automatically shows all available styles and refreshes any local cache with newer information. Refreshing catalog/cache information does not apply a style to the customer's settings. The initial inspection observed the list request and its 100-post limit; it did not fully trace cache-refresh behavior.

## Activation and setting semantics

1. `src/slp_style/slp_style.tsx` posts `{value: <post ID>, force_change: true}` to the installation's `store-locator-plus/v2/options/style_id/<apikey>` endpoint with `X-WP-Nonce`.
2. `include/module/rest/SLP_REST_Handler.php::update_smart_option()` sets the option, executes change callbacks, and persists JS and non-JS option groups.
3. `SLP_SmartOptions::change_style_id()` calls `SLP_Style_Manager::change_style()` / `apply_style()`.
4. `include/module/style/SLP_Style_Manager.php` fetches the individual post through `include/module/service/SLP_Service.php::get_styles()`. The card listing deliberately omitted the functional fields; activation fetches them separately on the server.
5. For each custom-field key, the manager checks whether SmartOptions knows it, takes value `[0]`, converts the exact string `&nbsp;` to an empty string, and passes it to `SmartOptions::set()`. That setter requires an active option. Unknown/inactive options are not applied; installed add-ons and subscription configuration affect the result.
6. CSS is assigned to `active_style_css` from the direct array or legacy file object's `content`, then the JS and non-JS groups are persisted.

Applying a style overlays supplied settings. Omitted settings retain prior values; it is not a complete reset to defaults. Switching styles can therefore carry settings forward. Reapplying a style can overwrite customer edits to supplied fields.

The active card's action is “Reload.” `force_change: true` allows the same style ID to be reapplied. Success currently triggers `window.location.reload()`. The SaaS preview loads the customer's actual embed script and saved configuration; it is not an isolated draft-style sandbox.

Lance confirmed that all customer style changes are manual and user-invoked through this UI: Activate fetches and applies the latest version of the selected style; Reload fetches and reapplies the latest version of the current style. There is no opt-in update program or automatic application of published CSS/settings. Treat catalog/cache refresh separately from style application.

The inspected fetch path makes a remote GET and has no transient-cache calls, despite constants named `TRANSIENT_BASE` in the style manager. This does not establish the absence of HTTP/CDN or other runtime caching.

Failure-handling limitation observed in source, not exercised against customer data: `apply_style()` returns without propagating a fetch error, while the REST option handler can still return a successful style-ID update. A future publisher/consumer flow should distinguish saving an ID from successfully fetching and applying a release.

## Settings History and customer customizations

Lance confirmed that the existing Settings History data table and UI handle preservation separately from style publishing. Whenever settings change, including customization and style application, an entry records the changes, providing the existing preservation mechanism for settings and styles. Reapplying a style can change current settings while prior changes remain recorded in history.

The Settings History implementation, recording coverage, and restore flow were not traced in the initial review. Verify those paths before changing setting-write behavior; do not infer that a new preservation system is required or claim unverified restore semantics.

## Frontend and SaaS delivery

- WordPress: `store-locator-plus/include/module/ui/SLP_UI.php::assign_user_stylesheet()` attaches saved `active_style_css` with `wp_add_inline_style()` when using `a_gallery_style.css`.
- SaaS: `myslp-dashboard/include/MySLP_REST_API.php` explicitly returns `inline_style` in its map response. `get_inline_style()` combines saved `active_style_css`, configured map dimensions, tagline width, and the `slp_ui_headers` filter output.
- Gallery publication, catalog/cache refresh, customer activation, and presentation delivery are distinct stages. The inspected activation path copies CSS/settings into the installation's options. Publishing a post does not itself replace those saved copies; Lance confirmed customer application remains manual through Activate/Reload.

## Dated live observations

Read-only GETs on 2026-10-16 returned 29 published styles. Stable identity must account for existing numeric IDs and slugs: Default is ID 67 / slug `basic`; Bennett is 1194 / `bennett`; Bobbitt is 1591 / `bobbitt`. Directory exists locally but was absent from that published listing.

Individual GETs confirmed array-valued `custom_fields` and direct `css` arrays for those three styles. All carried CSS marker version `2608.02.01`. Their returned CSS differed byte-for-byte from local `stylesheet.min.css`. Some local settings differed as strings; four Bobbitt local keys were absent remotely. These comparisons do not establish that every string difference changes behavior. Lance subsequently confirmed that server posts are authoritative; reconcile Git backups against that baseline before proposing publication changes.

## Confirmed requirements and remaining design work

- Confirmed by Lance on 2026-10-18: WordPress gallery posts are authoritative; Git assets are generative sources/backups for now.
- Confirmed: the Style panel refreshes available-style information and any local cache; only customer Activate/Reload actions apply the latest style. Automatic customer updates and opt-in distribution are outside the requested model.
- Confirmed: Settings History already preserves setting changes separately from style publishing.
- Remaining: streamline authoring/building/publishing to the authoritative server; define publishing environment and ownership, preview/validation, publisher rollback, and compatibility with existing post IDs and response shapes. Check existing Settings History integration before changing the activation/write path.

The component boundaries, activation contract, and Lance's requirements are durable context. Counts, comparisons, and reported production commit are dated evidence and must be rechecked. No new build/deploy implementation has been selected.
