musaw commited on
Commit
7d9f55b
·
1 Parent(s): 9003457

release(v1): clean docs structure and modernize search UX

Browse files
.github/release_template.md CHANGED
@@ -1,23 +1,28 @@
1
  ## Summary
 
2
  - What changed in this release.
3
 
4
  ## Highlights
 
5
  - Data:
6
  - ASR:
7
  - TTS:
8
  - Benchmarks:
9
- - Docs/Tooling:
10
 
11
  ## Validation
 
12
  - Link check: `python scripts/check_links.py`
13
  - Normalization check: `python scripts/validate_normalization.py data/processed/normalization_seed_v0.1.tsv`
 
14
  - Tests: `python -m pytest -q` (if available)
15
 
16
  ## Known Limitations
 
17
  - List current caveats.
18
 
19
  ## References
 
20
  - Changelog: [CHANGELOG.md](../CHANGELOG.md)
21
  - Release checklist: [docs/release_checklist.md](../docs/release_checklist.md)
22
- - Release notes draft v0.1.1: [docs/release_v0.1.1.md](../docs/release_v0.1.1.md)
23
- - Release notes draft v0.1.2: [docs/release_v0.1.2.md](../docs/release_v0.1.2.md)
 
1
  ## Summary
2
+
3
  - What changed in this release.
4
 
5
  ## Highlights
6
+
7
  - Data:
8
  - ASR:
9
  - TTS:
10
  - Benchmarks:
11
+ - Docs and Tooling:
12
 
13
  ## Validation
14
+
15
  - Link check: `python scripts/check_links.py`
16
  - Normalization check: `python scripts/validate_normalization.py data/processed/normalization_seed_v0.1.tsv`
17
+ - Resource catalog check: `python scripts/validate_resource_catalog.py`
18
  - Tests: `python -m pytest -q` (if available)
19
 
20
  ## Known Limitations
21
+
22
  - List current caveats.
23
 
24
  ## References
25
+
26
  - Changelog: [CHANGELOG.md](../CHANGELOG.md)
27
  - Release checklist: [docs/release_checklist.md](../docs/release_checklist.md)
28
+ - Release notes index: [docs/releases/README.md](../docs/releases/README.md)
 
CHANGELOG.md CHANGED
@@ -3,21 +3,33 @@
3
  All notable changes to this project will be documented in this file.
4
 
