A taxonomy supports discovery
A selected parent category includes its descendants. NestedTerms provides traversal while the application constructs the filter response.
A visual identity with a catalog underneath.
SinfulSmoke pairs a distinctive visual world with a structured catalog of pipes, leaf and accessories. The original logo anchors a new system of product artwork, collections and detailed item pages.
Catalog discovery needs more than attractive cards. Categories, descendant terms, filters and result counts need to agree as the visitor narrows a collection.
NestedTerms defines the catalog taxonomy. A build step validates associations and ships a read-only catalog with the application. Stow’s browser adapter manages the demo bag and favorites without a writable server cart.
A selected parent category includes its descendants. NestedTerms provides traversal while the application constructs the filter response.
Catalog installation checks every declared term before associating it. The deployment archive contains the prepared catalog; public browsing remains read-only.
Stow’s browser adapter owns bounded bag quantities and favorites membership. Saved state migrates from the previous storage format; recently viewed history remains separate navigation state.
NestedTerms 2 powers hierarchical categories and tag associations. Stow 2.1 supplies the browser basket used for the demo bag and favorites. Preflight checks the read-only server deployment. These client-side baskets do not create orders or payments.
Runs only in catalog build/isolated tests. Public requests read the packaged catalog.
NestedTerms package ↗$tags = CatalogTag::whereIn('slug', $item['terms'])->get();
if ($tags->count() !== count($item['terms'])) {
throw new \RuntimeException("Unknown catalog terms for {$item['slug']}.");
}
$record->syncTags($tags->all());AllDescendants comes from NestedTerms; application builds the facet response.
NestedTerms package ↗private function node(CatalogTag $tag): array
{
return ['slug' => $tag->slug, 'label' => $tag->name,
'ids' => [$tag->id, ...$tag->allDescendants()->modelKeys()],
'children' => $tag->children->map(fn ($child) => $this->node($child))->all()];
}The shared runner checks the Vapor manifest alongside production configuration and the storefront’s read-only runtime rules.
Preflight package ↗$runner = new Runner;
$results = array_merge($results, $runner->run([
new VaporManifest($manifest, 'production', config('preflight.vapor_limits')),
$app->make(ProductionConfiguration::class),
$app->make(DemoRuntime::class),
]));The application passes valid catalog slugs and its item/quantity limits to Stow. The migration imports previously saved demo lines into the package’s browser storage.
Stow package ↗basket = createBrowserBasket({
storageKey: "sinfulsmoke.stow.bag.v1",
allowedIds: items.map((item) => item.slug),
maxItems: 20,
maxQuantity: 9,
migrate(storage) {
let legacy;
try {
legacy = JSON.parse(storage.getItem("sinfulsmoke.demo-previews.v1") || "[]");
} catch { return []; }
return Array.isArray(legacy)
? legacy.map((line) => ({ id: line?.slug, quantity: line?.quantity }))
: [];
},
});A separate Stow basket is configured for at most 24 items and one of each. The application keeps catalog validation and visitor-facing notices.
Stow package ↗export function toggleFavorite(slug) {
if (!favorites || !catalog.value.some((item) => item.slug === slug)) return;
const removing = isFavorite(slug);
if (removing) favorites.remove(slug);
else favorites.add(slug);
collectionNotice.value = removing
? "Removed from favorites."
: isFavorite(slug) ? "Saved to favorites." : "You can save up to 24 favorites.";
}The host application keeps its own footer and copyright. A shared Blade component follows the application root, so client rendering does not duplicate it.
SiteCredit package ↗<x-site-credit />A published nontransactional showcase. Stow manages browser-only favorites and demo bag state; ordering, payment collection and real inventory sales are unavailable.
Designed, Developed and Hosted by Better Web Design and Development Services, LLC