How-To: Add a New Store
Relevant source files
The following files were used as context for generating this wiki page:- app/Filament/Resources/StoreResource.php
- app/Models/Store.php
- app/Services/AutoCreateStore.php
- app/Filament/Resources/StoreResource/Api/Handlers/CreateHandler.php
- app/Filament/Resources/StoreResource/Api/Requests/CreateStoreRequest.php
- app/Filament/Resources/StoreResource/Actions/ImportStoreAction.php
- config/price_buddy.php
- app/Models/Url.php
In PriceBuddy, a "Store" represents an online retailer. Each store configuration contains the domains it operates on and, crucially, the scraping strategies required to extract product information (title, price, image) from its product pages. Adding stores is a fundamental prerequisite for tracking products from new retailers.
This document outlines the various methods for adding a new store to the application. These methods include manual creation through the Filament admin panel, programmatic creation via the REST API, automatic creation when adding a new product URL from an unknown retailer, and importing a store's configuration from a JSON object.
Sources: README.md, app/Filament/Resources/StoreResource.php
Store Data Model
The core of the store functionality is the Store Eloquent model. It holds all configuration related to a retailer, including its name, associated domains, and the logic for scraping data.
Sources: app/Models/Store.php
Entity Relationship Diagram
The diagram below illustrates how the Store model relates to other key models in the database. A Store is created by a User, has many Url records, and through those URLs, has many Product records.
Key Attributes
The stores table contains several important columns for defining a store's behavior.
| Attribute | Type | Description |
|---|---|---|
name | string | The human-readable name of the store (e.g., "Amazon"). |
slug | string | A URL-friendly version of the name, automatically generated. |
initials | string | A two-letter abbreviation for the store, automatically generated from the name if not provided. |
domains | array | A JSON array of objects, each containing a domain key (e.g., [{ "domain": "amazon.com" }]). |
scrape_strategy | array | A JSON object defining how to extract title, price, and image data. Each key contains a type (e.g., 'selector') and a value (e.g., 'h1'). |
settings | array | A JSON object for various settings, including scraper_service, scraper_service_settings, and locale_settings. |
notes | text | A field for any additional information about the store or its scraping nuances. |
user_id | int | The ID of the user who created the store. |
Sources: app/Models/Store.php:28-40, app/Filament/Resources/StoreResource.php:51-127
Methods for Adding a Store
There are four primary ways to add a new store, catering to different use cases from manual user input to fully automated workflows.
1. Manual Creation (Filament Admin Panel)
Users can manually create a store through the "Stores" resource in the Filament admin panel. The creation form is divided into sections for basic information, domains, scraping strategies, and advanced settings.
Sources: app/Filament/Resources/StoreResource.php, tests/Feature/Filament/StoreTest.php:90-116
Form Fields
The StoreResource::form() method defines the structure of the creation and edit forms.
| Section | Field | Description |
|---|---|---|
| Basics | name | The required name of the store. |
| Domains | domains | A repeater field to add one or more domains associated with the store. |
| Title strategy | type, value, prepend, append | Defines the method (e.g., Selector, Regex, JSONPath) and value for extracting the product title. |
| Price strategy | type, value, prepend, append | Defines the method and value for extracting the product price. |
| Image strategy | type, value, prepend, append | Defines the method and value for extracting the product image. |
| Scraper service | scraper_service | A choice between http (fast, for static HTML) and api (slower, for JavaScript-rendered pages via Selenium). |
scraper_service_settings | Advanced options for the api scraper service. | |
| Locale | locale, currency | Overrides for default locale and currency settings for this specific store. |
| Notes | notes | A rich text editor for additional notes. |
Sources: app/Filament/Resources/StoreResource.php:51-127
2. Automatic Creation
A store can be automatically created when a user adds a product URL from a domain that is not yet associated with any existing store. This process is handled by the AutoCreateStore service.
Sources: app/Services/AutoCreateStore.php, app/Models/Url.php:121-123
Auto-Creation Flow
The service attempts to intelligently determine the correct scraping strategies by fetching the URL's content and applying a series of predefined rules.
The strategies for finding the title, price, and image are defined in config/price_buddy.php. The service iterates through CSS selectors and regular expressions until a valid value is found for each attribute.
Sources: config/price_buddy.php:20-67, app/Services/AutoCreateStore.php:115-189
3. Programmatic Creation (REST API)
A new store can be created by making a POST request to the /api/stores endpoint. This is managed by the CreateHandler for the StoreResource.
Sources: app/Filament/Resources/StoreResource/Api/Handlers/CreateHandler.php, tests/Feature/Api/StoreApiTest.php:82-120
API Creation Sequence
The following diagram shows the sequence of events when a store is created via the API.
Request Parameters
The request body must conform to the validation rules defined in CreateStoreRequest.
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | The name of the store. |
domains | array | Yes | An array of domain objects, e.g., [{"domain": "store.com"}]. |
domains.*.domain | string | Yes | The domain name. |
scrape_strategy | array | Yes | Object containing title, price, and image strategies. |
scrape_strategy.*.type | string | Yes | The type of strategy (selector, regex, jsonpath). |
scrape_strategy.*.value | string | Yes | The value for the strategy (e.g., CSS selector). |
settings | array | Yes | Object containing scraper and locale settings. |
settings.scraper_service | string | Yes | Must be one of the ScraperService enum values (e.g., http, api). |
settings.scraper_service_settings | string | No | Newline-separated key=value pairs for the API scraper. |
notes | string | No | Additional notes. |
user_id | integer | No | Must be the ID of the authenticated user if provided. |
Sources: app/Filament/Resources/StoreResource/Api/Requests/CreateStoreRequest.php:23-49
4. Import from JSON
The Filament admin panel includes an "Import" action that allows for creating a store from a JSON object. This feature is useful for migrating store configurations or sharing them between instances.
The action, defined in ImportStoreAction, presents a modal with a textarea for the JSON payload. Upon submission, it decodes the JSON and uses the CreateStoreAction to create the new store record. The JSON structure must match the attributes expected by the CreateStoreAction.
Sources: app/Filament/Resources/StoreResource/Actions/ImportStoreAction.php:39-55
Conclusion
The PriceBuddy application provides multiple flexible pathways for adding new stores. The manual UI method is ideal for administrators setting up known retailers with complex scraping rules. The API offers a programmatic interface for integration with other systems. The automatic creation feature significantly enhances user experience by seamlessly adding new stores on the fly. Finally, the JSON import function provides a convenient way to back up, restore, or share store configurations. This multi-faceted approach ensures that the application can easily adapt to an ever-expanding list of online retailers.