mirror of
https://github.com/SamyRai/tercul-backend.git
synced 2025-12-27 05:11:34 +00:00
This commit introduces a new blog feature by implementing a JSON schema for blog posts and providing five example content files. Key changes: - Created a new directory structure for schemas and content (`schemas/`, `content/blog/`). - Implemented a JSON schema for blog posts, split into `blog.json` and `_defs.json` for reusability. - Added five example blog post files with full, realistic content. - Included a Python script (`validate.py`) to validate the example content against the schema.
240 lines
5.6 KiB
JSON
240 lines
5.6 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "https://example.com/schemas/blog.json",
|
|
"title": "Blog Post",
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"contentTypeSlug",
|
|
"title",
|
|
"slug",
|
|
"status",
|
|
"content",
|
|
"languageCode",
|
|
"isDefault"
|
|
],
|
|
"properties": {
|
|
"contentTypeSlug": {
|
|
"type": "string",
|
|
"enum": ["blog"]
|
|
},
|
|
"title": {
|
|
"type": "string",
|
|
"minLength": 1,
|
|
"maxLength": 200
|
|
},
|
|
"slug": {
|
|
"type": "string",
|
|
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
|
|
"minLength": 3,
|
|
"maxLength": 200
|
|
},
|
|
"status": {
|
|
"type": "string",
|
|
"enum": ["planned", "draft", "scheduled", "published", "archived"]
|
|
},
|
|
"content": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"excerpt",
|
|
"content",
|
|
"publishDate",
|
|
"author",
|
|
"tags",
|
|
"meta_title",
|
|
"meta_description"
|
|
],
|
|
"properties": {
|
|
"excerpt": {
|
|
"type": "string",
|
|
"minLength": 1
|
|
},
|
|
"content": {
|
|
"type": "string"
|
|
},
|
|
"publishDate": {
|
|
"type": "string",
|
|
"format": "date"
|
|
},
|
|
"author": {
|
|
"type": "string",
|
|
"minLength": 1
|
|
},
|
|
"tags": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string",
|
|
"minLength": 1
|
|
},
|
|
"uniqueItems": false
|
|
},
|
|
"meta_title": {
|
|
"type": "string",
|
|
"minLength": 1
|
|
},
|
|
"meta_description": {
|
|
"type": "string",
|
|
"minLength": 1
|
|
}
|
|
}
|
|
},
|
|
"languageCode": {
|
|
"type": "string",
|
|
"pattern": "^[a-z]{2}(?:-[A-Z]{2})?$"
|
|
},
|
|
"isDefault": {
|
|
"type": "boolean"
|
|
},
|
|
"id": {
|
|
"type": "string",
|
|
"pattern": "^[a-zA-Z0-9_-]{3,200}$"
|
|
},
|
|
"translation_group_id": {
|
|
"type": "string",
|
|
"pattern": "^[a-zA-Z0-9_-]{3,200}$"
|
|
},
|
|
"lifecycle": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"state": {
|
|
"type": "string",
|
|
"enum": ["planned", "draft", "scheduled", "published", "archived"]
|
|
},
|
|
"scheduled_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"published_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"timezone": {
|
|
"type": "string",
|
|
"minLength": 1
|
|
}
|
|
}
|
|
},
|
|
"seo": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"canonical": {
|
|
"type": "string",
|
|
"format": "uri"
|
|
},
|
|
"og_title": {
|
|
"type": "string"
|
|
},
|
|
"og_description": {
|
|
"type": "string"
|
|
},
|
|
"og_image": {
|
|
"$ref": "_defs.json#/$defs/imageAsset"
|
|
},
|
|
"twitter_card": {
|
|
"type": "string",
|
|
"enum": ["summary", "summary_large_image"]
|
|
},
|
|
"json_ld": {
|
|
"type": "object",
|
|
"additionalProperties": true
|
|
}
|
|
}
|
|
},
|
|
"taxonomy": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"categories": {
|
|
"type": "array",
|
|
"items": { "type": "string" },
|
|
"uniqueItems": true
|
|
},
|
|
"series": {
|
|
"type": "string"
|
|
},
|
|
"featured": {
|
|
"type": "boolean"
|
|
},
|
|
"pin_until": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
}
|
|
}
|
|
},
|
|
"relations": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"related_services": {
|
|
"type": "array",
|
|
"items": { "type": "string" },
|
|
"uniqueItems": true
|
|
},
|
|
"related_posts": {
|
|
"type": "array",
|
|
"items": { "type": "string" },
|
|
"uniqueItems": true
|
|
}
|
|
}
|
|
},
|
|
"sources": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "_defs.json#/$defs/source"
|
|
}
|
|
},
|
|
"assets": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"hero_image": {
|
|
"$ref": "_defs.json#/$defs/imageAsset"
|
|
},
|
|
"attachments": {
|
|
"type": "array",
|
|
"items": { "$ref": "_defs.json#/$defs/attachment" }
|
|
}
|
|
}
|
|
},
|
|
"audit": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"created_at": { "type": "string", "format": "date-time" },
|
|
"updated_at": { "type": "string", "format": "date-time" },
|
|
"created_by": { "type": "string" },
|
|
"updated_by": { "type": "string" },
|
|
"revision": { "type": "integer", "minimum": 0 },
|
|
"fact_checked": { "type": "boolean" },
|
|
"legal_reviewed": { "type": "boolean" },
|
|
"change_notes": { "type": "string" }
|
|
}
|
|
},
|
|
"metrics": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"views": { "type": "integer", "minimum": 0 },
|
|
"avg_read_time_sec": { "type": "integer", "minimum": 0 },
|
|
"cta_clicks": { "type": "integer", "minimum": 0 }
|
|
}
|
|
},
|
|
"readability": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"reading_time_minutes_est": { "type": "integer", "minimum": 0 },
|
|
"word_count": { "type": "integer", "minimum": 0 },
|
|
"summary_bullets": {
|
|
"type": "array",
|
|
"items": { "type": "string" },
|
|
"maxItems": 12
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|