5
  The format is inspired by [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
6
- and this project uses milestone-style tags (for example `v0.1`, `v0.2`).
7
 
8
  ## [Unreleased]
9
  ### Added
10
- - Hugging Face model-card metadata at the top of `README.md`.
11
- - GitHub topics checklist (`docs/github_topics_checklist.md`).
12
- - Backlink strategy plan (`docs/backlink_strategy.md`).
13
- - SEO intent landing pages for Pashto datasets, ASR, and TTS.
14
- - Release note drafts for `v0.1.1` and `v0.1.2`.
15
 
16
  ### Changed
17
- - Expanded documentation map to include SEO operations and intent pages.
18
 
19
  ### Fixed
20
- - Finalized hardcoded URL coverage for the `pashto-language-resources` slug across docs and release notes.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  ## [v0.1] - 2026-02-14
23
  ### Added
@@ -25,3 +37,4 @@ and this project uses milestone-style tags (for example `v0.1`, `v0.2`).
25
  - Structured `resources/` folder for datasets, models, benchmarks, and tools.
26
  - Link-check script and normalization-validator tests.
27
  - Documentation hub and model/release/process guidance.
 
 
3
  All notable changes to this project will be documented in this file.
4
 
5
  The format is inspired by [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
6
+ and this project uses semantic version tags (for example `v1.0.0`, `v1.0.1`).
7
 
8
  ## [Unreleased]
9
  ### Added
10
+ - None yet.
 
 
 
 
11
 
12
  ### Changed
13
+ - None yet.
14
 
15
  ### Fixed
16
+ - None yet.
17
+
18
+ ## [v1.0.0] - 2026-02-18
19
+ ### Added
20
+ - Release notes index under `docs/releases/` with `docs/releases/v1.0.0.md`.
21
+ - Improved discoverability assets: topics checklist, backlink strategy, and intent landing pages.
22
+ - Hugging Face model-card metadata in `README.md`.
23
+
24
+ ### Changed
25
+ - Cleaned and restructured README and docs navigation for lower redundancy.
26
+ - Modernized `docs/search/index.html` with stronger UI/UX and interaction patterns.
27
+ - Standardized release process and checklist around semantic versioning.
28
+ - Updated package and citation metadata to `1.0.0`.
29
+
30
+ ### Fixed
31
+ - Removed stale draft release-note references from documentation and templates.
32
+ - Finalized hardcoded URL usage for the `pashto-language-resources` slug.
33
 
34
  ## [v0.1] - 2026-02-14
35
  ### Added
 
37
  - Structured `resources/` folder for datasets, models, benchmarks, and tools.
38
  - Link-check script and normalization-validator tests.
39
  - Documentation hub and model/release/process guidance.
40
+
CITATION.cff CHANGED
@@ -2,7 +2,8 @@ cff-version: 1.2.0
2
  message: "If you use this repository, please cite it."
3
  title: "Pashto Language Resources Hub (Pukhto/Pashto)"
4
  type: software
5
- version: 0.1.0
 
6
  license: Apache-2.0
7
  repository-code: "https://github.com/Musawer1214/pashto-language-resources"
8
  url: "https://github.com/Musawer1214/pashto-language-resources"
@@ -18,4 +19,3 @@ keywords:
18
  - NLP
19
  - machine translation
20
  - language resources
21
-
 
2
  message: "If you use this repository, please cite it."
3
  title: "Pashto Language Resources Hub (Pukhto/Pashto)"
4
  type: software
5
+ version: 1.0.0
6
+ date-released: 2026-02-18
7
  license: Apache-2.0
8
  repository-code: "https://github.com/Musawer1214/pashto-language-resources"
9
  url: "https://github.com/Musawer1214/pashto-language-resources"
 
19
  - NLP
20
  - machine translation
21
  - language resources
 
README.md CHANGED
@@ -18,111 +18,66 @@ tags:
18
 
19
  # Pashto Language Resources Hub (Pukhto/Pashto)
20
 
21
- Open-source repository for Pashto language technology resources: datasets, models, benchmarks, ASR, TTS, NLP, and machine translation (MT).
22
 
23
- This project curates verified Pashto resources and maintains reproducible tooling for discovery, validation, and documentation.
24
 
25
- ## Start Here
26
 
27
- - Main resource search: [Pashto Resource Search](https://musawer1214.github.io/pashto-language-resources/search/)
28
  - Project site: [Pashto Language Resources Hub](https://musawer1214.github.io/pashto-language-resources/)
29
- - GitHub repository: [Musawer1214/pashto-language-resources](https://github.com/Musawer1214/pashto-language-resources)
 
30
  - Hugging Face mirror: [Musawer14/pashto-language-resources](https://huggingface.co/Musawer14/pashto-language-resources)
31
 
32
- ## If You Searched For
33
 
34
- This repository is relevant to these search intents:
 
 
35
 
36
- - Pashto datasets
37
- - Pashto ASR model
38
- - Pashto TTS resources
39
- - Pashto NLP benchmark
40
- - Pashto machine translation resources
41
- - Pukhto language technology
42
- - Pushto AI resources
43
 
44
- ## Current Scope
 
 
 
 
 
 
45
 
46
- - Build open Pashto datasets, benchmarks, and model references for ASR, TTS, NLP, and MT.
47
- - Track practical tools, apps, and academic papers for Pashto integration in technology.
48
- - Keep everything transparent, reproducible, and contribution-friendly.
49
 
50
- ## Resource System
 
 
51
 
52
- Machine-readable and searchable resource pipeline:
53
-
54
- - Canonical catalog: [resources/catalog/resources.json](resources/catalog/resources.json)
55
- - Catalog schema: [resources/schema/resource.schema.json](resources/schema/resource.schema.json)
56
- - Candidate feed (auto-generated): [resources/catalog/pending_candidates.json](resources/catalog/pending_candidates.json)
57
- - Search UI source: [docs/search/index.html](docs/search/index.html)
58
- - Search data export: [docs/search/resources.json](docs/search/resources.json)
59
- - Resource index docs: [docs/resource_catalog.md](docs/resource_catalog.md)
60
- - Automation docs: [docs/resource_automation.md](docs/resource_automation.md)
61
- - Cycle runbook: [docs/resource_cycle_runbook.md](docs/resource_cycle_runbook.md)
62
-
63
- ## How New Resources Are Added
64
-
65
- 1. Auto discovery runs daily from `.github/workflows/resource_sync.yml` and updates `resources/catalog/pending_candidates.json` in a review PR.
66
- 2. Manual review checks quality, Pashto evidence, and license compatibility before promoting entries into `resources/catalog/resources.json` with `status: verified`.
67
- 3. Regeneration and validation runs `python scripts/validate_resource_catalog.py` and `python scripts/generate_resource_views.py`, then commits generated updates.
68
-
69
- Shortcut wrapper:
70
- - `python scripts/run_resource_cycle.py --limit 25`
71
-
72
- ## Quickstart
73
 
74
  ```bash
75
- python -m pip install -e ".[dev]"
76
  python scripts/validate_resource_catalog.py
77
  python scripts/generate_resource_views.py
78
  python scripts/check_links.py
79
  python -m pytest -q
80
  ```
81
 
82
- ## Discoverability And SEO
83
 
84
- - Playbook: [docs/discoverability_seo.md](docs/discoverability_seo.md)
85
- - Docs hub: [docs/README.md](docs/README.md)
86
- - Resource search page: [docs/search/index.html](docs/search/index.html)
87
- - Citation metadata: [CITATION.cff](CITATION.cff)
88
- - Platform sync policy: [docs/platform_sync_policy.md](docs/platform_sync_policy.md)
89
  - GitHub topics checklist: [docs/github_topics_checklist.md](docs/github_topics_checklist.md)
90
  - Backlink strategy: [docs/backlink_strategy.md](docs/backlink_strategy.md)
91
- - Intent page: [Pashto datasets](docs/pashto_datasets.md)
92
- - Intent page: [Pashto ASR](docs/pashto_asr.md)
93
- - Intent page: [Pashto TTS](docs/pashto_tts.md)
94
- - Release notes: [v0.1.1](docs/release_v0.1.1.md)
95
- - Release notes: [v0.1.2](docs/release_v0.1.2.md)
96
-
97
- ## Documentation Map
98
-
99
- - Purpose: [PROJECT_PURPOSE.md](PROJECT_PURPOSE.md)
100
- - Contributing: [CONTRIBUTING.md](CONTRIBUTING.md)
101
- - Roadmap: [ROADMAP.md](ROADMAP.md)
102
- - Governance: [GOVERNANCE.md](GOVERNANCE.md)
103
- - License policy: [LICENSE_POLICY.md](LICENSE_POLICY.md)
104
  - Changelog: [CHANGELOG.md](CHANGELOG.md)
105
- - Community: [community/COMMUNICATION.md](community/COMMUNICATION.md)
106
- - Docs hub: [docs/README.md](docs/README.md)
107
- - Resource index: [docs/resource_catalog.md](docs/resource_catalog.md)
108
- - Resource automation: [docs/resource_automation.md](docs/resource_automation.md)
109
-
110
- ## Resource Sections
111
-
112
- - Datasets: [resources/datasets/README.md](resources/datasets/README.md)
113
- - Models: [resources/models/README.md](resources/models/README.md)
114
- - Benchmarks: [resources/benchmarks/README.md](resources/benchmarks/README.md)
115
- - Tools: [resources/tools/README.md](resources/tools/README.md)
116
- - Papers: [resources/papers/README.md](resources/papers/README.md)
117
- - Projects: [resources/projects/README.md](resources/projects/README.md)
118
- - Code: [resources/codes/README.md](resources/codes/README.md)
119
-
120
- ## Workspaces
121
-
122
- - [data/](data/README.md): datasets, curation, metadata, quality
123
- - [asr/](asr/README.md): ASR baselines and experiments
124
- - [tts/](tts/README.md): TTS baselines and experiments
125
- - [benchmarks/](benchmarks/README.md): benchmark sets and evaluation
126
- - [experiments/](experiments/README.md): reproducible run cards
127
- - [apps/desktop/](apps/desktop/README.md): user-facing integration references
128
- - [models/](models/README.md): model layout and release conventions
 
18
 
19
  # Pashto Language Resources Hub (Pukhto/Pashto)
20
 
21
+ Open-source Pashto language technology hub for datasets, models, benchmarks, ASR, TTS, NLP, and machine translation.
22
 
23
+ This repository curates verified Pashto resources and keeps validation and publishing workflows reproducible.
24
 
25
+ ## Quick Links
26
 
27
+ - Search page: [Pashto Resource Search](https://musawer1214.github.io/pashto-language-resources/search/)
28
  - Project site: [Pashto Language Resources Hub](https://musawer1214.github.io/pashto-language-resources/)
29
+ - Documentation hub: [docs/README.md](docs/README.md)
30
+ - GitHub: [Musawer1214/pashto-language-resources](https://github.com/Musawer1214/pashto-language-resources)
31
  - Hugging Face mirror: [Musawer14/pashto-language-resources](https://huggingface.co/Musawer14/pashto-language-resources)
32
 
33
+ ## High-Intent Pages
34
 
35
+ - [Pashto datasets](docs/pashto_datasets.md)
36
+ - [Pashto ASR resources](docs/pashto_asr.md)
37
+ - [Pashto TTS resources](docs/pashto_tts.md)
38
 
39
+ ## Repository Structure
 
 
 
 
 
 
40
 
41
+ - `resources/`: verified external resources with structured categories.
42
+ - `data/`: normalization seeds, metadata, and data workflows.
43
+ - `asr/`: ASR notes, baselines, and references.
44
+ - `tts/`: TTS notes, baselines, and references.
45
+ - `benchmarks/`: schemas, result templates, and evaluation guidance.
46
+ - `experiments/`: reproducible run-card templates.
47
+ - `docs/`: SEO, release, platform, and contribution documentation.
48
 
49
+ ## Resource Workflow
 
 
50
 
51
+ 1. Discovery job (`.github/workflows/resource_sync.yml`) updates candidate feed.
52
+ 2. Maintainer review promotes high-quality entries to `resources/catalog/resources.json`.
53
+ 3. Regeneration and validation updates derived views and search index.
54
 
55
+ Core commands:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
  ```bash
 
58
  python scripts/validate_resource_catalog.py
59
  python scripts/generate_resource_views.py
60
  python scripts/check_links.py
61
  python -m pytest -q
62
  ```
63
 
64
+ ## SEO and Discoverability
65
 
66
+ - SEO playbook: [docs/discoverability_seo.md](docs/discoverability_seo.md)
 
 
 
 
67
  - GitHub topics checklist: [docs/github_topics_checklist.md](docs/github_topics_checklist.md)
68
  - Backlink strategy: [docs/backlink_strategy.md](docs/backlink_strategy.md)
69
+ - Platform sync policy: [docs/platform_sync_policy.md](docs/platform_sync_policy.md)
70
+ - Search UI source: [docs/search/index.html](docs/search/index.html)
71
+ - Citation metadata: [CITATION.cff](CITATION.cff)
72
+
73
+ ## Releases
74
+
75
+ - Release notes index: [docs/releases/README.md](docs/releases/README.md)
76
+ - Latest release notes: [v1.0.0](docs/releases/v1.0.0.md)
 
 
 
 
 
77
  - Changelog: [CHANGELOG.md](CHANGELOG.md)
78
+
79
+ ## Contributing
80
+
81
+ - Contribution guide: [CONTRIBUTING.md](CONTRIBUTING.md)
82
+ - Community communication: [community/COMMUNICATION.md](community/COMMUNICATION.md)
83
+ - Resource guidelines: [docs/dataset_guidelines.md](docs/dataset_guidelines.md)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
docs/README.md CHANGED
@@ -1,8 +1,9 @@
1
  # Documentation Hub
2
 
3
- This folder is the main documentation entry point for contributors.
 
 
4
 
5
- ## Start here
6
  - Project purpose: [../PROJECT_PURPOSE.md](../PROJECT_PURPOSE.md)
7
  - Contributing guide: [../CONTRIBUTING.md](../CONTRIBUTING.md)
8
  - Governance: [../GOVERNANCE.md](../GOVERNANCE.md)
@@ -10,45 +11,40 @@ This folder is the main documentation entry point for contributors.
10
  - Roadmap: [../ROADMAP.md](../ROADMAP.md)
11
  - Changelog: [../CHANGELOG.md](../CHANGELOG.md)
12
 
13
- ## Core documentation
14
- - Workstreams: [workstreams.md](workstreams.md)
15
- - Dataset guidelines: [dataset_guidelines.md](dataset_guidelines.md)
16
- - Pashto normalization policy: [pashto_normalization_v0.1.md](pashto_normalization_v0.1.md)
17
- - Common Voice Pashto integration: [common_voice_pashto_24.md](common_voice_pashto_24.md)
18
- - Discoverability and SEO playbook: [discoverability_seo.md](discoverability_seo.md)
19
- - Platform sync policy: [platform_sync_policy.md](platform_sync_policy.md)
20
  - GitHub topics checklist: [github_topics_checklist.md](github_topics_checklist.md)
21
  - Backlink strategy: [backlink_strategy.md](backlink_strategy.md)
 
 
 
 
 
 
 
 
 
 
 
22
  - Release process: [release_process.md](release_process.md)
23
  - Release checklist: [release_checklist.md](release_checklist.md)
 
24
  - Platforms and publish flow: [platforms.md](platforms.md)
 
25
  - GitHub operations: [github_operations.md](github_operations.md)
26
- - Resource automation: [resource_automation.md](resource_automation.md)
27
- - Resource cycle runbook: [resource_cycle_runbook.md](resource_cycle_runbook.md)
28
 
29
- ## Intent landing pages
30
- - Pashto datasets page: [pashto_datasets.md](pashto_datasets.md)
31
- - Pashto ASR page: [pashto_asr.md](pashto_asr.md)
32
- - Pashto TTS page: [pashto_tts.md](pashto_tts.md)
33
 
34
- ## Release notes
35
- - v0.1.1 draft notes: [release_v0.1.1.md](release_v0.1.1.md)
36
- - v0.1.2 draft notes: [release_v0.1.2.md](release_v0.1.2.md)
37
-
38
- ## Resource tracking
39
- - Master resource index: [resource_catalog.md](resource_catalog.md)
40
- - GitHub Pages search: [search/index.html](search/index.html)
41
  - Structured resources folder: [../resources/README.md](../resources/README.md)
42
 
43
  ## Tooling
 
44
  - Scripts overview: [../scripts/README.md](../scripts/README.md)
45
  - Link checker: [../scripts/check_links.py](../scripts/check_links.py)
46
  - Resource catalog validator: [../scripts/validate_resource_catalog.py](../scripts/validate_resource_catalog.py)
47
  - Resource view generator: [../scripts/generate_resource_views.py](../scripts/generate_resource_views.py)
48
  - Candidate sync script: [../scripts/sync_resources.py](../scripts/sync_resources.py)
49
  - Normalization validator: [../scripts/validate_normalization.py](../scripts/validate_normalization.py)
50
-
51
- ## Evaluation and experiments
52
- - Benchmark result format: [../benchmarks/results/README.md](../benchmarks/results/README.md)
53
- - Benchmark schema: [../benchmarks/schema/benchmark_result.schema.json](../benchmarks/schema/benchmark_result.schema.json)
54
- - Experiment run cards: [../experiments/README.md](../experiments/README.md)
 
1
  # Documentation Hub
2
 
3
+ This folder is the main documentation entry point for contributors and maintainers.
4
+
5
+ ## Project Foundations
6
 
 
7
  - Project purpose: [../PROJECT_PURPOSE.md](../PROJECT_PURPOSE.md)
8
  - Contributing guide: [../CONTRIBUTING.md](../CONTRIBUTING.md)
9
  - Governance: [../GOVERNANCE.md](../GOVERNANCE.md)
 
11
  - Roadmap: [../ROADMAP.md](../ROADMAP.md)
12
  - Changelog: [../CHANGELOG.md](../CHANGELOG.md)
13
 
14
+ ## Discovery and SEO
15
+
16
+ - Discoverability playbook: [discoverability_seo.md](discoverability_seo.md)
 
 
 
 
17
  - GitHub topics checklist: [github_topics_checklist.md](github_topics_checklist.md)
18
  - Backlink strategy: [backlink_strategy.md](backlink_strategy.md)
19
+ - Search UI: [search/index.html](search/index.html)
20
+ - Resource catalog docs: [resource_catalog.md](resource_catalog.md)
21
+
22
+ ## Intent Landing Pages
23
+
24
+ - Pashto datasets: [pashto_datasets.md](pashto_datasets.md)
25
+ - Pashto ASR resources: [pashto_asr.md](pashto_asr.md)
26
+ - Pashto TTS resources: [pashto_tts.md](pashto_tts.md)
27
+
28
+ ## Release and Platform Operations
29
+
30
  - Release process: [release_process.md](release_process.md)
31
  - Release checklist: [release_checklist.md](release_checklist.md)
32
+ - Release notes index: [releases/README.md](releases/README.md)
33
  - Platforms and publish flow: [platforms.md](platforms.md)
34
+ - Platform sync policy: [platform_sync_policy.md](platform_sync_policy.md)
35
  - GitHub operations: [github_operations.md](github_operations.md)
 
 
36
 
37
+ ## Resource Automation
 
 
 
38
 
39
+ - Resource automation: [resource_automation.md](resource_automation.md)
40
+ - Resource cycle runbook: [resource_cycle_runbook.md](resource_cycle_runbook.md)
 
 
 
 
 
41
  - Structured resources folder: [../resources/README.md](../resources/README.md)
42
 
43
  ## Tooling
44
+
45
  - Scripts overview: [../scripts/README.md](../scripts/README.md)
46
  - Link checker: [../scripts/check_links.py](../scripts/check_links.py)
47
  - Resource catalog validator: [../scripts/validate_resource_catalog.py](../scripts/validate_resource_catalog.py)
48
  - Resource view generator: [../scripts/generate_resource_views.py](../scripts/generate_resource_views.py)
49
  - Candidate sync script: [../scripts/sync_resources.py](../scripts/sync_resources.py)
50
  - Normalization validator: [../scripts/validate_normalization.py](../scripts/validate_normalization.py)
 
 
 
 
 
docs/discoverability_seo.md CHANGED
@@ -3,7 +3,7 @@
3
  This playbook focuses on making the repository easier to find in:
4
 
5
  - GitHub search
6
- - Google/Bing search
7
  - Academic and resource discovery channels
8
 
9
  ## 1) Repository Slug Status
@@ -28,7 +28,7 @@ Set these in repository `Settings -> General` and About panel:
28
  - Description:
29
  - `Open-source Pashto (Pukhto/Pashto) datasets, ASR, TTS, NLP, MT, models, and benchmark resources.`
30
  - Website:
31
- - [GitHub Pages home](https://musawer1214.github.io/pashto-language-resources/) (final slug)
32
  - Topics:
33
  - `pashto`
34
  - `pukhto`
@@ -45,7 +45,7 @@ Set these in repository `Settings -> General` and About panel:
45
 
46
  - Keep the first 160 characters of `README.md` keyword clear.
47
  - Use consistent terminology across pages: `Pashto (Pukhto/Pushto)`.
48
- - Publish regular updates in `CHANGELOG.md` and GitHub Releases.
49
  - Keep `CITATION.cff` updated for scholarly reuse and citation.
50
 
51
  ## 4) Pages SEO and Crawlability
@@ -61,19 +61,21 @@ Keep these updated when renaming slug or domain.
61
  ## 5) External Discovery Boost
62
 
63
  - Add the GitHub Pages search URL to:
64
- - Hugging Face model/dataset cards
65
  - Relevant community profiles and README links
66
- - Conference/demo pages for Pashto language technology
67
  - Ask contributors to link specific resource pages in blog posts or papers.
68
 
69
- ## SEO Operation Assets
70
 
71
  - GitHub topics checklist: [github_topics_checklist.md](github_topics_checklist.md)
72
  - Backlink strategy: [backlink_strategy.md](backlink_strategy.md)
73
  - Intent page: [Pashto datasets](pashto_datasets.md)
74
  - Intent page: [Pashto ASR](pashto_asr.md)
75
  - Intent page: [Pashto TTS](pashto_tts.md)
76
- ## 6) Indexing Checklist (After Push)
 
 
77
 
78
  1. Push all changes to `main`.
79
  2. Verify GitHub Pages is serving:
@@ -88,5 +90,3 @@ Keep these updated when renaming slug or domain.
88
  - Home page
89
  - Search page
90
  6. Recheck search visibility after 1 to 3 weeks.
91
-
92
-
 
3
  This playbook focuses on making the repository easier to find in:
4
 
5
  - GitHub search
6
+ - Google and Bing search
7
  - Academic and resource discovery channels
8
 
9
  ## 1) Repository Slug Status
 
28
  - Description:
29
  - `Open-source Pashto (Pukhto/Pashto) datasets, ASR, TTS, NLP, MT, models, and benchmark resources.`
30
  - Website:
31
+ - [GitHub Pages home](https://musawer1214.github.io/pashto-language-resources/)
32
  - Topics:
33
  - `pashto`
34
  - `pukhto`
 
45
 
46
  - Keep the first 160 characters of `README.md` keyword clear.
47
  - Use consistent terminology across pages: `Pashto (Pukhto/Pushto)`.
48
+ - Publish updates through `CHANGELOG.md` and release notes in `docs/releases/`.
49
  - Keep `CITATION.cff` updated for scholarly reuse and citation.
50
 
51
  ## 4) Pages SEO and Crawlability
 
61
  ## 5) External Discovery Boost
62
 
63
  - Add the GitHub Pages search URL to:
64
+ - Hugging Face model and dataset cards
65
  - Relevant community profiles and README links
66
+ - Conference or demo pages for Pashto language technology
67
  - Ask contributors to link specific resource pages in blog posts or papers.
68
 
69
+ ## 6) SEO Operation Assets
70
 
71
  - GitHub topics checklist: [github_topics_checklist.md](github_topics_checklist.md)
72
  - Backlink strategy: [backlink_strategy.md](backlink_strategy.md)
73
  - Intent page: [Pashto datasets](pashto_datasets.md)
74
  - Intent page: [Pashto ASR](pashto_asr.md)
75
  - Intent page: [Pashto TTS](pashto_tts.md)
76
+ - Release notes index: [releases/README.md](releases/README.md)
77
+
78
+ ## 7) Indexing Checklist (After Push)
79
 
80
  1. Push all changes to `main`.
81
  2. Verify GitHub Pages is serving:
 
90
  - Home page
91
  - Search page
92
  6. Recheck search visibility after 1 to 3 weeks.
 
 
docs/index.md CHANGED
@@ -8,35 +8,25 @@ description: Open-source Pashto (Pukhto/Pashto) datasets, models, benchmarks, AS
8
 
9
  `pashto-language-resources` is a community-led open-source project focused on making Pashto (also written as Pukhto/Pushto) a first-class language in speech and language AI.
10
 
 
 
 
 
 
 
11
  ## Mission
12
 
13
  - Build open Pashto datasets and resource indexes for ASR, TTS, NLP, and MT.
14
  - Publish reproducible baseline models, benchmark schemas, and evaluation workflows.
15
  - Keep progress transparent, contributor-friendly, and public-benefit oriented.
16
 
17
- ## What Is In This Repository
18
-
19
- - `data/`: dataset workflows, metadata, and normalization seeds.
20
- - `asr/`: ASR baselines and experiment notes.
21
- - `tts/`: TTS baselines and quality tracking.
22
- - `benchmarks/`: benchmark schema, result format, and metric guidance.
23
- - `experiments/`: reproducible run cards and experiment records.
24
- - `docs/`: policies, roadmap, release process, and operating guides.
25
- - `resources/`: verified external Pashto datasets, models, tools, benchmarks, and papers.
26
-
27
- ## Search Pashto Resources
28
-
29
- - Search UI: [Pashto Resource Search](search/)
30
- - Resource index docs: [resource_catalog.md](resource_catalog.md)
31
- - Machine-readable catalog (GitHub): [resources.json source](https://github.com/Musawer1214/pashto-language-resources/blob/main/resources/catalog/resources.json)
32
-
33
  ## Intent Pages
34
 
35
  - Pashto datasets: [pashto_datasets.md](pashto_datasets.md)
36
  - Pashto ASR resources: [pashto_asr.md](pashto_asr.md)
37
  - Pashto TTS resources: [pashto_tts.md](pashto_tts.md)
38
 
39
- ## Project References
40
 
41
  - Repository: [Musawer1214/pashto-language-resources](https://github.com/Musawer1214/pashto-language-resources)
42
  - Hugging Face: [Musawer14/pashto-language-resources](https://huggingface.co/Musawer14/pashto-language-resources)
@@ -46,30 +36,24 @@ description: Open-source Pashto (Pukhto/Pashto) datasets, models, benchmarks, AS
46
 
47
  ## SEO Operations
48
 
 
49
  - GitHub topics checklist: [github_topics_checklist.md](github_topics_checklist.md)
50
  - Backlink strategy: [backlink_strategy.md](backlink_strategy.md)
51
- - Release notes v0.1.1: [release_v0.1.1.md](release_v0.1.1.md)
52
- - Release notes v0.1.2: [release_v0.1.2.md](release_v0.1.2.md)
53
 
54
- ## Contributing
 
 
 
 
 
 
55
 
56
  You can help by improving documentation, validating normalization rows, sharing verified resources, or contributing data, model, and evaluation workflows.
57
 
58
- For contributor workflow and standards, start at:
59
  - [docs/README.md](README.md)
60
  - [community/COMMUNICATION.md](../community/COMMUNICATION.md)
61
 
62
- ## Search Terms
63
-
64
- This project is relevant to searches like:
65
-
66
- - Pashto datasets
67
- - Pashto ASR model
68
- - Pashto TTS resources
69
- - Pashto NLP benchmark
70
- - Pashto language technology
71
- - Pukhto language resources
72
-
73
  ## License
74
 
75
  This project is released under Apache 2.0. See [LICENSE](../LICENSE).
 
8
 
9
  `pashto-language-resources` is a community-led open-source project focused on making Pashto (also written as Pukhto/Pushto) a first-class language in speech and language AI.
10
 
11
+ ## Quick Actions
12
+
13
+ - Search resources: [Pashto Resource Search](search/)
14
+ - Browse all docs: [Documentation Hub](README.md)
15
+ - Browse verified resource catalog: [resource_catalog.md](resource_catalog.md)
16
+
17
  ## Mission
18
 
19
  - Build open Pashto datasets and resource indexes for ASR, TTS, NLP, and MT.
20
  - Publish reproducible baseline models, benchmark schemas, and evaluation workflows.
21
  - Keep progress transparent, contributor-friendly, and public-benefit oriented.
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  ## Intent Pages
24
 
25
  - Pashto datasets: [pashto_datasets.md](pashto_datasets.md)
26
  - Pashto ASR resources: [pashto_asr.md](pashto_asr.md)
27
  - Pashto TTS resources: [pashto_tts.md](pashto_tts.md)
28
 
29
+ ## Repository References
30
 
31
  - Repository: [Musawer1214/pashto-language-resources](https://github.com/Musawer1214/pashto-language-resources)
32
  - Hugging Face: [Musawer14/pashto-language-resources](https://huggingface.co/Musawer14/pashto-language-resources)
 
36
 
37
  ## SEO Operations
38
 
39
+ - Discoverability playbook: [discoverability_seo.md](discoverability_seo.md)
40
  - GitHub topics checklist: [github_topics_checklist.md](github_topics_checklist.md)
41
  - Backlink strategy: [backlink_strategy.md](backlink_strategy.md)
 
 
42
 
43
+ ## Releases
44
+
45
+ - Release notes index: [releases/README.md](releases/README.md)
46
+ - Current release notes: [v1.0.0](releases/v1.0.0.md)
47
+ - Changelog: [../CHANGELOG.md](../CHANGELOG.md)
48
+
49
+ ## Contribution
50
 
51
  You can help by improving documentation, validating normalization rows, sharing verified resources, or contributing data, model, and evaluation workflows.
52
 
53
+ Start here:
54
  - [docs/README.md](README.md)
55
  - [community/COMMUNICATION.md](../community/COMMUNICATION.md)
56
 
 
 
 
 
 
 
 
 
 
 
 
57
  ## License
58
 
59
  This project is released under Apache 2.0. See [LICENSE](../LICENSE).
docs/platform_sync_policy.md CHANGED
@@ -28,12 +28,19 @@ Use a lowest-common-denominator style in shared docs:
28
  - Relative links for internal files whenever possible.
29
  - YAML front matter only where needed (`README.md` for HF metadata, docs pages for Jekyll SEO).
30
  - Avoid GitHub-only HTML widgets and avoid HF-specific custom blocks in shared files.
 
31
  ## Known Platform Differences
32
 
33
  - GitHub accepts regular Git binary blobs in many repos.
34
- - Hugging Face may reject binary blobs unless stored with Xet/LFS-compatible flow.
35
  - Hugging Face may warn about missing model-card metadata in README; this is a warning, not a push blocker.
36
 
 
 
 
 
 
 
37
  ## Safe Update Checklist
38
 
39
  1. Run checks:
@@ -57,4 +64,3 @@ If GitHub and Hugging Face histories diverge:
57
  - Keep GitHub `main` as canonical source history.
58
  - Sync Hugging Face using a content snapshot commit based on `hf/main`.
59
  - Do not rewrite remote history unless explicitly required.
60
-
 
28
  - Relative links for internal files whenever possible.
29
  - YAML front matter only where needed (`README.md` for HF metadata, docs pages for Jekyll SEO).
30
  - Avoid GitHub-only HTML widgets and avoid HF-specific custom blocks in shared files.
31
+
32
  ## Known Platform Differences
33
 
34
  - GitHub accepts regular Git binary blobs in many repos.
35
+ - Hugging Face may reject binary blobs unless stored with Xet or LFS-compatible flow.
36
  - Hugging Face may warn about missing model-card metadata in README; this is a warning, not a push blocker.
37
 
38
+ ## Tagging Strategy
39
+
40
+ - Create annotated tags on GitHub release commits.
41
+ - If Hugging Face rejects a tag because of blocked binary history, create the same tag name on the HF-safe `hf/main` commit.
42
+ - Keep release notes content identical even when commit hashes differ across platforms.
43
+
44
  ## Safe Update Checklist
45
 
46
  1. Run checks:
 
64
  - Keep GitHub `main` as canonical source history.
65
  - Sync Hugging Face using a content snapshot commit based on `hf/main`.
66
  - Do not rewrite remote history unless explicitly required.
 
docs/release_checklist.md CHANGED
@@ -3,14 +3,19 @@
3
  Use this checklist before tagging a new release.
4
 
5
  ## Required
 
6
  - [ ] Update [CHANGELOG.md](../CHANGELOG.md).
 
7
  - [ ] Run `python scripts/check_links.py`.
8
  - [ ] Run `python scripts/validate_normalization.py data/processed/normalization_seed_v0.1.tsv`.
 
9
  - [ ] Confirm benchmark snapshots are stored in [../benchmarks/results/README.md](../benchmarks/results/README.md) format.
10
  - [ ] Confirm docs reflect the release scope.
11
 
12
  ## Recommended
 
13
  - [ ] Run tests (`python -m pytest -q`).
14
  - [ ] Re-check key external resource links in [resource_catalog.md](resource_catalog.md).
15
  - [ ] Verify README rendering on GitHub and Hugging Face after push.
16
-
 
 
3
  Use this checklist before tagging a new release.
4
 
5
  ## Required
6
+
7
  - [ ] Update [CHANGELOG.md](../CHANGELOG.md).
8
+ - [ ] Add release notes under [releases/README.md](releases/README.md).
9
  - [ ] Run `python scripts/check_links.py`.
10
  - [ ] Run `python scripts/validate_normalization.py data/processed/normalization_seed_v0.1.tsv`.
11
+ - [ ] Run `python scripts/validate_resource_catalog.py`.
12
  - [ ] Confirm benchmark snapshots are stored in [../benchmarks/results/README.md](../benchmarks/results/README.md) format.
13
  - [ ] Confirm docs reflect the release scope.
14
 
15
  ## Recommended
16
+
17
  - [ ] Run tests (`python -m pytest -q`).
18
  - [ ] Re-check key external resource links in [resource_catalog.md](resource_catalog.md).
19
  - [ ] Verify README rendering on GitHub and Hugging Face after push.
20
+ - [ ] Verify GitHub and Hugging Face `main` trees are content-equivalent.
21
+ - [ ] Push release tag to both platforms.
docs/release_process.md CHANGED
@@ -1,21 +1,32 @@
1
- # 🚀 Release Process
2
 
3
- ## ⏱️ Cadence
4
- - Monthly milestone release
5
- - Hotfix releases as needed
 
 
 
6
 
7
- ## ✅ Required for release
8
  - Changelog summary in [../CHANGELOG.md](../CHANGELOG.md)
9
  - Benchmark snapshot in [../benchmarks/results/README.md](../benchmarks/results/README.md) format
10
  - Known limitations section in release notes
11
- - Reproducible commands/scripts
12
- - Link and normalization checks:
13
  - `python scripts/check_links.py`
14
  - `python scripts/validate_normalization.py data/processed/normalization_seed_v0.1.tsv`
 
 
 
 
 
 
 
 
 
 
 
15
 
16
- ## 🔖 Versioning
17
- - Use semantic-style tags for major milestones (e.g., `v0.1`, `v0.2`)
18
 
19
- ## 🧾 Templates
20
  - Release checklist: [release_checklist.md](release_checklist.md)
21
- - Release notes template: [../.github/release_template.md](../.github/release_template.md)
 
1
+ # Release Process
2
 
3
+ ## Cadence
4
+
5
+ - Scheduled release: monthly milestone or when a major quality threshold is met.
6
+ - Hotfix release: any urgent fixes that should not wait for the next milestone.
7
+
8
+ ## Required for Release
9
 
 
10
  - Changelog summary in [../CHANGELOG.md](../CHANGELOG.md)
11
  - Benchmark snapshot in [../benchmarks/results/README.md](../benchmarks/results/README.md) format
12
  - Known limitations section in release notes
13
+ - Reproducible commands or scripts
14
+ - Validation checks:
15
  - `python scripts/check_links.py`
16
  - `python scripts/validate_normalization.py data/processed/normalization_seed_v0.1.tsv`
17
+ - `python scripts/validate_resource_catalog.py`
18
+
19
+ ## Versioning
20
+
21
+ - Use semantic version tags: `vMAJOR.MINOR.PATCH`.
22
+ - Example: `v1.0.0`, `v1.0.1`, `v1.1.0`, `v2.0.0`.
23
+
24
+ ## Release Notes Location
25
+
26
+ - Store release notes in [releases/README.md](releases/README.md).
27
+ - Add one file per release tag under `docs/releases/`.
28
 
29
+ ## Templates
 
30
 
 
31
  - Release checklist: [release_checklist.md](release_checklist.md)
32
+ - Release template: [../.github/release_template.md](../.github/release_template.md)
docs/release_v0.1.1.md DELETED
@@ -1,38 +0,0 @@
1
- # Release Notes Draft: v0.1.1
2
-
3
- Status: draft
4
- Target date: TBD
5
-
6
- ## Summary
7
-
8
- v0.1.1 focuses on discoverability improvements and cross-platform consistency between GitHub and Hugging Face.
9
-
10
- ## Highlights
11
-
12
- - Added HF model-card YAML metadata to `README.md`.
13
- - Added SEO operations docs:
14
- - `docs/github_topics_checklist.md`
15
- - `docs/backlink_strategy.md`
16
- - Added intent landing pages:
17
- - `docs/pashto_datasets.md`
18
- - `docs/pashto_asr.md`
19
- - `docs/pashto_tts.md`
20
- - Expanded docs hub and index references for new SEO content.
21
-
22
- ## Validation Checklist
23
-
24
- - [ ] `python scripts/check_links.py`
25
- - [ ] `python scripts/validate_resource_catalog.py`
26
- - [ ] `python -m pytest -q`
27
-
28
- ## Release Commands
29
-
30
- ```bash
31
- git tag v0.1.1
32
- git push origin v0.1.1
33
- ```
34
-
35
- ## Compare
36
-
37
- - GitHub compare: [v0.1...v0.1.1](https://github.com/Musawer1214/pashto-language-resources/compare/v0.1...v0.1.1)
38
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
docs/release_v0.1.2.md DELETED
@@ -1,33 +0,0 @@
1
- # Release Notes Draft: v0.1.2
2
-
3
- Status: draft
4
- Target date: TBD
5
-
6
- ## Summary
7
-
8
- v0.1.2 is reserved for post-indexing improvements after monitoring search performance and backlink growth.
9
-
10
- ## Planned Scope
11
-
12
- - Refine high-intent docs based on Search Console query data.
13
- - Expand verified resource coverage with citation-quality metadata.
14
- - Publish first KPI review for backlinks and discoverability metrics.
15
- - Tighten internal linking between docs hub, search page, and resource sections.
16
-
17
- ## Validation Checklist
18
-
19
- - [ ] `python scripts/check_links.py`
20
- - [ ] `python scripts/validate_resource_catalog.py`
21
- - [ ] `python -m pytest -q`
22
-
23
- ## Release Commands
24
-
25
- ```bash
26
- git tag v0.1.2
27
- git push origin v0.1.2
28
- ```
29
-
30
- ## Compare
31
-
32
- - GitHub compare: [v0.1.1...v0.1.2](https://github.com/Musawer1214/pashto-language-resources/compare/v0.1.1...v0.1.2)
33
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
docs/releases/README.md ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Releases
2
+
3
+ This directory stores versioned release notes for the project.
4
+
5
+ ## Current
6
+
7
+ - [v1.0.0](v1.0.0.md)
8
+
9
+ ## Notes
10
+
11
+ - `v1.0.0` is the first official stable release tag.
12
+ - Earlier bootstrap history (`v0.1`) remains documented in [../../CHANGELOG.md](../../CHANGELOG.md).
docs/releases/v1.0.0.md ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Release Notes: v1.0.0
2
+
3
+ Release date: 2026-02-18
4
+ Tag: `v1.0.0`
5
+
6
+ ## Summary
7
+
8
+ First stable release of `pashto-language-resources` with cleaned structure, stronger discoverability, and upgraded web usability for resource exploration.
9
+
10
+ ## Highlights
11
+
12
+ - Unified release documentation under `docs/releases/`.
13
+ - Removed stale draft release pages and redundant references.
14
+ - Refined docs structure for clearer navigation and lower duplication.
15
+ - Upgraded search page UX with faster exploration patterns and clearer controls.
16
+ - Hardened platform-sync guidance for GitHub and Hugging Face parity.
17
+
18
+ ## Validation
19
+
20
+ - `python scripts/check_links.py`
21
+ - `python scripts/validate_resource_catalog.py`
22
+ - `python scripts/validate_normalization.py data/processed/normalization_seed_v0.1.tsv`
23
+ - `python -m pytest -q`
24
+
25
+ ## Platform State
26
+
27
+ - GitHub repository: `Musawer1214/pashto-language-resources`
28
+ - Hugging Face mirror: `Musawer14/pashto-language-resources`
29
+ - Main-branch content is kept equivalent across both platforms.
30
+
31
+ ## Compare
32
+
33
+ - [GitHub compare: v0.1...v1.0.0](https://github.com/Musawer1214/pashto-language-resources/compare/v0.1...v1.0.0)
docs/search/index.html CHANGED
@@ -41,79 +41,152 @@ permalink: /search/
41
  </script>
42
  <link rel="preconnect" href="https://fonts.googleapis.com">
43
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
44
- <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Arabic:wght@400;500;700&family=Space+Grotesk:wght@500;700&display=swap" rel="stylesheet">
45
  <style>
46
  :root {
47
- --bg: #f6f4ec;
48
- --panel: #fffef9;
49
- --ink: #1d2a24;
50
- --muted: #4c6158;
51
- --line: #d6ddd7;
52
- --brand: #106b53;
53
- --brand-soft: #e0f0ea;
54
- --accent: #c76a1a;
55
- --accent-soft: #f7e9d8;
56
- --shadow: 0 12px 30px rgba(29, 42, 36, 0.08);
 
 
 
57
  }
58
 
59
  * { box-sizing: border-box; }
60
 
61
  body {
62
  margin: 0;
63
- font-family: "IBM Plex Sans Arabic", "Segoe UI", sans-serif;
64
  color: var(--ink);
 
 
65
  background:
66
- radial-gradient(circle at 8% 12%, #fce4c4 0, rgba(252, 228, 196, 0) 35%),
67
- radial-gradient(circle at 92% 6%, #d8ece5 0, rgba(216, 236, 229, 0) 38%),
68
  var(--bg);
69
- min-height: 100vh;
70
  }
71
 
72
- .wrap {
73
- max-width: 1100px;
 
 
74
  margin: 0 auto;
75
- padding: 24px 18px 44px;
76
  }
77
 
78
  .hero {
79
- background: linear-gradient(120deg, #fff, #f7fbf9);
80
  border: 1px solid var(--line);
 
81
  box-shadow: var(--shadow);
82
- border-radius: 18px;
83
- padding: 20px 18px;
84
- margin-bottom: 16px;
85
- transform: translateY(8px);
86
- opacity: 0;
87
- animation: rise 500ms ease forwards;
 
 
 
 
88
  }
89
 
90
  .eyebrow {
91
- letter-spacing: 0.07em;
 
 
92
  text-transform: uppercase;
93
  color: var(--accent);
94
- font-family: "Space Grotesk", sans-serif;
95
- font-weight: 700;
96
- font-size: 12px;
97
- margin-bottom: 6px;
98
  }
99
 
100
  h1 {
101
- margin: 0 0 8px;
102
- font-family: "Space Grotesk", sans-serif;
103
- font-size: 33px;
104
- line-height: 1.1;
105
  }
106
 
107
- .hero p {
108
- margin: 0;
109
  color: var(--muted);
110
- line-height: 1.5;
 
111
  }
112
 
113
- .controls {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  margin-top: 14px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  display: grid;
116
- grid-template-columns: 2.2fr 1fr 1fr 1fr 1fr;
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  gap: 10px;
118
  }
119
 
@@ -124,110 +197,158 @@ permalink: /search/
124
  }
125
 
126
  .field label {
127
- font-size: 12px;
128
- font-weight: 700;
129
- color: var(--muted);
130
- letter-spacing: 0.04em;
131
  text-transform: uppercase;
132
- font-family: "Space Grotesk", sans-serif;
 
133
  }
134
 
135
  input, select {
136
  width: 100%;
137
  border: 1px solid var(--line);
138
- background: var(--panel);
 
139
  color: var(--ink);
140
- border-radius: 10px;
141
- padding: 10px 11px;
142
  font: inherit;
143
  }
144
 
145
- input:focus, select:focus {
146
- outline: 2px solid #8cc9b5;
147
- border-color: #8cc9b5;
 
148
  }
149
 
150
- .summary {
151
- margin: 14px 2px 6px;
152
  display: flex;
 
153
  justify-content: space-between;
 
154
  align-items: center;
155
- gap: 12px;
156
- color: var(--muted);
157
- font-size: 14px;
158
  }
159
 
160
- .badge {
161
- background: var(--brand-soft);
162
- color: var(--brand);
163
- border: 1px solid #b7dccc;
164
- padding: 3px 9px;
 
 
 
 
 
 
165
  border-radius: 999px;
166
- font-weight: 600;
 
 
 
167
  }
168
 
169
- .crawl {
170
- margin: 8px 2px 16px;
171
- color: var(--muted);
172
- font-size: 14px;
173
- line-height: 1.5;
 
174
  }
175
 
176
- .crawl p {
177
- margin: 6px 0;
 
 
178
  }
179
 
180
- .crawl-links {
181
- margin: 8px 0 0;
182
- padding-left: 18px;
 
183
  }
184
 
185
- .crawl-links li {
186
- margin: 3px 0;
 
 
 
187
  }
188
 
189
- .grid {
190
- display: grid;
191
- grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
192
- gap: 12px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
  list-style: none;
194
- padding: 0;
195
  margin: 0;
 
 
 
196
  }
197
 
 
 
 
198
  .card {
199
  border: 1px solid var(--line);
200
- border-radius: 14px;
201
  background: var(--panel);
202
  box-shadow: var(--shadow);
203
- padding: 13px 12px;
204
  display: flex;
205
  flex-direction: column;
206
  gap: 9px;
207
- opacity: 0;
208
- animation: rise 420ms ease forwards;
209
  }
210
 
211
  .chips {
212
  display: flex;
213
- gap: 6px;
214
  flex-wrap: wrap;
 
215
  }
216
 
217
  .chip {
218
  border-radius: 999px;
219
- padding: 2px 8px;
220
- font-size: 11px;
221
- font-weight: 700;
222
- font-family: "Space Grotesk", sans-serif;
223
- letter-spacing: 0.03em;
224
  text-transform: uppercase;
 
225
  border: 1px solid transparent;
226
  }
227
 
228
  .chip.category { background: var(--brand-soft); color: var(--brand); border-color: #b7dccc; }
229
- .chip.source { background: var(--accent-soft); color: #955016; border-color: #efc89f; }
230
- .chip.status { background: #eef3ff; color: #3e4f86; border-color: #d2dbf6; }
231
 
232
  .title {
233
  margin: 0;
@@ -241,68 +362,115 @@ permalink: /search/
241
  border-bottom: 1px solid transparent;
242
  }
243
 
244
- .title a:hover {
245
- border-bottom-color: currentColor;
246
- }
247
 
248
- .meta {
 
249
  color: var(--muted);
 
250
  font-size: 13px;
251
- line-height: 1.45;
252
- margin: 0;
253
  }
254
 
255
- .card footer {
256
  margin-top: auto;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  font-size: 12px;
258
  color: var(--muted);
 
259
  }
260
 
261
  .empty {
262
  border: 1px dashed #b9c4bd;
263
- border-radius: 12px;
264
- padding: 24px;
265
  background: #fcfcfa;
266
  color: var(--muted);
267
  text-align: center;
268
  }
269
 
270
- @keyframes rise {
271
- from { opacity: 0; transform: translateY(8px); }
 
 
 
 
 
 
 
 
 
 
 
 
272
  to { opacity: 1; transform: translateY(0); }
273
  }
274
 
275
- @media (max-width: 900px) {
276
- .controls {
277
- grid-template-columns: 1fr 1fr;
278
- }
279
 
280
- .controls .field:first-child {
281
- grid-column: span 2;
282
- }
 
 
 
283
  }
284
 
285
- @media (max-width: 560px) {
286
- h1 { font-size: 28px; }
287
  .controls { grid-template-columns: 1fr; }
288
- .controls .field:first-child { grid-column: span 1; }
289
- .summary { flex-direction: column; align-items: flex-start; }
290
  }
291
  </style>
292
  </head>
293
  <body>
294
- <main class="wrap">
295
- <section class="hero">
296
- <div class="eyebrow">Pukhto Pashto</div>
297
- <h1>Pashto Technology Resource Search</h1>
298
- <p>
299
- Search and filter verified and candidate resources that support Pashto in ASR, TTS, NLP, translation, tooling, and research.
300
- </p>
301
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
  <div class="controls">
303
- <div class="field">
304
  <label for="q">Search</label>
305
- <input id="q" type="search" placeholder="Try: ASR, pbt_Arab, translation, speech" />
306
  </div>
307
  <div class="field">
308
  <label for="category">Category</label>
@@ -320,22 +488,46 @@ permalink: /search/
320
  <label for="status">Status</label>
321
  <select id="status"></select>
322
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
323
  </div>
324
  </section>
325
 
326
- <div class="summary">
327
  <span id="countText">Loading resources...</span>
328
  <span class="badge" id="generatedAt">Catalog timestamp: -</span>
329
  </div>
330
 
331
- <section class="crawl" aria-label="Pashto resource categories">
332
- <p>
333
- Browse or search resource entries covering Pashto datasets, speech recognition (ASR), text-to-speech (TTS), NLP, translation, tools, and benchmarks.
334
- </p>
335
- <p>
336
- Project overview: <a href="https://github.com/Musawer1214/pashto-language-resources">Musawer1214/pashto-language-resources</a>
337
- </p>
338
- <ul class="crawl-links">
339
  <li><a href="https://github.com/Musawer1214/pashto-language-resources/blob/main/resources/datasets/README.md">Pashto datasets</a></li>
340
  <li><a href="https://github.com/Musawer1214/pashto-language-resources/blob/main/resources/models/README.md">Pashto models</a></li>
341
  <li><a href="https://github.com/Musawer1214/pashto-language-resources/blob/main/resources/benchmarks/README.md">Pashto benchmarks</a></li>
@@ -345,16 +537,17 @@ permalink: /search/
345
  </section>
346
 
347
  <noscript>
348
- JavaScript is needed for filtering, but the linked category pages above remain accessible.
349
  </noscript>
350
 
351
- <ul id="results" class="grid"></ul>
352
  </main>
353
 
354
  <script>
355
  const state = {
356
  all: [],
357
- filtered: []
 
358
  };
359
 
360
  const els = {
@@ -363,11 +556,29 @@ permalink: /search/
363
  source: document.getElementById("source"),
364
  task: document.getElementById("task"),
365
  status: document.getElementById("status"),
 
366
  results: document.getElementById("results"),
367
  countText: document.getElementById("countText"),
368
- generatedAt: document.getElementById("generatedAt")
 
 
 
 
 
 
 
 
369
  };
370
 
 
 
 
 
 
 
 
 
 
371
  function uniqSorted(values) {
372
  return [...new Set(values.filter(Boolean))].sort((a, b) => a.localeCompare(b));
373
  }
@@ -379,13 +590,30 @@ permalink: /search/
379
  allOption.textContent = allLabel;
380
  select.appendChild(allOption);
381
  for (const opt of options) {
382
- const el = document.createElement("option");
383
- el.value = opt;
384
- el.textContent = opt;
385
- select.appendChild(el);
386
  }
387
  }
388
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
389
  function matchesQuery(resource, query) {
390
  if (!query) return true;
391
  const hay = [
@@ -403,6 +631,26 @@ permalink: /search/
403
  return hay.includes(query);
404
  }
405
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
  function applyFilters() {
407
  const q = els.q.value.trim().toLowerCase();
408
  const category = els.category.value;
@@ -410,20 +658,21 @@ permalink: /search/
410
  const task = els.task.value;
411
  const status = els.status.value;
412
 
413
- state.filtered = state.all.filter((resource) => {
414
  if (!matchesQuery(resource, q)) return false;
415
  if (category && resource.category !== category) return false;
416
  if (source && resource.source !== source) return false;
417
  if (status && resource.status !== status) return false;
418
  if (task && !(resource.tasks || []).includes(task)) return false;
419
  return true;
420
- });
421
 
422
  renderResults();
 
423
  }
424
 
425
  function chip(label, cls) {
426
- return `<span class="chip ${cls}">${label}</span>`;
427
  }
428
 
429
  function renderResults() {
@@ -431,26 +680,104 @@ permalink: /search/
431
  els.countText.textContent = `${items.length} result${items.length === 1 ? "" : "s"} of ${state.all.length}`;
432
 
433
  if (!items.length) {
434
- els.results.innerHTML = `<li class="empty">No matches. Try broadening filters or changing keywords.</li>`;
435
  return;
436
  }
437
 
438
- els.results.innerHTML = items.map((resource, idx) => `
439
- <li class="card" style="animation-delay:${Math.min(idx * 28, 320)}ms">
440
- <div class="chips">
441
- ${chip(resource.category, "category")}
442
- ${chip(resource.source, "source")}
443
- ${chip(resource.status, "status")}
444
- </div>
445
- <h2 class="title"><a href="${resource.url}" target="_blank" rel="noreferrer">${resource.title}</a></h2>
446
- <p class="meta">${resource.summary}</p>
447
- <p class="meta"><strong>Primary use:</strong> ${resource.primary_use}</p>
448
- <p class="meta"><strong>Pashto evidence:</strong> <a href="${resource.evidence_url}" target="_blank" rel="noreferrer">${resource.evidence_text}</a></p>
449
- <footer>
450
- ${(resource.tasks || []).length ? `Tasks: ${resource.tasks.join(", ")}` : "Tasks: n/a"}
451
- </footer>
452
- </li>
453
- `).join("");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
454
  }
455
 
456
  async function load() {
@@ -458,37 +785,43 @@ permalink: /search/
458
  const res = await fetch("./resources.json", { cache: "no-store" });
459
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
460
  const payload = await res.json();
 
461
  state.all = payload.resources || [];
462
- state.filtered = [...state.all];
463
 
464
  fillSelect(els.category, uniqSorted(state.all.map((r) => r.category)), "All categories");
465
  fillSelect(els.source, uniqSorted(state.all.map((r) => r.source)), "All sources");
466
  fillSelect(els.status, uniqSorted(state.all.map((r) => r.status)), "All statuses");
467
- fillSelect(
468
- els.task,
469
- uniqSorted(state.all.flatMap((r) => r.tasks || [])),
470
- "All tasks"
471
- );
472
 
473
  const generated = payload.generated_on ? new Date(payload.generated_on) : null;
474
  els.generatedAt.textContent = generated && !Number.isNaN(generated.getTime())
475
  ? `Catalog timestamp: ${generated.toISOString()}`
476
  : "Catalog timestamp: unknown";
477
 
 
478
  applyFilters();
479
  } catch (err) {
480
  els.countText.textContent = "Failed to load resources";
481
- els.results.innerHTML = `<li class="empty">Could not load search data. ${String(err)}</li>`;
482
  }
483
  }
484
 
485
- [els.q, els.category, els.source, els.task, els.status].forEach((el) => {
486
  el.addEventListener("input", applyFilters);
487
  el.addEventListener("change", applyFilters);
488
  });
489
 
 
 
 
 
 
 
 
 
490
  load();
491
  </script>
492
  </body>
493
  </html>
494
-
 
41
  </script>
42
  <link rel="preconnect" href="https://fonts.googleapis.com">
43
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
44
+ <link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;600;700;800&family=Noto+Naskh+Arabic:wght@500;700&display=swap" rel="stylesheet">
45
  <style>
46
  :root {
47
+ --bg: #f3f2ea;
48
+ --panel: #fffdf7;
49
+ --ink: #1d2628;
50
+ --muted: #55656a;
51
+ --line: #d5ddd8;
52
+ --brand: #0f6f61;
53
+ --brand-soft: #dcf2ee;
54
+ --accent: #b9621f;
55
+ --accent-soft: #f8e6d7;
56
+ --shadow: 0 14px 36px rgba(16, 29, 35, 0.12);
57
+ --radius-lg: 18px;
58
+ --radius-md: 12px;
59
+ --radius-sm: 9px;
60
  }
61
 
62
  * { box-sizing: border-box; }
63
 
64
  body {
65
  margin: 0;
 
66
  color: var(--ink);
67
+ font-family: "Manrope", "Segoe UI", sans-serif;
68
+ min-height: 100vh;
69
  background:
70
+ radial-gradient(circle at 8% 8%, #ffe0bf 0, rgba(255, 224, 191, 0) 30%),
71
+ radial-gradient(circle at 92% 7%, #d2ece4 0, rgba(210, 236, 228, 0) 35%),
72
  var(--bg);
 
73
  }
74
 
75
+ a { color: var(--brand); }
76
+
77
+ .container {
78
+ max-width: 1180px;
79
  margin: 0 auto;
80
+ padding: 22px 18px 42px;
81
  }
82
 
83
  .hero {
84
+ background: linear-gradient(130deg, #fffef9, #f5faf8);
85
  border: 1px solid var(--line);
86
+ border-radius: var(--radius-lg);
87
  box-shadow: var(--shadow);
88
+ padding: 20px;
89
+ margin-bottom: 14px;
90
+ }
91
+
92
+ .hero-top {
93
+ display: flex;
94
+ justify-content: space-between;
95
+ align-items: flex-start;
96
+ gap: 14px;
97
+ flex-wrap: wrap;
98
  }
99
 
100
  .eyebrow {
101
+ margin: 0 0 8px;
102
+ font-size: 12px;
103
+ letter-spacing: 0.08em;
104
  text-transform: uppercase;
105
  color: var(--accent);
106
+ font-weight: 800;
 
 
 
107
  }
108
 
109
  h1 {
110
+ margin: 0;
111
+ font-size: 34px;
112
+ line-height: 1.08;
113
+ letter-spacing: -0.02em;
114
  }
115
 
116
+ .subtitle {
117
+ margin: 10px 0 0;
118
  color: var(--muted);
119
+ line-height: 1.55;
120
+ max-width: 760px;
121
  }
122
 
123
+ .stat-row {
124
+ display: grid;
125
+ grid-template-columns: repeat(3, minmax(120px, 1fr));
126
+ gap: 8px;
127
+ width: min(380px, 100%);
128
+ }
129
+
130
+ .stat {
131
+ border: 1px solid var(--line);
132
+ border-radius: var(--radius-md);
133
+ background: var(--panel);
134
+ padding: 10px;
135
+ text-align: center;
136
+ }
137
+
138
+ .stat strong {
139
+ display: block;
140
+ font-size: 20px;
141
+ line-height: 1;
142
+ color: var(--brand);
143
+ }
144
+
145
+ .stat span {
146
+ display: block;
147
+ margin-top: 4px;
148
+ color: var(--muted);
149
+ font-size: 12px;
150
+ font-weight: 700;
151
+ text-transform: uppercase;
152
+ letter-spacing: 0.04em;
153
+ }
154
+
155
+ .quick-links {
156
  margin-top: 14px;
157
+ display: flex;
158
+ flex-wrap: wrap;
159
+ gap: 8px;
160
+ }
161
+
162
+ .pill-link {
163
+ border: 1px solid #b8cec6;
164
+ border-radius: 999px;
165
+ background: #f8fcfa;
166
+ color: var(--brand);
167
+ text-decoration: none;
168
+ font-size: 13px;
169
+ font-weight: 700;
170
+ padding: 7px 12px;
171
+ }
172
+
173
+ .toolbar {
174
+ margin-bottom: 12px;
175
  display: grid;
176
+ gap: 12px;
177
+ }
178
+
179
+ .panel {
180
+ border: 1px solid var(--line);
181
+ border-radius: var(--radius-lg);
182
+ background: var(--panel);
183
+ box-shadow: var(--shadow);
184
+ padding: 16px;
185
+ }
186
+
187
+ .controls {
188
+ display: grid;
189
+ grid-template-columns: 2fr repeat(5, minmax(140px, 1fr));
190
  gap: 10px;
191
  }
192
 
 
197
  }
198
 
199
  .field label {
200
+ font-size: 11px;
201
+ letter-spacing: 0.05em;
 
 
202
  text-transform: uppercase;
203
+ font-weight: 800;
204
+ color: var(--muted);
205
  }
206
 
207
  input, select {
208
  width: 100%;
209
  border: 1px solid var(--line);
210
+ border-radius: var(--radius-sm);
211
+ background: #fff;
212
  color: var(--ink);
213
+ padding: 10px;
 
214
  font: inherit;
215
  }
216
 
217
+ input:focus, select:focus, button:focus {
218
+ outline: 2px solid #7bc7b8;
219
+ outline-offset: 1px;
220
+ border-color: #7bc7b8;
221
  }
222
 
223
+ .action-row {
224
+ margin-top: 10px;
225
  display: flex;
226
+ flex-wrap: wrap;
227
  justify-content: space-between;
228
+ gap: 10px;
229
  align-items: center;
 
 
 
230
  }
231
 
232
+ .group {
233
+ display: flex;
234
+ flex-wrap: wrap;
235
+ gap: 7px;
236
+ align-items: center;
237
+ }
238
+
239
+ .btn {
240
+ border: 1px solid var(--line);
241
+ background: #fff;
242
+ color: var(--ink);
243
  border-radius: 999px;
244
+ padding: 7px 12px;
245
+ font-size: 13px;
246
+ font-weight: 700;
247
+ cursor: pointer;
248
  }
249
 
250
+ .btn:hover { border-color: #98b9ae; }
251
+
252
+ .btn.brand {
253
+ background: var(--brand);
254
+ color: #fff;
255
+ border-color: var(--brand);
256
  }
257
 
258
+ .btn.light {
259
+ background: #f6faf8;
260
+ color: var(--brand);
261
+ border-color: #b9d8cf;
262
  }
263
 
264
+ .btn.active {
265
+ background: var(--accent-soft);
266
+ border-color: #efc08f;
267
+ color: #915117;
268
  }
269
 
270
+ .intent-row {
271
+ margin-top: 10px;
272
+ display: flex;
273
+ flex-wrap: wrap;
274
+ gap: 7px;
275
  }
276
 
277
+ .intent {
278
+ border: 1px solid #cfdad4;
279
+ background: #fbfdfc;
280
+ border-radius: 999px;
281
+ padding: 6px 11px;
282
+ font-size: 13px;
283
+ font-weight: 700;
284
+ cursor: pointer;
285
+ color: var(--muted);
286
+ }
287
+
288
+ .intent:hover { border-color: #9cb8af; color: var(--ink); }
289
+
290
+ .summary {
291
+ margin: 0 2px 12px;
292
+ display: flex;
293
+ justify-content: space-between;
294
+ align-items: center;
295
+ gap: 10px;
296
+ color: var(--muted);
297
+ font-size: 14px;
298
+ }
299
+
300
+ .badge {
301
+ background: var(--brand-soft);
302
+ color: var(--brand);
303
+ border: 1px solid #b7dccc;
304
+ padding: 4px 9px;
305
+ border-radius: 999px;
306
+ font-weight: 700;
307
+ font-size: 12px;
308
+ }
309
+
310
+ .results {
311
  list-style: none;
 
312
  margin: 0;
313
+ padding: 0;
314
+ display: grid;
315
+ gap: 12px;
316
  }
317
 
318
+ .results.grid { grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); }
319
+ .results.list { grid-template-columns: 1fr; }
320
+
321
  .card {
322
  border: 1px solid var(--line);
323
+ border-radius: var(--radius-md);
324
  background: var(--panel);
325
  box-shadow: var(--shadow);
326
+ padding: 13px;
327
  display: flex;
328
  flex-direction: column;
329
  gap: 9px;
330
+ animation: cardIn 360ms ease;
 
331
  }
332
 
333
  .chips {
334
  display: flex;
 
335
  flex-wrap: wrap;
336
+ gap: 6px;
337
  }
338
 
339
  .chip {
340
  border-radius: 999px;
341
+ font-size: 10px;
342
+ font-weight: 800;
343
+ letter-spacing: 0.04em;
 
 
344
  text-transform: uppercase;
345
+ padding: 3px 8px;
346
  border: 1px solid transparent;
347
  }
348
 
349
  .chip.category { background: var(--brand-soft); color: var(--brand); border-color: #b7dccc; }
350
+ .chip.source { background: var(--accent-soft); color: #915117; border-color: #efc89f; }
351
+ .chip.status { background: #edf2ff; color: #3f4f86; border-color: #d0dbf6; }
352
 
353
  .title {
354
  margin: 0;
 
362
  border-bottom: 1px solid transparent;
363
  }
364
 
365
+ .title a:hover { border-bottom-color: currentColor; }
 
 
366
 
367
+ .text {
368
+ margin: 0;
369
  color: var(--muted);
370
+ line-height: 1.48;
371
  font-size: 13px;
 
 
372
  }
373
 
374
+ .meta-links {
375
  margin-top: auto;
376
+ display: flex;
377
+ flex-wrap: wrap;
378
+ gap: 8px;
379
+ align-items: center;
380
+ }
381
+
382
+ .mini-link {
383
+ font-size: 12px;
384
+ font-weight: 700;
385
+ color: var(--brand);
386
+ text-decoration: none;
387
+ }
388
+
389
+ .tasks {
390
  font-size: 12px;
391
  color: var(--muted);
392
+ margin: 0;
393
  }
394
 
395
  .empty {
396
  border: 1px dashed #b9c4bd;
397
+ border-radius: var(--radius-md);
398
+ padding: 26px;
399
  background: #fcfcfa;
400
  color: var(--muted);
401
  text-align: center;
402
  }
403
 
404
+ .crawl {
405
+ margin: 0 2px 12px;
406
+ color: var(--muted);
407
+ line-height: 1.5;
408
+ font-size: 14px;
409
+ }
410
+
411
+ .crawl ul {
412
+ margin: 8px 0 0;
413
+ padding-left: 18px;
414
+ }
415
+
416
+ @keyframes cardIn {
417
+ from { opacity: 0; transform: translateY(5px); }
418
  to { opacity: 1; transform: translateY(0); }
419
  }
420
 
421
+ @media (max-width: 1020px) {
422
+ .controls { grid-template-columns: repeat(3, minmax(140px, 1fr)); }
423
+ .controls .field.search { grid-column: span 3; }
424
+ }
425
 
426
+ @media (max-width: 720px) {
427
+ h1 { font-size: 30px; }
428
+ .controls { grid-template-columns: 1fr 1fr; }
429
+ .controls .field.search { grid-column: span 2; }
430
+ .summary { flex-direction: column; align-items: flex-start; }
431
+ .stat-row { width: 100%; }
432
  }
433
 
434
+ @media (max-width: 520px) {
 
435
  .controls { grid-template-columns: 1fr; }
436
+ .controls .field.search { grid-column: span 1; }
437
+ h1 { font-size: 28px; }
438
  }
439
  </style>
440
  </head>
441
  <body>
442
+ <main class="container">
443
+ <header class="hero">
444
+ <div class="hero-top">
445
+ <div>
446
+ <p class="eyebrow">Pukhto / Pashto Resources</p>
447
+ <h1>Pashto Technology Resource Search</h1>
448
+ <p class="subtitle">
449
+ Filter verified and candidate resources for ASR, TTS, NLP, translation, tools, and benchmark work.
450
+ Share search states with URL parameters and jump quickly to high-intent pages.
451
+ </p>
452
+ </div>
453
+ <div class="stat-row" aria-label="Catalog metrics">
454
+ <div class="stat"><strong id="statTotal">-</strong><span>Total</span></div>
455
+ <div class="stat"><strong id="statVerified">-</strong><span>Verified</span></div>
456
+ <div class="stat"><strong id="statTasks">-</strong><span>Task Tags</span></div>
457
+ </div>
458
+ </div>
459
+ <nav class="quick-links" aria-label="Quick links">
460
+ <a class="pill-link" href="../">Docs Home</a>
461
+ <a class="pill-link" href="../pashto_datasets.md">Datasets Page</a>
462
+ <a class="pill-link" href="../pashto_asr.md">ASR Page</a>
463
+ <a class="pill-link" href="../pashto_tts.md">TTS Page</a>
464
+ <a class="pill-link" href="https://github.com/Musawer1214/pashto-language-resources">GitHub</a>
465
+ <a class="pill-link" href="https://huggingface.co/Musawer14/pashto-language-resources">Hugging Face</a>
466
+ </nav>
467
+ </header>
468
+
469
+ <section class="toolbar panel" aria-label="Search controls">
470
  <div class="controls">
471
+ <div class="field search">
472
  <label for="q">Search</label>
473
+ <input id="q" type="search" placeholder="Try: asr, pbt_arab, translation, speech, benchmark" autocomplete="off">
474
  </div>
475
  <div class="field">
476
  <label for="category">Category</label>
 
488
  <label for="status">Status</label>
489
  <select id="status"></select>
490
  </div>
491
+ <div class="field">
492
+ <label for="sort">Sort</label>
493
+ <select id="sort">
494
+ <option value="relevance">Relevance</option>
495
+ <option value="title_asc">Title (A-Z)</option>
496
+ <option value="title_desc">Title (Z-A)</option>
497
+ <option value="source_asc">Source (A-Z)</option>
498
+ </select>
499
+ </div>
500
+ </div>
501
+
502
+ <div class="action-row">
503
+ <div class="group" role="group" aria-label="Result view mode">
504
+ <button type="button" class="btn active" id="viewGrid">Grid view</button>
505
+ <button type="button" class="btn" id="viewList">List view</button>
506
+ </div>
507
+ <div class="group">
508
+ <button type="button" class="btn light" id="clearFilters">Clear filters</button>
509
+ <button type="button" class="btn brand" id="copyLink">Copy search link</button>
510
+ </div>
511
+ </div>
512
+
513
+ <div class="intent-row" aria-label="Quick intent filters">
514
+ <button type="button" class="intent" data-intent="datasets">Datasets</button>
515
+ <button type="button" class="intent" data-intent="asr">ASR</button>
516
+ <button type="button" class="intent" data-intent="tts">TTS</button>
517
+ <button type="button" class="intent" data-intent="nlp">NLP</button>
518
+ <button type="button" class="intent" data-intent="mt">Translation</button>
519
+ <button type="button" class="intent" data-intent="verified">Verified only</button>
520
  </div>
521
  </section>
522
 
523
+ <div class="summary" aria-live="polite">
524
  <span id="countText">Loading resources...</span>
525
  <span class="badge" id="generatedAt">Catalog timestamp: -</span>
526
  </div>
527
 
528
+ <section class="crawl" aria-label="Resource categories and crawlable links">
529
+ Browse Pashto resource categories directly:
530
+ <ul>
 
 
 
 
 
531
  <li><a href="https://github.com/Musawer1214/pashto-language-resources/blob/main/resources/datasets/README.md">Pashto datasets</a></li>
532
  <li><a href="https://github.com/Musawer1214/pashto-language-resources/blob/main/resources/models/README.md">Pashto models</a></li>
533
  <li><a href="https://github.com/Musawer1214/pashto-language-resources/blob/main/resources/benchmarks/README.md">Pashto benchmarks</a></li>
 
537
  </section>
538
 
539
  <noscript>
540
+ JavaScript is needed for filtering. Category links above remain fully accessible.
541
  </noscript>
542
 
543
+ <ul id="results" class="results grid"></ul>
544
  </main>
545
 
546
  <script>
547
  const state = {
548
  all: [],
549
+ filtered: [],
550
+ view: "grid"
551
  };
552
 
553
  const els = {
 
556
  source: document.getElementById("source"),
557
  task: document.getElementById("task"),
558
  status: document.getElementById("status"),
559
+ sort: document.getElementById("sort"),
560
  results: document.getElementById("results"),
561
  countText: document.getElementById("countText"),
562
+ generatedAt: document.getElementById("generatedAt"),
563
+ statTotal: document.getElementById("statTotal"),
564
+ statVerified: document.getElementById("statVerified"),
565
+ statTasks: document.getElementById("statTasks"),
566
+ viewGrid: document.getElementById("viewGrid"),
567
+ viewList: document.getElementById("viewList"),
568
+ clearFilters: document.getElementById("clearFilters"),
569
+ copyLink: document.getElementById("copyLink"),
570
+ intents: [...document.querySelectorAll(".intent")]
571
  };
572
 
573
+ function esc(value) {
574
+ return String(value || "")
575
+ .replace(/&/g, "&amp;")
576
+ .replace(/</g, "&lt;")
577
+ .replace(/>/g, "&gt;")
578
+ .replace(/"/g, "&quot;")
579
+ .replace(/'/g, "&#39;");
580
+ }
581
+
582
  function uniqSorted(values) {
583
  return [...new Set(values.filter(Boolean))].sort((a, b) => a.localeCompare(b));
584
  }
 
590
  allOption.textContent = allLabel;
591
  select.appendChild(allOption);
592
  for (const opt of options) {
593
+ const entry = document.createElement("option");
594
+ entry.value = opt;
595
+ entry.textContent = opt;
596
+ select.appendChild(entry);
597
  }
598
  }
599
 
600
+ function updateMetrics() {
601
+ const verified = state.all.filter((r) => r.status === "verified").length;
602
+ const tasks = uniqSorted(state.all.flatMap((r) => r.tasks || [])).length;
603
+ els.statTotal.textContent = String(state.all.length);
604
+ els.statVerified.textContent = String(verified);
605
+ els.statTasks.textContent = String(tasks);
606
+ }
607
+
608
+ function setView(view) {
609
+ state.view = view === "list" ? "list" : "grid";
610
+ els.results.classList.toggle("grid", state.view === "grid");
611
+ els.results.classList.toggle("list", state.view === "list");
612
+ els.viewGrid.classList.toggle("active", state.view === "grid");
613
+ els.viewList.classList.toggle("active", state.view === "list");
614
+ syncUrl();
615
+ }
616
+
617
  function matchesQuery(resource, query) {
618
  if (!query) return true;
619
  const hay = [
 
631
  return hay.includes(query);
632
  }
633
 
634
+ function sortItems(items) {
635
+ const mode = els.sort.value;
636
+ const sorted = [...items];
637
+ if (mode === "title_asc") {
638
+ sorted.sort((a, b) => (a.title || "").localeCompare(b.title || ""));
639
+ } else if (mode === "title_desc") {
640
+ sorted.sort((a, b) => (b.title || "").localeCompare(a.title || ""));
641
+ } else if (mode === "source_asc") {
642
+ sorted.sort((a, b) => (a.source || "").localeCompare(b.source || "") || (a.title || "").localeCompare(b.title || ""));
643
+ } else {
644
+ sorted.sort((a, b) => {
645
+ const av = a.status === "verified" ? 0 : 1;
646
+ const bv = b.status === "verified" ? 0 : 1;
647
+ if (av !== bv) return av - bv;
648
+ return (a.title || "").localeCompare(b.title || "");
649
+ });
650
+ }
651
+ return sorted;
652
+ }
653
+
654
  function applyFilters() {
655
  const q = els.q.value.trim().toLowerCase();
656
  const category = els.category.value;
 
658
  const task = els.task.value;
659
  const status = els.status.value;
660
 
661
+ state.filtered = sortItems(state.all.filter((resource) => {
662
  if (!matchesQuery(resource, q)) return false;
663
  if (category && resource.category !== category) return false;
664
  if (source && resource.source !== source) return false;
665
  if (status && resource.status !== status) return false;
666
  if (task && !(resource.tasks || []).includes(task)) return false;
667
  return true;
668
+ }));
669
 
670
  renderResults();
671
+ syncUrl();
672
  }
673
 
674
  function chip(label, cls) {
675
+ return `<span class="chip ${cls}">${esc(label)}</span>`;
676
  }
677
 
678
  function renderResults() {
 
680
  els.countText.textContent = `${items.length} result${items.length === 1 ? "" : "s"} of ${state.all.length}`;
681
 
682
  if (!items.length) {
683
+ els.results.innerHTML = '<li class="empty">No matches. Try broadening filters or clearing one filter at a time.</li>';
684
  return;
685
  }
686
 
687
+ els.results.innerHTML = items.map((resource) => {
688
+ const title = esc(resource.title || "Untitled resource");
689
+ const url = esc(resource.url || "#");
690
+ const summary = esc(resource.summary || "No summary provided.");
691
+ const primaryUse = esc(resource.primary_use || "n/a");
692
+ const evidenceText = esc(resource.evidence_text || "evidence link");
693
+ const evidenceUrl = esc(resource.evidence_url || resource.url || "#");
694
+ const tasks = (resource.tasks || []).map((t) => esc(t)).join(", ") || "n/a";
695
+
696
+ return `
697
+ <li class="card">
698
+ <div class="chips">
699
+ ${chip(resource.category || "unknown", "category")}
700
+ ${chip(resource.source || "unknown", "source")}
701
+ ${chip(resource.status || "unknown", "status")}
702
+ </div>
703
+ <h2 class="title"><a href="${url}" target="_blank" rel="noreferrer">${title}</a></h2>
704
+ <p class="text">${summary}</p>
705
+ <p class="text"><strong>Primary use:</strong> ${primaryUse}</p>
706
+ <p class="tasks"><strong>Tasks:</strong> ${tasks}</p>
707
+ <div class="meta-links">
708
+ <a class="mini-link" href="${url}" target="_blank" rel="noreferrer">Open resource</a>
709
+ <a class="mini-link" href="${evidenceUrl}" target="_blank" rel="noreferrer">Pashto evidence: ${evidenceText}</a>
710
+ </div>
711
+ </li>
712
+ `;
713
+ }).join("");
714
+ }
715
+
716
+ function syncUrl() {
717
+ const params = new URLSearchParams();
718
+ if (els.q.value.trim()) params.set("q", els.q.value.trim());
719
+ if (els.category.value) params.set("category", els.category.value);
720
+ if (els.source.value) params.set("source", els.source.value);
721
+ if (els.task.value) params.set("task", els.task.value);
722
+ if (els.status.value) params.set("status", els.status.value);
723
+ if (els.sort.value && els.sort.value !== "relevance") params.set("sort", els.sort.value);
724
+ if (state.view !== "grid") params.set("view", state.view);
725
+
726
+ const next = `${window.location.pathname}${params.toString() ? `?${params.toString()}` : ""}`;
727
+ window.history.replaceState({}, "", next);
728
+ }
729
+
730
+ function applyUrlState() {
731
+ const params = new URLSearchParams(window.location.search);
732
+ if (params.get("q")) els.q.value = params.get("q");
733
+ if (params.get("category")) els.category.value = params.get("category");
734
+ if (params.get("source")) els.source.value = params.get("source");
735
+ if (params.get("task")) els.task.value = params.get("task");
736
+ if (params.get("status")) els.status.value = params.get("status");
737
+ if (params.get("sort")) els.sort.value = params.get("sort");
738
+ if (params.get("view")) setView(params.get("view"));
739
+ }
740
+
741
+ function clearFilters() {
742
+ els.q.value = "";
743
+ els.category.value = "";
744
+ els.source.value = "";
745
+ els.task.value = "";
746
+ els.status.value = "";
747
+ els.sort.value = "relevance";
748
+ setView("grid");
749
+ applyFilters();
750
+ }
751
+
752
+ function applyIntent(intent) {
753
+ if (intent === "datasets") {
754
+ els.category.value = "dataset";
755
+ els.task.value = "";
756
+ els.q.value = "";
757
+ } else if (intent === "asr") {
758
+ els.task.value = "asr";
759
+ } else if (intent === "tts") {
760
+ els.task.value = "tts";
761
+ } else if (intent === "nlp") {
762
+ els.task.value = "nlp";
763
+ } else if (intent === "mt") {
764
+ els.task.value = "";
765
+ els.q.value = "translation";
766
+ } else if (intent === "verified") {
767
+ els.status.value = "verified";
768
+ }
769
+ applyFilters();
770
+ }
771
+
772
+ async function copySearchLink() {
773
+ try {
774
+ await navigator.clipboard.writeText(window.location.href);
775
+ els.copyLink.textContent = "Link copied";
776
+ setTimeout(() => { els.copyLink.textContent = "Copy search link"; }, 1200);
777
+ } catch (_error) {
778
+ els.copyLink.textContent = "Copy failed";
779
+ setTimeout(() => { els.copyLink.textContent = "Copy search link"; }, 1200);
780
+ }
781
  }
782
 
783
  async function load() {
 
785
  const res = await fetch("./resources.json", { cache: "no-store" });
786
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
787
  const payload = await res.json();
788
+
789
  state.all = payload.resources || [];
 
790
 
791
  fillSelect(els.category, uniqSorted(state.all.map((r) => r.category)), "All categories");
792
  fillSelect(els.source, uniqSorted(state.all.map((r) => r.source)), "All sources");
793
  fillSelect(els.status, uniqSorted(state.all.map((r) => r.status)), "All statuses");
794
+ fillSelect(els.task, uniqSorted(state.all.flatMap((r) => r.tasks || [])), "All tasks");
795
+
796
+ updateMetrics();
 
 
797
 
798
  const generated = payload.generated_on ? new Date(payload.generated_on) : null;
799
  els.generatedAt.textContent = generated && !Number.isNaN(generated.getTime())
800
  ? `Catalog timestamp: ${generated.toISOString()}`
801
  : "Catalog timestamp: unknown";
802
 
803
+ applyUrlState();
804
  applyFilters();
805
  } catch (err) {
806
  els.countText.textContent = "Failed to load resources";
807
+ els.results.innerHTML = `<li class="empty">Could not load search data. ${esc(String(err))}</li>`;
808
  }
809
  }
810
 
811
+ [els.q, els.category, els.source, els.task, els.status, els.sort].forEach((el) => {
812
  el.addEventListener("input", applyFilters);
813
  el.addEventListener("change", applyFilters);
814
  });
815
 
816
+ els.viewGrid.addEventListener("click", () => setView("grid"));
817
+ els.viewList.addEventListener("click", () => setView("list"));
818
+ els.clearFilters.addEventListener("click", clearFilters);
819
+ els.copyLink.addEventListener("click", copySearchLink);
820
+ els.intents.forEach((button) => {
821
+ button.addEventListener("click", () => applyIntent(button.dataset.intent));
822
+ });
823
+
824
  load();
825
  </script>
826
  </body>
827
  </html>
 
pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
 
5
  [project]
6
  name = "pashto-language-resources"
7
- version = "0.1.0"
8
  description = "Open Pashto language resources for ASR, TTS, NLP, and benchmarks"
9
  requires-python = ">=3.10"
10
  readme = "README.md"
@@ -35,3 +35,4 @@ python_files = ["test_*.py"]
35
  packages = []
36
 
37
 
 
 
4
 
5
  [project]
6
  name = "pashto-language-resources"
7
+ version = "1.0.0"
8
  description = "Open Pashto language resources for ASR, TTS, NLP, and benchmarks"
9
  requires-python = ">=3.10"
10
  readme = "README.md"
 
35
  packages = []
36
 
37
 
38
+