update .gitignore, enhance README, implement Pexels API integration, and improve page generation logic

This commit is contained in:
2026-05-17 21:56:54 +02:00
parent ed7eeda24c
commit 135e1ac682
5 changed files with 411 additions and 91 deletions

129
Pexels.md Normal file
View File

@@ -0,0 +1,129 @@
---
name: pexels-api
description: Domain knowledge for the Pexels stock photo and video API.
---
# Pexels API
Pexels provides a large library of high-quality stock photos and videos licensed under the Pexels License (personal and commercial use, no attribution required but appreciated).
## Data Model
### Photo Resource
| Field | Type | Description |
|---|---|---|
| `id` | integer | Unique numeric photo identifier |
| `width` | integer | Original width in pixels |
| `height` | integer | Original height in pixels |
| `url` | string | Pexels web page URL for this photo |
| `photographer` | string | Photographer display name |
| `photographer_url` | string | Photographer's Pexels profile URL |
| `photographer_id` | integer | Photographer's numeric ID |
| `avg_color` | string | Hex color (e.g. `#978E82`), useful as image placeholder |
| `alt` | string | Alt text describing the photo |
| `liked` | boolean | Whether the current user liked this photo |
| `src` | object | Pre-sized image URLs (see below) |
**`src` object sizes:**
| Key | Dimensions | Notes |
|---|---|---|
| `original` | Full resolution | Matches `width`×`height` |
| `large2x` | W 940 × H 650 @2x | Retina-ready |
| `large` | W 940 × H 650 | Standard large |
| `medium` | H 350 (proportional) | Proportionally scaled |
| `small` | H 130 (proportional) | Thumbnail |
| `portrait` | W 800 × H 1200 | Cropped portrait |
| `landscape` | W 1200 × H 627 | Cropped landscape |
| `tiny` | W 280 × H 200 | Smallest preview |
### Video Resource
| Field | Type | Description |
|---|---|---|
| `id` | integer | Unique numeric video identifier |
| `width` | integer | Original width in pixels |
| `height` | integer | Original height in pixels |
| `url` | string | Pexels web page URL for this video |
| `image` | string | Video screenshot/poster URL |
| `duration` | integer | Duration in seconds |
| `user` | object | Videographer: `id` (int), `name` (str), `url` (str) |
| `video_files` | array | Available quality versions (see below) |
| `video_pictures` | array | Preview thumbnails: `id`, `picture` (URL), `nr` (index) |
**`video_files` element:**
| Field | Type | Description |
|---|---|---|
| `id` | integer | File variant ID |
| `quality` | string/null | `"hd"`, `"sd"`, `"hls"`, or null |
| `file_type` | string | MIME type (e.g. `video/mp4`) |
| `width` | integer/null | Width (null for HLS) |
| `height` | integer/null | Height (null for HLS) |
| `fps` | number | Frames per second |
| `link` | string | Direct download URL |
| `size` | integer | File size in bytes |
### Collection Resource
| Field | Type | Description |
|---|---|---|
| `id` | string | Alphanumeric collection identifier (e.g. `"8xntbhr"`) |
| `title` | string | Collection name |
| `description` | string/null | Optional description |
| `private` | boolean | Whether the collection is private |
| `media_count` | integer | Total photos + videos |
| `photos_count` | integer | Number of photos |
| `videos_count` | integer | Number of videos |
## Entity Relationships
- A **Photo** belongs to a **Photographer** (via `photographer_id`).
- A **Video** belongs to a **User/Videographer** (via `user.id`).
- A **Collection** contains mixed **Photo** and **Video** objects. Collection media items include an extra `type` field (`"Photo"` or `"Video"`) to discriminate.
- Collections are read-only via API — create/edit on pexels.com, iOS, or Android app.
## API Endpoints
### Photos (base: `/v1/`)
| Endpoint | Method | Description |
|---|---|---|
| `/v1/search?query=...` | GET | Full-text search with `orientation`, `size`, `color`, `locale` filters |
| `/v1/curated` | GET | Trending editor-curated photos, updated hourly |
| `/v1/photos/:id` | GET | Single Photo by numeric ID |
### Videos (base: `/v1/videos/`)
| Endpoint | Method | Description |
|---|---|---|
| `/v1/videos/search?query=...` | GET | Full-text search with `orientation`, `size`, `locale` filters |
| `/v1/videos/popular` | GET | Trending videos with `min_width`, `min_height`, `min_duration`, `max_duration` filters |
| `/v1/videos/videos/:id` | GET | Single Video by numeric ID |
### Collections (base: `/v1/collections/`)
| Endpoint | Method | Description |
|---|---|---|
| `/v1/collections/featured` | GET | Editor-curated themed collections |
| `/v1/collections` | GET | Your saved collections |
| `/v1/collections/:id` | GET | All media in a collection, filterable by `type` (photos/videos) and `sort` (asc/desc) |
## Pagination
All list endpoints accept `page` (default 1) and `per_page` (default 15, max 80). Responses include `page`, `per_page`, `total_results`, and optional `next_page`/`prev_page` URL strings. The `total_results` for search endpoints is capped at a high number (e.g. 8000) even when more results exist.
## Rate Limits
- **Default**: 200 requests/hour, 20,000 requests/month.
- **Response headers**: `X-Ratelimit-Limit` (monthly quota), `X-Ratelimit-Remaining`, `X-Ratelimit-Reset` (UNIX timestamp for monthly rollover).
- Rate limit headers are only returned on successful (2xx) responses, not on 429 errors.
- Higher limits available with proper attribution — contact api@pexels.com.
## Search Tips & Gotchas
- Queries can be broad ("nature", "people") or specific ("group of people working").
- **Color filter** (photos only): Named colors (red, orange, yellow, green, turquoise, blue, violet, pink, brown, black, gray, white) or hex codes (e.g. `#ffffff`).
- **Locale** affects search relevance for non-English queries. Supported: en-US, pt-BR, es-ES, ca-ES, de-DE, it-IT, fr-FR, sv-SE, id-ID, pl-PL, ja-JP, zh-TW, zh-CN, ko-KR, th-TH, nl-NL, hu-HU, vi-VN, cs-CZ, da-DK, fi-FI, uk-UA, el-GR, ro-RO, nb-NO, sk-SK, tr-TR, ru-RU.
- **Size filter** means different things: for photos, `large` = 24MP+, `medium` = 12MP+, `small` = 4MP+; for videos, `large` = 4K, `medium` = Full HD, `small` = HD.
- Video `quality` field may be null for newer video files — use `width`/`height` to determine actual resolution.
- Collection IDs are alphanumeric strings (not integers like photo/video IDs).
- The deprecated video base URL `https://api.pexels.com/videos/` still works but should not be used — use `/v1/videos/` instead.
## Attribution
Best practice: link to the photo/video page on Pexels and credit the photographer/videographer (e.g. "Photo by John Doe on Pexels"). Use the `url` field from the response for attribution links.