@mohasinac/appkit 4.43.0 → 4.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/server/features/categories/adapters.d.ts +47 -0
- package/dist/_internal/server/features/categories/adapters.js +235 -0
- package/dist/_internal/server/features/checkout/actions.js +161 -22
- package/dist/_internal/server/features/checkout/expand-order-items.js +34 -0
- package/dist/_internal/server/features/orders/adapters.js +21 -0
- package/dist/_internal/server/features/refunds/actions.js +1 -1
- package/dist/_internal/server/features/seo/sitemap.js +54 -15
- package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
- package/dist/_internal/server/features/stores/adapters.js +6 -0
- package/dist/_internal/server/functions/scheduled.d.ts +4 -2
- package/dist/_internal/server/functions/scheduled.js +64 -6
- package/dist/_internal/server/jobs/core/adminAnalytics.d.ts +0 -1
- package/dist/_internal/server/jobs/core/adminAnalytics.js +9 -1
- package/dist/_internal/server/jobs/core/analyticsAlertEvaluate.d.ts +47 -0
- package/dist/_internal/server/jobs/core/analyticsAlertEvaluate.js +468 -0
- package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +14 -1
- package/dist/_internal/server/jobs/core/countersReconcile.js +24 -8
- package/dist/_internal/server/jobs/core/onCategoryWrite.js +54 -0
- package/dist/_internal/server/jobs/core/priceIndexRollup.d.ts +47 -0
- package/dist/_internal/server/jobs/core/priceIndexRollup.js +234 -0
- package/dist/_internal/server/jobs/core/{testerSandboxCleanup.d.ts → testDataCleanup.d.ts} +3 -3
- package/dist/_internal/server/jobs/core/{testerSandboxCleanup.js → testDataCleanup.js} +3 -3
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +5 -1
- package/dist/_internal/server/jobs/handlers/analyticsAlertEvaluate.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/analyticsAlertEvaluate.js +2 -0
- package/dist/_internal/server/jobs/handlers/index.d.ts +3 -1
- package/dist/_internal/server/jobs/handlers/index.js +3 -1
- package/dist/_internal/server/jobs/handlers/messages.d.ts +5 -2
- package/dist/_internal/server/jobs/handlers/messages.js +5 -2
- package/dist/_internal/server/jobs/handlers/priceIndexRollup.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/priceIndexRollup.js +2 -0
- package/dist/_internal/server/jobs/handlers/testDataCleanup.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/testDataCleanup.js +2 -0
- package/dist/_internal/shared/actions/action-registry.js +34 -0
- package/dist/_internal/shared/checkout/order-math.d.ts +113 -3
- package/dist/_internal/shared/checkout/order-math.js +194 -7
- package/dist/_internal/shared/features/categories/price-guidance.d.ts +110 -0
- package/dist/_internal/shared/features/categories/price-guidance.js +136 -0
- package/dist/_internal/shared/features/site-settings/gst-registration.d.ts +90 -0
- package/dist/_internal/shared/features/site-settings/gst-registration.js +126 -0
- package/dist/_internal/shared/fees/calculator.d.ts +105 -0
- package/dist/_internal/shared/fees/calculator.js +143 -0
- package/dist/_internal/shared/listing-types/art/config.d.ts +0 -6
- package/dist/_internal/shared/listing-types/classified/config.d.ts +0 -6
- package/dist/_internal/shared/listing-types/digital-code/config.d.ts +0 -6
- package/dist/_internal/shared/listing-types/live/config.d.ts +0 -6
- package/dist/_internal/shared/listing-types/standard/config.d.ts +0 -6
- package/dist/_internal/shared/listing-types/stickers/config.d.ts +0 -6
- package/dist/_internal/shared/templating/placeholders.d.ts +70 -0
- package/dist/_internal/shared/templating/placeholders.js +73 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.js +1 -0
- package/dist/constants/api-endpoints.d.ts +42 -0
- package/dist/constants/api-endpoints.js +14 -0
- package/dist/features/admin/actions/admin-actions.d.ts +1 -1
- package/dist/features/admin/actions/admin-actions.js +1 -1
- package/dist/features/admin/components/AdminCategoryEditorView.js +269 -3
- package/dist/features/admin/components/AdminProductEditorView.js +8 -1
- package/dist/features/admin/components/AdminProductsView.js +78 -7
- package/dist/features/admin/components/AdminSiteSettingsView.js +20 -1
- package/dist/features/admin/components/AdminTaxCodeEditorView.d.ts +10 -0
- package/dist/features/admin/components/AdminTaxCodeEditorView.js +160 -0
- package/dist/features/admin/components/AdminTaxCodesView.d.ts +13 -0
- package/dist/features/admin/components/AdminTaxCodesView.js +86 -0
- package/dist/features/admin/components/AdminTesterChecklistView.js +1 -1
- package/dist/features/admin/components/analytics/AdminTopProductsTable.js +1 -1
- package/dist/features/auth/schemas/firestore.d.ts +0 -1
- package/dist/features/blog/schemas/firestore.d.ts +2 -2
- package/dist/features/catalogue/components/CatalogueItemEditorView.js +14 -3
- package/dist/features/categories/api/[id]/description-template/route.d.ts +45 -0
- package/dist/features/categories/api/[id]/description-template/route.js +252 -0
- package/dist/features/categories/api/route.js +156 -11
- package/dist/features/categories/components/CategoryDetailPageView.js +43 -10
- package/dist/features/categories/components/CategoryTemplatePicker.d.ts +65 -0
- package/dist/features/categories/components/CategoryTemplatePicker.js +170 -0
- package/dist/features/categories/constants/listing-categories.d.ts +17 -0
- package/dist/features/categories/constants/listing-categories.js +53 -0
- package/dist/features/categories/hooks/useCategoryTree.js +28 -2
- package/dist/features/categories/repository/categories.repository.d.ts +62 -11
- package/dist/features/categories/repository/categories.repository.js +178 -35
- package/dist/features/categories/repository/price-index.repository.d.ts +115 -0
- package/dist/features/categories/repository/price-index.repository.js +85 -0
- package/dist/features/categories/schemas/category-content.d.ts +206 -0
- package/dist/features/categories/schemas/category-content.js +28 -0
- package/dist/features/categories/schemas/firestore.d.ts +74 -5
- package/dist/features/categories/schemas/firestore.js +74 -3
- package/dist/features/categories/schemas/index.d.ts +1047 -0
- package/dist/features/categories/schemas/index.js +96 -0
- package/dist/features/categories/server.d.ts +1 -0
- package/dist/features/categories/server.js +7 -0
- package/dist/features/categories/types/index.d.ts +9 -0
- package/dist/features/events/schemas/firestore.d.ts +2 -2
- package/dist/features/faq/schemas/firestore.d.ts +2 -1
- package/dist/features/faq/schemas/firestore.js +20 -8
- package/dist/features/orders/schemas/firestore.d.ts +70 -0
- package/dist/features/orders/types/index.d.ts +55 -0
- package/dist/features/products/columns/index.d.ts +0 -1
- package/dist/features/products/columns/index.js +5 -1
- package/dist/features/products/components/ProductFilters.d.ts +0 -9
- package/dist/features/products/components/ProductForm.d.ts +27 -1
- package/dist/features/products/components/ProductForm.js +26 -12
- package/dist/features/products/constants/sieve.d.ts +0 -6
- package/dist/features/products/constants/sieve.js +35 -2
- package/dist/features/products/repository/products.repository.d.ts +115 -1
- package/dist/features/products/repository/products.repository.js +491 -39
- package/dist/features/products/schemas/firestore.d.ts +65 -5
- package/dist/features/products/schemas/firestore.js +9 -0
- package/dist/features/products/schemas/product-features.d.ts +140 -2
- package/dist/features/products/schemas/product-features.js +62 -1
- package/dist/features/promotions/repository/coupons.repository.js +6 -1
- package/dist/features/promotions/schemas/firestore.d.ts +44 -1
- package/dist/features/promotions/schemas/firestore.js +76 -2
- package/dist/features/seller/actions/seller-actions.js +17 -2
- package/dist/features/seller/components/PrintCenterView.d.ts +3 -2
- package/dist/features/seller/components/PrintCenterView.js +3 -2
- package/dist/features/seller/components/SellerAnalyticsAlertsView.js +21 -11
- package/dist/features/seller/components/SellerOrdersView.js +6 -1
- package/dist/features/seller/components/SellerPayoutSettingsView.js +19 -3
- package/dist/features/seller/components/SellerProductShell.d.ts +50 -2
- package/dist/features/seller/components/SellerProductShell.js +101 -9
- package/dist/features/seller/components/SellerProductsFilterDrawer.d.ts +13 -1
- package/dist/features/seller/components/SellerProductsFilterDrawer.js +2 -2
- package/dist/features/seller/components/SellerProductsView.js +108 -3
- package/dist/features/seller/types/index.d.ts +17 -0
- package/dist/features/seller/utils/product-draft-mapping.d.ts +13 -0
- package/dist/features/seller/utils/product-draft-mapping.js +17 -0
- package/dist/features/store-extensions/constants/alert-metrics.d.ts +86 -0
- package/dist/features/store-extensions/constants/alert-metrics.js +142 -0
- package/dist/features/store-extensions/schemas/firestore.d.ts +19 -1
- package/dist/features/stores/schemas/firestore.d.ts +31 -2
- package/dist/features/tax-codes/repository/tax-codes.repository.d.ts +55 -0
- package/dist/features/tax-codes/repository/tax-codes.repository.js +131 -0
- package/dist/features/tax-codes/schemas/firestore.d.ts +125 -0
- package/dist/features/tax-codes/schemas/firestore.js +82 -0
- package/dist/features/tax-codes/schemas/tax-code-form.d.ts +63 -0
- package/dist/features/tax-codes/schemas/tax-code-form.js +152 -0
- package/dist/features/tax-codes/schemas/tax-codes.validators.d.ts +107 -0
- package/dist/features/tax-codes/schemas/tax-codes.validators.js +85 -0
- package/dist/features/tester/actions/index.d.ts +0 -1
- package/dist/features/tester/actions/index.js +0 -1
- package/dist/features/tester/components/AdminTesterFeedbackIssuesView.js +1 -1
- package/dist/features/tester/components/AdminTesterFeedbackListView.js +1 -1
- package/dist/features/tester/components/index.d.ts +0 -4
- package/dist/features/tester/components/index.js +0 -2
- package/dist/features/tester/repository/tester-checklist-item.repository.d.ts +1 -20
- package/dist/features/tester/repository/tester-checklist-item.repository.js +0 -52
- package/dist/features/tester/schemas/firestore.d.ts +0 -6
- package/dist/features/tester/seed-data/authored/admin__admin-detail-round-trips.js +3 -3
- package/dist/features/tester/seed-data/authored/admin__site-system.js +4 -5
- package/dist/features/tester/seed-data/authored/content-discovery__category-counts-and-rollup.js +2 -2
- package/dist/features/tester/seed-data/authored/index.js +0 -2
- package/dist/features/tester/seed-data/authored/page-wiring__reachability.js +0 -19
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +8 -27
- package/dist/index.d.ts +21 -7
- package/dist/index.js +53 -7
- package/dist/next/routing/route-map.d.ts +2 -4
- package/dist/next/routing/route-map.js +1 -2
- package/dist/repositories/index.d.ts +1 -0
- package/dist/repositories/index.js +1 -0
- package/dist/schemas/registry.d.ts +506 -0
- package/dist/seed/_helpers/brand-rows.d.ts +35 -0
- package/dist/seed/_helpers/brand-rows.js +576 -0
- package/dist/seed/_helpers/category-content.d.ts +39 -0
- package/dist/seed/_helpers/category-content.js +634 -0
- package/dist/seed/_helpers/category-forest.d.ts +2 -0
- package/dist/seed/_helpers/category-forest.js +585 -243
- package/dist/seed/_helpers/category-models.d.ts +5 -0
- package/dist/seed/_helpers/category-models.js +1364 -0
- package/dist/seed/_helpers/category-tree.js +17 -1
- package/dist/seed/_helpers/character-features.d.ts +10 -0
- package/dist/seed/_helpers/character-features.js +118 -0
- package/dist/seed/_helpers/search-txt-wrappers.d.ts +10 -0
- package/dist/seed/_helpers/search-txt-wrappers.js +12 -1
- package/dist/seed/categories-seed-data.js +147 -169
- package/dist/seed/index.d.ts +1 -0
- package/dist/seed/index.js +1 -0
- package/dist/seed/manifest.d.ts +1 -1
- package/dist/seed/manifest.js +5 -0
- package/dist/seed/product-features-seed-data.d.ts +1 -8
- package/dist/seed/product-features-seed-data.js +358 -154
- package/dist/seed/products-art-seed-data.js +16 -4
- package/dist/seed/products-auctions-seed-data.js +6 -6
- package/dist/seed/products-classifieds-seed-data.js +17 -7
- package/dist/seed/products-digital-codes-seed-data.js +12 -12
- package/dist/seed/products-preorders-seed-data.js +8 -8
- package/dist/seed/products-prize-draws-seed-data.js +25 -8
- package/dist/seed/products-standard-seed-data.js +10 -60
- package/dist/seed/products-stickers-seed-data.js +6 -6
- package/dist/seed/site-settings-seed-data.js +24 -0
- package/dist/seed/store-extensions-seed-data.js +10 -4
- package/dist/seed/tax-codes-seed-data.d.ts +34 -0
- package/dist/seed/tax-codes-seed-data.js +100 -0
- package/dist/seed/test-data-ttl.d.ts +29 -0
- package/dist/seed/test-data-ttl.js +31 -0
- package/dist/server-entry.d.ts +1 -1
- package/dist/server-entry.js +6 -1
- package/dist/server.d.ts +2 -1
- package/dist/server.js +5 -2
- package/dist/styles.css +40 -0
- package/dist/ui/components/PaginatedSelect.d.ts +14 -0
- package/dist/ui/components/PaginatedSelect.js +0 -0
- package/dist/ui/components/PaginatedSelect.style.css +40 -0
- package/dist/utils/physical-location.d.ts +23 -0
- package/dist/utils/physical-location.js +52 -0
- package/dist/utils/search-txt-builders.d.ts +20 -0
- package/dist/utils/search-txt-builders.js +36 -0
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +4 -1
- package/dist/_internal/server/jobs/handlers/testerSandboxCleanup.d.ts +0 -2
- package/dist/_internal/server/jobs/handlers/testerSandboxCleanup.js +0 -2
- package/dist/features/tester/actions/leaderboard-actions.d.ts +0 -3
- package/dist/features/tester/actions/leaderboard-actions.js +0 -5
- package/dist/features/tester/components/BugHunterLeaderboardView.d.ts +0 -23
- package/dist/features/tester/components/BugHunterLeaderboardView.js +0 -18
- package/dist/features/tester/components/TesterHubView.d.ts +0 -5
- package/dist/features/tester/components/TesterHubView.js +0 -110
- package/dist/features/tester/seed-data/authored/public-pages__bug-hunters.d.ts +0 -2
- package/dist/features/tester/seed-data/authored/public-pages__bug-hunters.js +0 -78
- package/dist/features/tester/seed-data/tester-ttl.d.ts +0 -4
- package/dist/features/tester/seed-data/tester-ttl.js +0 -6
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* WHY: The seed carried FOUR brand rows for a catalogue that was about to span
|
|
3
|
+
* Beyblade, trading cards, figures and die-cast. A product's `brand`
|
|
4
|
+
* string that matches no brand row is invisible on every brand page, and
|
|
5
|
+
* the four existing rows cover none of the three new verticals.
|
|
6
|
+
* WHAT: One factory plus 28 compact declarations. The boilerplate every brand
|
|
7
|
+
* row needs — tier-0 coordinates, isBrand, searchability, the seo block —
|
|
8
|
+
* is written once; each brand declares only what differs.
|
|
9
|
+
*
|
|
10
|
+
* EXPORTS:
|
|
11
|
+
* BRAND_ROWS — Partial<CategoryDocument>[], categoryType:"brand"
|
|
12
|
+
* BRAND_ROW_COUNT — asserted by the seed so a silent drop is loud
|
|
13
|
+
*
|
|
14
|
+
* ## 🛑 Three traps, all of them live
|
|
15
|
+
*
|
|
16
|
+
* 1. **`BrandDetailPageView` filters products on the brand's DISPLAY NAME**
|
|
17
|
+
* (`sieveFilter("brand", EQ, brandName)`), not on `brandSlug`. So renaming
|
|
18
|
+
* a brand silently orphans its entire catalogue — which is why
|
|
19
|
+
* `Takara-Tomy` keeps its existing hyphenated spelling even though the
|
|
20
|
+
* company writes it "Takara Tomy". Keep `brand` and `brandSlug` in lockstep
|
|
21
|
+
* on the product side.
|
|
22
|
+
*
|
|
23
|
+
* 2. **`display.icon` BEATS `display.coverImage`.** `BrandsSection` reads
|
|
24
|
+
* `brand.display?.icon` first and only falls back to `coverImage`. The
|
|
25
|
+
* existing seed uses `icon` for EMOJI, so an emoji left there wins over a
|
|
26
|
+
* real logo. Every row here leaves `icon` unset.
|
|
27
|
+
*
|
|
28
|
+
* 3. **A brand row with no product is a DEAD FACET, and worse than absent** —
|
|
29
|
+
* it renders as a card in the brands grid that opens an empty page. That is
|
|
30
|
+
* the whole reason there is no standalone `Tomy` row: Takara is the
|
|
31
|
+
* pre-merger Beyblade maker and Takara Tomy is the merged entity, while
|
|
32
|
+
* Tomy's own pre-merger role is established by NO source we hold (zero
|
|
33
|
+
* `Tomy`-only brand values across all fifteen crawls, and the local corpus
|
|
34
|
+
* never attributes a product code to Tomy alone). Every row below is one
|
|
35
|
+
* B6 can put at least one real product behind.
|
|
36
|
+
*
|
|
37
|
+
* ## 🛑 Why these are seedPhoto tiles and not 28 committed logo SVGs
|
|
38
|
+
*
|
|
39
|
+
* The plan recommended committing `public/images/brands/<slug>.svg` to avoid
|
|
40
|
+
* `seedExtMedia`, which persists an `/api/media/ext?url=…` into Firestore and
|
|
41
|
+
* costs a lambda plus a third-party fetch plus a full sharp encode PER IMAGE
|
|
42
|
+
* PER RENDER — Root Cause #104, the thing that took Fast Origin Transfer to
|
|
43
|
+
* 52.52 GB against a 10 GB cap.
|
|
44
|
+
*
|
|
45
|
+
* That reasoning is right and the conclusion has moved, because `seedPhoto`
|
|
46
|
+
* now resolves to one of six STATIC LOCAL SVG tiles served `immutable` from
|
|
47
|
+
* `/images/`. It already has the property the recommendation was reaching for:
|
|
48
|
+
* no proxy, no third-party fetch, no per-render cost.
|
|
49
|
+
*
|
|
50
|
+
* And it avoids a question committing the files would raise — 26 of these are
|
|
51
|
+
* marques we do not own, so shipping drawn approximations of their logos is
|
|
52
|
+
* trademark reproduction for commercial use. A neutral tile is honest about
|
|
53
|
+
* being a placeholder. Real logos are a licensed-asset task, not a seed task.
|
|
54
|
+
*
|
|
55
|
+
* @tag domain:categories
|
|
56
|
+
* @tag layer:seed
|
|
57
|
+
* @tag pattern:shared-literal
|
|
58
|
+
* @tag access:server-only
|
|
59
|
+
* @tag consumers:seed/categories-seed-data.ts
|
|
60
|
+
* @tag sideEffects:none
|
|
61
|
+
*/
|
|
62
|
+
/*
|
|
63
|
+
* 🛑 `constants/field-names`, NOT `features/categories/schemas/firestore`.
|
|
64
|
+
* There are TWO `CATEGORY_FIELDS` constants in this codebase and they have
|
|
65
|
+
* drifted — only this one carries `CATEGORY_TYPE_VALUES`, and the schema copy
|
|
66
|
+
* carries `PRODUCT_DEFAULTS_TAX_CODE_ID`, which this one does not.
|
|
67
|
+
* `categories-seed-data.ts` imports this copy; matching it is what keeps the
|
|
68
|
+
* brand discriminator a single spelling.
|
|
69
|
+
*/
|
|
70
|
+
import { CATEGORY_FIELDS } from "../../constants/field-names";
|
|
71
|
+
import { seedPhoto } from "./media";
|
|
72
|
+
export function brandRow(input, order, stamps) {
|
|
73
|
+
const id = `brand-${input.slug}`;
|
|
74
|
+
return {
|
|
75
|
+
id,
|
|
76
|
+
slug: id,
|
|
77
|
+
name: input.name,
|
|
78
|
+
categoryType: CATEGORY_FIELDS.CATEGORY_TYPE_VALUES.BRAND,
|
|
79
|
+
description: input.description,
|
|
80
|
+
...(input.website ? { brandWebsite: input.website } : {}),
|
|
81
|
+
brandCountry: input.country,
|
|
82
|
+
...(input.founded ? { brandFounded: input.founded } : {}),
|
|
83
|
+
highlights: input.highlights,
|
|
84
|
+
...(input.faqs ? { faqs: input.faqs } : {}),
|
|
85
|
+
rootId: id,
|
|
86
|
+
parentIds: [],
|
|
87
|
+
childrenIds: [],
|
|
88
|
+
ancestors: [],
|
|
89
|
+
tier: 0,
|
|
90
|
+
path: id,
|
|
91
|
+
isLeaf: true,
|
|
92
|
+
order,
|
|
93
|
+
/*
|
|
94
|
+
* 🛑 `icon` deliberately UNSET — see trap 2. A cover image only.
|
|
95
|
+
* `position` is NOT set here: brand rows live outside the category
|
|
96
|
+
* forest's DFS numbering, and giving them a position inside it would
|
|
97
|
+
* corrupt the ranges `onCategoryWrite` shifts on insert.
|
|
98
|
+
*/
|
|
99
|
+
display: {
|
|
100
|
+
coverImage: seedPhoto(`brand-logo-${input.slug}-20260101`, 800, 800),
|
|
101
|
+
showInMenu: false,
|
|
102
|
+
showInFooter: input.footer ?? false,
|
|
103
|
+
},
|
|
104
|
+
isFeatured: input.featured ?? false,
|
|
105
|
+
isBrand: true,
|
|
106
|
+
isActive: true,
|
|
107
|
+
isSearchable: true,
|
|
108
|
+
createdBy: stamps.createdBy,
|
|
109
|
+
createdAt: stamps.createdAt,
|
|
110
|
+
updatedAt: stamps.updatedAt,
|
|
111
|
+
seo: {
|
|
112
|
+
title: `${input.name} | LetItRip`,
|
|
113
|
+
description: input.seoDescription,
|
|
114
|
+
keywords: input.keywords,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
119
|
+
// Beyblade — EIGHT rows, and the count is the interesting part
|
|
120
|
+
//
|
|
121
|
+
// Takara is the pre-2006 maker (beybladeshopindia's Brand field is literally
|
|
122
|
+
// `Takara` on 2,011 products, and the local corpus attributes Gen-1 codes to
|
|
123
|
+
// `(Takara)` while BX-era codes carry `(TT)`). Takara Tomy is the merged
|
|
124
|
+
// entity. There is NO standalone Tomy row — see trap 3.
|
|
125
|
+
//
|
|
126
|
+
// `Beyblade` itself stays a row because the existing seed has it and products
|
|
127
|
+
// reference it; it is the FRANCHISE rather than a manufacturer, the same
|
|
128
|
+
// precedent `Hot Wheels` follows on the die-cast side.
|
|
129
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
130
|
+
const BEYBLADE_BRANDS = [
|
|
131
|
+
{
|
|
132
|
+
slug: "takara-tomy",
|
|
133
|
+
// 🛑 Hyphenated, matching what products already carry. The company writes
|
|
134
|
+
// it "Takara Tomy"; renaming to match them orphans the catalogue.
|
|
135
|
+
name: "Takara-Tomy",
|
|
136
|
+
description: "The Japanese toy company behind every Beyblade generation since the 2006 merger, plus Tomica, Transformers (Japan) and Duel Masters. Known for premium tooling and Japan-exclusive releases.",
|
|
137
|
+
country: "Japan",
|
|
138
|
+
founded: 2006,
|
|
139
|
+
website: "https://www.takaratomy.co.jp",
|
|
140
|
+
highlights: [
|
|
141
|
+
"Manufactures every Beyblade generation from 2006 onward",
|
|
142
|
+
"Also behind Tomica, Transformers (Japan region) and Duel Masters",
|
|
143
|
+
"Japan-exclusive releases and the tighter tolerances competitive players prefer",
|
|
144
|
+
],
|
|
145
|
+
faqs: [
|
|
146
|
+
{ question: "Is Takara-Tomy the same company as Hasbro's Beyblade line?", answer: "No. Takara-Tomy manufactures and sells Beyblade in Japan and most of Asia; Hasbro licenses and distributes a separate — sometimes genuinely different — product line internationally, primarily in North America." },
|
|
147
|
+
{ question: "Are Takara-Tomy imports compatible with Hasbro Beyblade parts?", answer: "Within the same generation, almost always yes. Across generations, no: the launcher and locking systems changed every time." },
|
|
148
|
+
],
|
|
149
|
+
footer: true,
|
|
150
|
+
featured: true,
|
|
151
|
+
keywords: ["takara tomy", "takara tomy beyblade", "tomica takara", "beyblade japan"],
|
|
152
|
+
seoDescription: "Shop Takara-Tomy collectibles — Beyblade across every generation, plus Tomica and Transformers Japan releases.",
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
slug: "takara",
|
|
156
|
+
name: "Takara",
|
|
157
|
+
description: "The pre-merger company that created Beyblade in 1999 and made every Plastic Generation, Spin Gear, Magnacore, Engine Gear and HMS release until it merged with Tomy in 2006.",
|
|
158
|
+
country: "Japan",
|
|
159
|
+
founded: 1955,
|
|
160
|
+
highlights: [
|
|
161
|
+
"Created Beyblade in 1999 — every original-generation top is a Takara product",
|
|
162
|
+
"The marque on Gen-1 product codes (A-xx, MA-xx) before the 2006 merger",
|
|
163
|
+
"Vintage Takara pieces in playable condition are the scarcest Beyblade tier",
|
|
164
|
+
],
|
|
165
|
+
faqs: [
|
|
166
|
+
{ question: "What is the difference between Takara and Takara-Tomy?", answer: "Takara made Beyblade alone from 1999 until it merged with Tomy in 2006 to form Takara Tomy. A top with an A-xx or MA-xx code is a Takara release; a BB-xx, B-xx or BX-xx code is Takara Tomy." },
|
|
167
|
+
{ question: "Is a Takara-era top still usable?", answer: "Yes, though plastic from 1999–2003 has aged. Check the listing for stress marks around the Blade Base and for a clean spin gear — a cracked base is not repairable." },
|
|
168
|
+
],
|
|
169
|
+
featured: true,
|
|
170
|
+
keywords: ["takara", "takara beyblade", "plastic generation", "vintage beyblade"],
|
|
171
|
+
seoDescription: "Shop Takara-era Beyblade — the original 1999–2003 generations, from Spin Gear through HMS.",
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
slug: "beyblade",
|
|
175
|
+
name: "Beyblade",
|
|
176
|
+
description: "The spinning-top battle franchise itself, by Takara-Tomy in Japan and Hasbro internationally — spanning the Original series, Metal Fight, Burst and Beyblade X.",
|
|
177
|
+
country: "Japan",
|
|
178
|
+
founded: 1999,
|
|
179
|
+
website: "https://beyblade.takaratomy.co.jp",
|
|
180
|
+
highlights: [
|
|
181
|
+
"Four generations since 1999, all of them traded here",
|
|
182
|
+
"One of the best-selling spinning-top toy lines in the world",
|
|
183
|
+
"A live competitive tournament scene alongside collecting",
|
|
184
|
+
],
|
|
185
|
+
faqs: [
|
|
186
|
+
{ question: "What age range is Beyblade designed for?", answer: "Most sets are labelled 8+ for small parts and launcher spring mechanisms. Check the age rating on the listing before buying for a younger child." },
|
|
187
|
+
{ question: "Where can I find official tournament rules?", answer: "Takara-Tomy and Hasbro each publish rules for their own regions, and the World Beyblade Organization runs the community formats most Indian events use. The manufacturer link on this page goes to the current official rulebook." },
|
|
188
|
+
],
|
|
189
|
+
footer: true,
|
|
190
|
+
featured: true,
|
|
191
|
+
keywords: ["beyblade", "beyblade x", "beyblade burst", "spinning top battle", "beyblade india"],
|
|
192
|
+
seoDescription: "Shop Beyblade in India — Original, Metal Fight, Burst and Beyblade X tops, parts, launchers and stadiums.",
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
slug: "hasbro",
|
|
196
|
+
name: "Hasbro",
|
|
197
|
+
description: "The international Beyblade licensee. Hasbro distributes its own product line outside Japan with different packaging, different part names and occasionally different mould tolerances from the Takara-Tomy originals.",
|
|
198
|
+
country: "United States",
|
|
199
|
+
founded: 1923,
|
|
200
|
+
website: "https://shop.hasbro.com",
|
|
201
|
+
highlights: [
|
|
202
|
+
"The Beyblade line most collectors outside Japan grew up with",
|
|
203
|
+
"Widely available and generally cheaper than Japanese imports",
|
|
204
|
+
"Same-generation parts are usually cross-compatible with Takara-Tomy",
|
|
205
|
+
],
|
|
206
|
+
faqs: [
|
|
207
|
+
{ question: "Is a Hasbro Beyblade worse than the Takara-Tomy version?", answer: "Not worse, but often different. Hasbro releases can use softer plastics and slightly looser tolerances, which competitive players notice and casual players generally do not." },
|
|
208
|
+
{ question: "Why does my Hasbro top have a different name?", answer: "Hasbro renames most releases for western markets — Lost Longinus is sold as Lost Luinor L2, Spriggan as Spryzen. They are the same mould. Both names are indexed here, so either one finds the listing." },
|
|
209
|
+
],
|
|
210
|
+
keywords: ["hasbro", "hasbro beyblade", "beyblade burst hasbro", "luinor"],
|
|
211
|
+
seoDescription: "Shop Hasbro Beyblade — the international product line, with both Hasbro and Takara-Tomy names searchable.",
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
slug: "sonokong",
|
|
215
|
+
name: "Sonokong",
|
|
216
|
+
description: "The South Korean Beyblade licensee, distributing localised releases across Korea with its own packaging and occasional market-exclusive colourways.",
|
|
217
|
+
country: "South Korea",
|
|
218
|
+
founded: 1979,
|
|
219
|
+
highlights: [
|
|
220
|
+
"Korean-market releases, including colourways sold nowhere else",
|
|
221
|
+
"Same moulds as the Takara-Tomy originals under Korean packaging",
|
|
222
|
+
],
|
|
223
|
+
keywords: ["sonokong", "korean beyblade", "sonokong beyblade"],
|
|
224
|
+
seoDescription: "Shop Sonokong Beyblade — Korean-market releases and market-exclusive colourways.",
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
slug: "funskool",
|
|
228
|
+
name: "Funskool",
|
|
229
|
+
description: "The Indian licensee for several Hasbro lines, including locally packaged Beyblade releases — the version many Indian collectors owned first.",
|
|
230
|
+
country: "India",
|
|
231
|
+
founded: 1987,
|
|
232
|
+
highlights: [
|
|
233
|
+
"Indian-market packaging, and the release many local collectors started with",
|
|
234
|
+
"Locally distributed, so no import duty in the original purchase price",
|
|
235
|
+
],
|
|
236
|
+
faqs: [
|
|
237
|
+
{ question: "Is a Funskool Beyblade genuine?", answer: "Yes. Funskool is a licensed Indian distributor, not a reproduction — the product inside is the licensed release under Indian packaging." },
|
|
238
|
+
],
|
|
239
|
+
keywords: ["funskool", "funskool beyblade", "beyblade india original"],
|
|
240
|
+
seoDescription: "Shop Funskool Beyblade — the licensed Indian-market releases.",
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
slug: "young-toys",
|
|
244
|
+
name: "Young Toys",
|
|
245
|
+
description: "A Korean toy manufacturer and regional Beyblade licensee, also known for its own spinning-top lines.",
|
|
246
|
+
country: "South Korea",
|
|
247
|
+
highlights: ["Korean regional releases", "Also produces its own spinning-top lines"],
|
|
248
|
+
keywords: ["young toys", "young toys beyblade", "korean spinning tops"],
|
|
249
|
+
seoDescription: "Shop Young Toys releases — Korean regional Beyblade and spinning-top lines.",
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
slug: "newboy",
|
|
253
|
+
name: "NewBoy",
|
|
254
|
+
description: "The Middle East regional licensee, distributing Beyblade across the Gulf states with localised packaging.",
|
|
255
|
+
country: "United Arab Emirates",
|
|
256
|
+
highlights: ["Gulf-market packaging", "Licensed regional distribution, not a reproduction"],
|
|
257
|
+
keywords: ["newboy", "newboy beyblade", "middle east beyblade"],
|
|
258
|
+
seoDescription: "Shop NewBoy Beyblade — licensed Middle East regional releases.",
|
|
259
|
+
},
|
|
260
|
+
];
|
|
261
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
262
|
+
// Trading card publishers — FIVE
|
|
263
|
+
//
|
|
264
|
+
// 🛑 Nintendo and Creatures Inc. are deliberately absent despite co-owning
|
|
265
|
+
// Pokémon. Their names appear on no card a buyer searches by, so a row for
|
|
266
|
+
// either is trap 3: a card in the brands grid that opens an empty page.
|
|
267
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
268
|
+
const TCG_BRANDS = [
|
|
269
|
+
{
|
|
270
|
+
slug: "pokemon-company",
|
|
271
|
+
name: "The Pokémon Company",
|
|
272
|
+
description: "Publisher of the Pokémon Trading Card Game, and the marque on every modern Japanese and English set since Wizards of the Coast's licence ended in 2003.",
|
|
273
|
+
country: "Japan",
|
|
274
|
+
founded: 1998,
|
|
275
|
+
website: "https://www.pokemon.co.jp",
|
|
276
|
+
highlights: [
|
|
277
|
+
"Publishes every modern Pokémon TCG set in both Japanese and English",
|
|
278
|
+
"Japanese print runs are smaller and card stock is generally better regarded",
|
|
279
|
+
],
|
|
280
|
+
faqs: [
|
|
281
|
+
{ question: "Why do Japanese and English Pokémon cards differ in price?", answer: "Different print runs, different pull rates and a different collector base. Japanese sets often have higher card quality and smaller runs; English sets have the larger market. They are genuinely different products, which is why language is a filter here." },
|
|
282
|
+
],
|
|
283
|
+
footer: true,
|
|
284
|
+
featured: true,
|
|
285
|
+
keywords: ["pokemon company", "pokemon tcg", "pokemon cards india", "pokemon japanese"],
|
|
286
|
+
seoDescription: "Shop Pokémon Trading Card Game product — singles, sealed boxes and ETBs in Japanese and English.",
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
slug: "wizards-of-the-coast",
|
|
290
|
+
name: "Wizards of the Coast",
|
|
291
|
+
description: "Held the English-language Pokémon TCG licence from 1999 to 2003, and publishes Magic: The Gathering. WotC-era Pokémon cards are the vintage tier of the game.",
|
|
292
|
+
country: "United States",
|
|
293
|
+
founded: 1990,
|
|
294
|
+
website: "https://company.wizards.com",
|
|
295
|
+
highlights: [
|
|
296
|
+
"The 1999–2003 English Pokémon sets — Base Set through e-Card",
|
|
297
|
+
"A WotC copyright line on the card is the single fastest vintage check",
|
|
298
|
+
],
|
|
299
|
+
faqs: [
|
|
300
|
+
{ question: "How do I tell a WotC-era Pokémon card from a modern reprint?", answer: "The copyright line at the bottom names Wizards of the Coast and the year. A modern reprint of the same artwork carries The Pokémon Company instead, and the two are priced very differently." },
|
|
301
|
+
],
|
|
302
|
+
keywords: ["wizards of the coast", "wotc pokemon", "base set", "vintage pokemon cards"],
|
|
303
|
+
seoDescription: "Shop Wizards of the Coast-era Pokémon — the 1999–2003 English vintage sets.",
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
slug: "bandai",
|
|
307
|
+
name: "Bandai",
|
|
308
|
+
description: "Publisher of the One Piece Card Game, Digimon Card Game and Gundam Card Game, and — through Bandai Spirits — one of the largest collectible figure and model-kit makers in the world.",
|
|
309
|
+
country: "Japan",
|
|
310
|
+
founded: 1950,
|
|
311
|
+
website: "https://www.bandai.com",
|
|
312
|
+
highlights: [
|
|
313
|
+
"One Piece, Digimon and Gundam card games",
|
|
314
|
+
"Bandai Spirits figures and the entire Gunpla model-kit range",
|
|
315
|
+
"The broadest single catalogue of any publisher here",
|
|
316
|
+
],
|
|
317
|
+
footer: true,
|
|
318
|
+
featured: true,
|
|
319
|
+
keywords: ["bandai", "one piece card game", "gunpla", "digimon tcg", "bandai spirits"],
|
|
320
|
+
seoDescription: "Shop Bandai — One Piece and Digimon card games, Gunpla model kits and Bandai Spirits figures.",
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
slug: "konami",
|
|
324
|
+
name: "Konami",
|
|
325
|
+
description: "Publisher of the Yu-Gi-Oh! Trading Card Game worldwide.",
|
|
326
|
+
country: "Japan",
|
|
327
|
+
founded: 1969,
|
|
328
|
+
website: "https://www.konami.com",
|
|
329
|
+
highlights: ["Yu-Gi-Oh! TCG structure decks, boosters and singles"],
|
|
330
|
+
keywords: ["konami", "yu-gi-oh", "yugioh cards india"],
|
|
331
|
+
seoDescription: "Shop Konami's Yu-Gi-Oh! Trading Card Game — structure decks, boosters and singles.",
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
slug: "bushiroad",
|
|
335
|
+
name: "Bushiroad",
|
|
336
|
+
description: "Publisher of Weiss Schwarz and Union Arena — crossover card games that license dozens of anime properties into one playable system.",
|
|
337
|
+
country: "Japan",
|
|
338
|
+
founded: 2007,
|
|
339
|
+
website: "https://bushiroad.com",
|
|
340
|
+
highlights: [
|
|
341
|
+
"Weiss Schwarz and Union Arena",
|
|
342
|
+
"Crossover sets licensing dozens of anime properties into one game",
|
|
343
|
+
],
|
|
344
|
+
keywords: ["bushiroad", "weiss schwarz", "union arena"],
|
|
345
|
+
seoDescription: "Shop Bushiroad card games — Weiss Schwarz and Union Arena sealed product and singles.",
|
|
346
|
+
},
|
|
347
|
+
];
|
|
348
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
349
|
+
// Figure makers — THIRTEEN, ordered by their measured tag counts in the crawl
|
|
350
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
351
|
+
const FIGURE_BRANDS = [
|
|
352
|
+
{
|
|
353
|
+
slug: "banpresto",
|
|
354
|
+
name: "Banpresto",
|
|
355
|
+
description: "A Bandai Spirits label producing prize figures for Japanese arcade machines — the largest single figure line in the crawl, and the entry price point for collecting at scale.",
|
|
356
|
+
country: "Japan",
|
|
357
|
+
founded: 1977,
|
|
358
|
+
highlights: [
|
|
359
|
+
"Prize figures made for Japanese arcade machines, not retail",
|
|
360
|
+
"Usually unarticulated and genuinely cheaper rather than lower value",
|
|
361
|
+
"The broadest anime-figure selection at the ₹1,200–2,200 tier",
|
|
362
|
+
],
|
|
363
|
+
faqs: [
|
|
364
|
+
{ question: "Are Banpresto prize figures lower quality?", answer: "They are simpler — fewer parts, no articulation, less complex paint — and priced accordingly. For display they hold up well, which is why prize figures are a tier rather than a compromise." },
|
|
365
|
+
],
|
|
366
|
+
footer: true,
|
|
367
|
+
featured: true,
|
|
368
|
+
keywords: ["banpresto", "prize figure", "anime figure india"],
|
|
369
|
+
seoDescription: "Shop Banpresto prize figures — the broadest anime-figure selection at the entry tier.",
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
slug: "tamashii-nations",
|
|
373
|
+
name: "Tamashii Nations",
|
|
374
|
+
description: "Bandai Spirits' collector label, best known for S.H.Figuarts — highly articulated 1/12-scale figures aimed at adult collectors.",
|
|
375
|
+
country: "Japan",
|
|
376
|
+
founded: 2008,
|
|
377
|
+
highlights: ["S.H.Figuarts and the Tamashii collector lines", "The articulation benchmark at 1/12 scale"],
|
|
378
|
+
keywords: ["tamashii nations", "s.h.figuarts", "shf", "articulated figures"],
|
|
379
|
+
seoDescription: "Shop Tamashii Nations — S.H.Figuarts and the Bandai Spirits collector lines.",
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
slug: "max-factory",
|
|
383
|
+
name: "Max Factory",
|
|
384
|
+
description: "Japanese figure maker behind the Figma articulated line and a large catalogue of scale statues.",
|
|
385
|
+
country: "Japan",
|
|
386
|
+
founded: 1987,
|
|
387
|
+
highlights: ["The Figma articulated line", "Scale statues across a wide anime licence range"],
|
|
388
|
+
keywords: ["max factory", "figma", "anime figures"],
|
|
389
|
+
seoDescription: "Shop Max Factory — Figma articulated figures and scale statues.",
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
slug: "good-smile-company",
|
|
393
|
+
name: "Good Smile Company",
|
|
394
|
+
description: "Creator of the Nendoroid line — stylised chibi figures with swappable faces and parts — alongside a premium scale-statue catalogue.",
|
|
395
|
+
country: "Japan",
|
|
396
|
+
founded: 2001,
|
|
397
|
+
highlights: ["Nendoroid, the definitive chibi collectible line", "Swappable faces and parts on every Nendoroid"],
|
|
398
|
+
keywords: ["good smile company", "nendoroid", "chibi figure"],
|
|
399
|
+
seoDescription: "Shop Good Smile Company — Nendoroid chibi figures and premium scale statues.",
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
slug: "megahouse",
|
|
403
|
+
name: "MegaHouse",
|
|
404
|
+
description: "A Bandai Namco figure label known for its One Piece and Gundam scale statues.",
|
|
405
|
+
country: "Japan",
|
|
406
|
+
founded: 2001,
|
|
407
|
+
highlights: ["One Piece Portrait.Of.Pirates and Gundam scale lines"],
|
|
408
|
+
keywords: ["megahouse", "portrait of pirates", "one piece figure"],
|
|
409
|
+
seoDescription: "Shop MegaHouse figures — One Piece Portrait.Of.Pirates and Gundam scale statues.",
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
slug: "furyu",
|
|
413
|
+
name: "FuRyu",
|
|
414
|
+
description: "Japanese prize-figure and scale-figure maker across a broad anime licence range.",
|
|
415
|
+
country: "Japan",
|
|
416
|
+
founded: 2007,
|
|
417
|
+
highlights: ["Prize and scale figures at the mid tier"],
|
|
418
|
+
keywords: ["furyu", "anime prize figure"],
|
|
419
|
+
seoDescription: "Shop FuRyu figures — prize and scale anime collectibles.",
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
slug: "taito",
|
|
423
|
+
name: "Taito",
|
|
424
|
+
description: "Arcade operator and prize-figure maker, whose figures come from its own crane machines.",
|
|
425
|
+
country: "Japan",
|
|
426
|
+
founded: 1953,
|
|
427
|
+
highlights: ["Arcade prize figures from Taito's own machines"],
|
|
428
|
+
keywords: ["taito", "taito prize figure"],
|
|
429
|
+
seoDescription: "Shop Taito prize figures — arcade-exclusive anime collectibles.",
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
slug: "medicom-toy",
|
|
433
|
+
name: "Medicom Toy",
|
|
434
|
+
description: "Japanese maker behind Mafex — highly articulated 1/12-scale comic and film figures — and the Be@rbrick line.",
|
|
435
|
+
country: "Japan",
|
|
436
|
+
founded: 1996,
|
|
437
|
+
highlights: ["The Mafex articulated line", "Be@rbrick designer collectibles"],
|
|
438
|
+
keywords: ["medicom", "mafex", "bearbrick"],
|
|
439
|
+
seoDescription: "Shop Medicom Toy — Mafex articulated figures and Be@rbrick collectibles.",
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
slug: "toy-biz",
|
|
443
|
+
name: "Toy Biz",
|
|
444
|
+
description: "The pre-Hasbro Marvel licensee. Its 1990s figures are a genuine vintage tier, and an unopened Toy Biz card is one of the scarcer things in this catalogue.",
|
|
445
|
+
country: "United States",
|
|
446
|
+
founded: 1990,
|
|
447
|
+
highlights: [
|
|
448
|
+
"1990s Marvel figures — the vintage tier of comic collecting",
|
|
449
|
+
"Carded examples are scarce and priced well above loose ones",
|
|
450
|
+
],
|
|
451
|
+
faqs: [
|
|
452
|
+
{ question: "Why are Toy Biz figures collectible?", answer: "They are the Marvel figures a generation grew up with, they predate Hasbro's licence, and the cards were rarely kept. Condition of the blister and card drives most of the price." },
|
|
453
|
+
],
|
|
454
|
+
keywords: ["toy biz", "vintage marvel figures", "1990s marvel"],
|
|
455
|
+
seoDescription: "Shop Toy Biz — vintage 1990s Marvel figures, carded and loose.",
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
slug: "mcfarlane-toys",
|
|
459
|
+
name: "McFarlane Toys",
|
|
460
|
+
description: "Holder of the DC figure licence, producing the DC Multiverse line alongside sports and game properties.",
|
|
461
|
+
country: "United States",
|
|
462
|
+
founded: 1994,
|
|
463
|
+
highlights: ["DC Multiverse — the current DC figure line", "Sports and video-game licences alongside it"],
|
|
464
|
+
keywords: ["mcfarlane", "dc multiverse", "dc figures"],
|
|
465
|
+
seoDescription: "Shop McFarlane Toys — DC Multiverse figures and licensed sports and game lines.",
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
slug: "mattel",
|
|
469
|
+
name: "Mattel",
|
|
470
|
+
description: "American toy company behind Hot Wheels, the Pixar Cars die-cast line and a long history of licensed action figures.",
|
|
471
|
+
country: "United States",
|
|
472
|
+
founded: 1945,
|
|
473
|
+
website: "https://shop.mattel.com",
|
|
474
|
+
highlights: ["Hot Wheels and Pixar Cars", "A deep back catalogue of licensed figures"],
|
|
475
|
+
keywords: ["mattel", "pixar cars", "mattel figures"],
|
|
476
|
+
seoDescription: "Shop Mattel — Pixar Cars die-cast and licensed figure lines.",
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
slug: "hot-toys",
|
|
480
|
+
name: "Hot Toys",
|
|
481
|
+
description: "Hong Kong maker of 1/6-scale film collectibles with tailored fabric costumes and portrait likenesses — the premium ceiling of this catalogue.",
|
|
482
|
+
country: "Hong Kong",
|
|
483
|
+
founded: 2000,
|
|
484
|
+
highlights: ["1/6-scale film figures with fabric costumes", "The premium end of collectible figures"],
|
|
485
|
+
keywords: ["hot toys", "1/6 scale", "movie masterpiece"],
|
|
486
|
+
seoDescription: "Shop Hot Toys — 1/6-scale premium film collectibles.",
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
slug: "mezco",
|
|
490
|
+
name: "Mezco Toyz",
|
|
491
|
+
description: "American maker of the One:12 Collective — 1/12-scale figures with fabric costumes.",
|
|
492
|
+
country: "United States",
|
|
493
|
+
founded: 1999,
|
|
494
|
+
highlights: ["The One:12 Collective line at 1/12 scale with fabric costumes"],
|
|
495
|
+
keywords: ["mezco", "one 12 collective"],
|
|
496
|
+
seoDescription: "Shop Mezco Toyz — One:12 Collective figures.",
|
|
497
|
+
},
|
|
498
|
+
];
|
|
499
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
500
|
+
// Die-cast — ONE
|
|
501
|
+
//
|
|
502
|
+
// 🛑 Hot Wheels only, and it is the LINE rather than its parent company —
|
|
503
|
+
// matching the precedent `Beyblade` already set. The twenty other marques the
|
|
504
|
+
// crawl surfaced (Matchbox, Tomica, Mini GT, M2, Greenlight, Maisto, Kyosho …)
|
|
505
|
+
// are out of scope; their data stays in docs/research/ so re-adding one is a
|
|
506
|
+
// seed change and not another crawl.
|
|
507
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
508
|
+
const DIECAST_BRANDS = [
|
|
509
|
+
{
|
|
510
|
+
slug: "hot-wheels",
|
|
511
|
+
name: "Hot Wheels",
|
|
512
|
+
description: "Mattel's 1:64 die-cast line since 1968 — Mainline blister singles, Premium series with metal bases and Real Riders tyres, and the members-only Red Line Club.",
|
|
513
|
+
country: "United States",
|
|
514
|
+
founded: 1968,
|
|
515
|
+
website: "https://creations.mattel.com",
|
|
516
|
+
highlights: [
|
|
517
|
+
"Mainline, Premium and Red Line Club, all at 1:64",
|
|
518
|
+
"Treasure Hunt and Super Treasure Hunt chase variants identified on every listing",
|
|
519
|
+
"Indian-card releases flagged, because collectors here price them differently",
|
|
520
|
+
],
|
|
521
|
+
faqs: [
|
|
522
|
+
{ question: "What is a Super Treasure Hunt?", answer: "A chase variant within a mainline wave carrying Spectraflame paint, Real Riders rubber tyres and the TH logo — usually one per case. A regular Treasure Hunt has the flame-circle logo without the premium paint and tyres." },
|
|
523
|
+
{ question: "Why does the Indian blister card matter?", answer: "It is printed differently from the US release and collectors here value the two differently, so listings state which card a car is on rather than leaving you to compare photographs." },
|
|
524
|
+
],
|
|
525
|
+
footer: true,
|
|
526
|
+
featured: true,
|
|
527
|
+
keywords: ["hot wheels", "hot wheels india", "treasure hunt", "car culture", "diecast 1:64"],
|
|
528
|
+
seoDescription: "Shop Hot Wheels in India — Mainline, Premium, Red Line Club and chase variants at 1:64.",
|
|
529
|
+
},
|
|
530
|
+
];
|
|
531
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
532
|
+
// Living collectibles — ONE
|
|
533
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
534
|
+
const LIVING_BRANDS = [
|
|
535
|
+
{
|
|
536
|
+
slug: "independent-keepers",
|
|
537
|
+
name: "Independent Keepers",
|
|
538
|
+
description: "Live animals and plants come from individual keepers, breeders and growers rather than a manufacturer. This entry groups those listings so they are reachable from brand browsing like everything else.",
|
|
539
|
+
country: "India",
|
|
540
|
+
highlights: [
|
|
541
|
+
"Every seller is verified before a live listing can go public",
|
|
542
|
+
"Provenance, age and health information disclosed per listing",
|
|
543
|
+
],
|
|
544
|
+
faqs: [
|
|
545
|
+
{ question: "Why is there a \"brand\" for living things at all?", answer: "Purely so live listings behave like every other listing in browse and search. It identifies the class of seller, not a manufacturer." },
|
|
546
|
+
],
|
|
547
|
+
keywords: ["independent keepers", "breeders", "live plants"],
|
|
548
|
+
seoDescription: "Live animals and plants from verified independent keepers and growers.",
|
|
549
|
+
},
|
|
550
|
+
];
|
|
551
|
+
/** Declaration order is display order; `order` is assigned from it. */
|
|
552
|
+
export const BRAND_SEED_INPUTS = [
|
|
553
|
+
...BEYBLADE_BRANDS,
|
|
554
|
+
...TCG_BRANDS,
|
|
555
|
+
...FIGURE_BRANDS,
|
|
556
|
+
...DIECAST_BRANDS,
|
|
557
|
+
...LIVING_BRANDS,
|
|
558
|
+
];
|
|
559
|
+
export function buildBrandRows(stamps) {
|
|
560
|
+
const seen = new Set();
|
|
561
|
+
return BRAND_SEED_INPUTS.map((input, i) => {
|
|
562
|
+
const id = `brand-${input.slug}`;
|
|
563
|
+
/*
|
|
564
|
+
* 🛑 Fatal, not last-write-wins. A brand id derives from the slug, so two
|
|
565
|
+
* rows at one id write the first and SILENTLY overwrite it — and
|
|
566
|
+
* `appkit-seed status` cannot see it, because it counts ids and the id
|
|
567
|
+
* exists either way.
|
|
568
|
+
*/
|
|
569
|
+
if (seen.has(id))
|
|
570
|
+
throw new Error(`duplicate brand id ${id}`);
|
|
571
|
+
seen.add(id);
|
|
572
|
+
return brandRow(input, i + 1, stamps);
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
/** Asserted by the seed so a silently dropped row is loud. */
|
|
576
|
+
export const BRAND_ROW_COUNT = BRAND_SEED_INPUTS.length;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { CategoryDescriptionTemplate, CategoryPriceGuidance, CategoryProductDefaults, CategoryTemplateVariant } from "../../features/categories/schemas/category-content";
|
|
2
|
+
/**
|
|
3
|
+
* When the competitor crawl was taken. Fixed, never `new Date()` — a seed file
|
|
4
|
+
* is re-executed on every `appkit-seed` invocation, so a moving timestamp makes
|
|
5
|
+
* `load` non-idempotent (Root Cause #25).
|
|
6
|
+
*/
|
|
7
|
+
export declare const CRAWL_AS_OF: Date;
|
|
8
|
+
/**
|
|
9
|
+
* The five bodies, by variant.
|
|
10
|
+
*
|
|
11
|
+
* `placeholders` is deliberately LEFT ABSENT on all five: the field's contract
|
|
12
|
+
* is that absent means "re-parse", and `extractPlaceholders(body)` is the one
|
|
13
|
+
* implementation. Writing the list here by hand would be a second copy that
|
|
14
|
+
* drifts the first time a body is edited — and the failure mode is a published
|
|
15
|
+
* description containing a literal `{{series}}`.
|
|
16
|
+
*/
|
|
17
|
+
export declare const TEMPLATES: Record<CategoryTemplateVariant, CategoryDescriptionTemplate>;
|
|
18
|
+
/** The set a normal collectible category offers. */
|
|
19
|
+
export declare const COLLECTIBLE_TEMPLATES: CategoryDescriptionTemplate[];
|
|
20
|
+
/** Parts and small accessories arrive carded or loose, not boxed. */
|
|
21
|
+
export declare const PART_TEMPLATES: CategoryDescriptionTemplate[];
|
|
22
|
+
/** Sealed-only verticals (TCG sealed product, model kits) — no repro tier. */
|
|
23
|
+
export declare const SEALED_TEMPLATES: CategoryDescriptionTemplate[];
|
|
24
|
+
export declare function templateSet(...variants: CategoryTemplateVariant[]): CategoryDescriptionTemplate[];
|
|
25
|
+
export declare function marketBand(leafId: string): CategoryPriceGuidance | undefined;
|
|
26
|
+
/** Every leaf id this map claims a band for — the seed asserts they all exist. */
|
|
27
|
+
export declare const MARKET_BAND_LEAF_IDS: string[];
|
|
28
|
+
/** A complete top. */
|
|
29
|
+
export declare function beyDefaults(leafId: string, series: string, system: string): CategoryProductDefaults;
|
|
30
|
+
/** A loose component. */
|
|
31
|
+
export declare function partDefaults(leafId: string, partKind: string): CategoryProductDefaults;
|
|
32
|
+
export declare function launcherDefaults(leafId: string, series: string): CategoryProductDefaults;
|
|
33
|
+
export declare function stadiumDefaults(leafId: string, series: string): CategoryProductDefaults;
|
|
34
|
+
export declare function tcgDefaults(leafId: string, game: string, format: string): CategoryProductDefaults;
|
|
35
|
+
export declare function figureDefaults(leafId: string, scaleOrLine: string): CategoryProductDefaults;
|
|
36
|
+
export declare function diecastDefaults(leafId: string, line: string): CategoryProductDefaults;
|
|
37
|
+
export declare function accessoryDefaults(leafId: string, kind: string): CategoryProductDefaults;
|
|
38
|
+
/** Live animals and plants — exempt, and nothing about them is a toy. */
|
|
39
|
+
export declare function livingDefaults(): CategoryProductDefaults;
|