260 lines
4.7 KiB
Markdown
260 lines
4.7 KiB
Markdown
Nice, this is a **perfect use-case for Copilot AI Agent** 👍
|
||
Below is a **clean, copy-paste ready Markdown file** you can put straight into your repo (e.g. `.copilot/categories.md`) and tell Copilot to follow.
|
||
|
||
This is written **explicitly for an AI agent**: clear goals, constraints, SQL, Laravel expectations.
|
||
|
||
---
|
||
|
||
````markdown
|
||
# SkinBase – Category System (NEW SQL Structure)
|
||
|
||
This document defines the **new category & taxonomy system** for SkinBase.
|
||
Copilot AI Agent must follow this structure strictly and MUST NOT reuse legacy logic.
|
||
|
||
---
|
||
|
||
## 🎯 Goals
|
||
|
||
- SEO-friendly URLs (no IDs in public routes)
|
||
- Clear separation of content types (Photography, Skins, Wallpapers, etc.)
|
||
- Unlimited category nesting
|
||
- Laravel-friendly (Eloquent, migrations, relations)
|
||
- Ready for sitemap, breadcrumbs, translations
|
||
|
||
---
|
||
|
||
## 🚫 Legacy System (DO NOT USE)
|
||
|
||
The old table `artworks_categories` is deprecated.
|
||
|
||
DO NOT:
|
||
- use `section_id`
|
||
- use `rootid`
|
||
- use `num_artworks`
|
||
- expose IDs in URLs
|
||
- infer hierarchy from numeric hacks
|
||
|
||
---
|
||
|
||
## ✅ New Database Structure
|
||
|
||
### 1️⃣ content_types
|
||
|
||
Top-level sections (URL level 1)
|
||
|
||
```sql
|
||
CREATE TABLE content_types (
|
||
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||
name VARCHAR(64) NOT NULL,
|
||
slug VARCHAR(64) NOT NULL UNIQUE,
|
||
description TEXT NULL,
|
||
created_at TIMESTAMP NULL,
|
||
updated_at TIMESTAMP NULL
|
||
) ENGINE=InnoDB;
|
||
````
|
||
|
||
Examples:
|
||
|
||
* Photography → `photography`
|
||
* Skins → `skins`
|
||
* Wallpapers → `wallpapers`
|
||
|
||
Used in URLs as:
|
||
|
||
```
|
||
/photography
|
||
/skins
|
||
/wallpapers
|
||
```
|
||
|
||
---
|
||
|
||
### 2️⃣ categories
|
||
|
||
Hierarchical categories (unlimited depth)
|
||
|
||
```sql
|
||
CREATE TABLE categories (
|
||
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||
content_type_id INT UNSIGNED NOT NULL,
|
||
parent_id INT UNSIGNED NULL,
|
||
|
||
name VARCHAR(128) NOT NULL,
|
||
slug VARCHAR(128) NOT NULL,
|
||
|
||
description TEXT NULL,
|
||
image VARCHAR(255) NULL,
|
||
|
||
is_active BOOLEAN DEFAULT TRUE,
|
||
sort_order INT DEFAULT 0,
|
||
|
||
created_at TIMESTAMP NULL,
|
||
updated_at TIMESTAMP NULL,
|
||
|
||
UNIQUE KEY uniq_category_slug (content_type_id, slug),
|
||
FOREIGN KEY (content_type_id) REFERENCES content_types(id),
|
||
FOREIGN KEY (parent_id) REFERENCES categories(id) ON DELETE CASCADE
|
||
) ENGINE=InnoDB;
|
||
```
|
||
|
||
Hierarchy example:
|
||
|
||
```
|
||
Photography
|
||
├── Abstract
|
||
├── Comic
|
||
└── Dark
|
||
```
|
||
|
||
---
|
||
|
||
### 3️⃣ artwork_category (pivot)
|
||
|
||
```sql
|
||
CREATE TABLE artwork_category (
|
||
artwork_id INT UNSIGNED NOT NULL,
|
||
category_id INT UNSIGNED NOT NULL,
|
||
PRIMARY KEY (artwork_id, category_id),
|
||
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE
|
||
) ENGINE=InnoDB;
|
||
```
|
||
|
||
---
|
||
|
||
## 🧭 Routing Rules (MANDATORY)
|
||
|
||
Public URLs MUST use slugs only.
|
||
|
||
### Category pages
|
||
|
||
```
|
||
/{content_type}
|
||
/{content_type}/{category}
|
||
/{content_type}/{parent-category}/{category}
|
||
```
|
||
|
||
Examples:
|
||
|
||
```
|
||
/photography
|
||
/photography/abstract
|
||
/skins/desktop-shell
|
||
```
|
||
|
||
### Artwork pages
|
||
|
||
```
|
||
/photography/abstract/fresh-red-apple
|
||
/skins/darkstep/minimal-dark-pro
|
||
```
|
||
|
||
❌ Never expose numeric IDs in URLs.
|
||
|
||
---
|
||
|
||
## 🧠 Laravel Eloquent Relations
|
||
|
||
Copilot MUST generate models with these relations:
|
||
|
||
```php
|
||
ContentType hasMany Categories
|
||
Category belongsTo ContentType
|
||
Category hasMany Categories (children)
|
||
Category belongsTo Category (parent)
|
||
Artwork belongsToMany Categories
|
||
```
|
||
|
||
---
|
||
|
||
## 🔍 Querying Logic
|
||
|
||
Lookup must be done by slug, not ID.
|
||
|
||
Example:
|
||
|
||
```php
|
||
$contentType = ContentType::whereSlug($type)->firstOrFail();
|
||
$category = Category::whereSlug($slug)
|
||
->where('content_type_id', $contentType->id)
|
||
->firstOrFail();
|
||
```
|
||
|
||
---
|
||
|
||
## 📈 SEO Rules
|
||
|
||
* One canonical URL per category
|
||
* Breadcrumbs must reflect hierarchy
|
||
* Pagination via `?page=X`
|
||
* Filters MUST use query params and be `noindex`
|
||
|
||
---
|
||
|
||
## 📦 Migration
|
||
|
||
Legacy data has already been converted.
|
||
|
||
Migration SQL file:
|
||
|
||
```
|
||
/mnt/data/skinbase_categories_migration.sql
|
||
```
|
||
|
||
Copilot must NOT regenerate category data.
|
||
|
||
---
|
||
|
||
## ❗ Hard Rules for AI Agent
|
||
|
||
* DO NOT invent new tables
|
||
* DO NOT mix legacy and new schema
|
||
* DO NOT store counters in categories
|
||
* DO NOT assume only 2 levels of depth
|
||
* ALWAYS use slugs
|
||
|
||
---
|
||
|
||
## ✅ Result Expectation
|
||
|
||
After integration:
|
||
|
||
* SEO-clean URLs
|
||
* Stable taxonomy
|
||
* Easy sitemap generation
|
||
* Future-ready for translations
|
||
|
||
END OF SPEC
|
||
|
||
```
|
||
|
||
---
|
||
|
||
## ✅ How to use this
|
||
|
||
1. Save as:
|
||
```
|
||
|
||
.copilot/skinbase-categories.md
|
||
|
||
```
|
||
|
||
2. In VS Code Copilot Chat:
|
||
```
|
||
|
||
Use .copilot/skinbase-categories.md as the authoritative spec.
|
||
Integrate category system accordingly.
|
||
|
||
```
|
||
|
||
---
|
||
|
||
If you want next, I can:
|
||
- ✍️ generate **Laravel migrations**
|
||
- 🧠 generate **Eloquent models**
|
||
- 🧭 generate **routes + controllers**
|
||
- 🔁 generate **301 redirect mapping**
|
||
- 🗺 generate **XML sitemap logic**
|
||
|
||
Just tell me what Copilot should build next 🚀
|
||
```
|