{
  "id": "blog",
  "slug": "blog",
  "title": "Content Blog Backend",
  "description": "Publishing platform with posts, authors, categories, tags, threaded comments, pages, and media. Preview schema, APIs, permissions, and SDK examples — then clone into Console.",
  "version": "1.0.0",
  "checksum": "sha256:blog-v1-2026-07-24",
  "status": "verified",
  "edition": "both",
  "project_type": "general",
  "database_intent": "sqlite",
  "source": "console projectTemplates blog + Apito Engineering review",
  "reviewed_at": "2026-07-24",
  "architecture_notes": "Author-centric CMS. Posts relate to authors, categories, tags, comments, and media. Pages share authors and media.",
  "models": [
    {
      "name": "author",
      "label": "Author",
      "scope": "general",
      "fields": [
        { "identifier": "name", "label": "Name", "field_type": "text", "required": true },
        { "identifier": "bio", "label": "Bio", "field_type": "multiline" },
        { "identifier": "avatar", "label": "Avatar", "field_type": "media" }
      ]
    },
    {
      "name": "post",
      "label": "Post",
      "scope": "general",
      "fields": [
        { "identifier": "title", "label": "Title", "field_type": "text", "required": true },
        { "identifier": "slug", "label": "Slug", "field_type": "text", "required": true },
        { "identifier": "excerpt", "label": "Excerpt", "field_type": "multiline" },
        { "identifier": "body", "label": "Body", "field_type": "multiline", "required": true },
        { "identifier": "status", "label": "Status", "field_type": "list", "options": ["draft", "scheduled", "published"], "required": true },
        { "identifier": "published_at", "label": "Published At", "field_type": "date" },
        { "identifier": "seo_title", "label": "SEO Title", "field_type": "text" },
        { "identifier": "seo_description", "label": "SEO Description", "field_type": "multiline" }
      ]
    },
    {
      "name": "category",
      "label": "Category",
      "scope": "general",
      "fields": [
        { "identifier": "name", "label": "Name", "field_type": "text", "required": true },
        { "identifier": "slug", "label": "Slug", "field_type": "text", "required": true }
      ]
    },
    {
      "name": "tag",
      "label": "Tag",
      "scope": "general",
      "fields": [
        { "identifier": "name", "label": "Name", "field_type": "text", "required": true },
        { "identifier": "slug", "label": "Slug", "field_type": "text", "required": true }
      ]
    },
    {
      "name": "comment",
      "label": "Comment",
      "scope": "general",
      "fields": [
        { "identifier": "author_name", "label": "Author Name", "field_type": "text", "required": true },
        { "identifier": "body", "label": "Body", "field_type": "multiline", "required": true },
        { "identifier": "status", "label": "Status", "field_type": "list", "options": ["pending", "approved", "spam"], "required": true }
      ]
    },
    {
      "name": "media",
      "label": "Media",
      "scope": "general",
      "fields": [
        { "identifier": "title", "label": "Title", "field_type": "text" },
        { "identifier": "file", "label": "File", "field_type": "media", "required": true },
        { "identifier": "alt", "label": "Alt Text", "field_type": "text" }
      ]
    },
    {
      "name": "page",
      "label": "Page",
      "scope": "general",
      "fields": [
        { "identifier": "title", "label": "Title", "field_type": "text", "required": true },
        { "identifier": "slug", "label": "Slug", "field_type": "text", "required": true },
        { "identifier": "body", "label": "Body", "field_type": "multiline", "required": true }
      ]
    }
  ],
  "relations": [
    { "from": "author", "to": "post", "forward": "has_many", "reverse": "has_one" },
    { "from": "author", "to": "page", "forward": "has_many", "reverse": "has_one" },
    { "from": "post", "to": "category", "forward": "has_many", "reverse": "has_many" },
    { "from": "post", "to": "tag", "forward": "has_many", "reverse": "has_many" },
    { "from": "post", "to": "comment", "forward": "has_many", "reverse": "has_one" },
    { "from": "comment", "to": "comment", "forward": "has_many", "reverse": "has_one", "known_as": "parent" },
    { "from": "post", "to": "media", "forward": "has_many", "reverse": "has_one" },
    { "from": "page", "to": "media", "forward": "has_many", "reverse": "has_one" }
  ],
  "roles": [
    { "name": "admin", "is_admin": true, "permissions": ["post:*", "author:*", "category:*", "tag:*", "comment:*", "media:*", "page:*"] },
    { "name": "editor", "permissions": ["post:*", "author:read", "category:*", "tag:*", "comment:*", "media:*", "page:*"] },
    { "name": "public", "permissions": ["post:read", "author:read", "category:read", "tag:read", "comment:create", "page:read", "media:read"] }
  ],
  "graphql_operations": [
    { "name": "postList", "type": "query", "model": "post", "example": "query { postList(where: { status: { eq: \"published\" } }) { id data { title slug } } }" },
    { "name": "createPost", "type": "mutation", "model": "post", "example": "mutation($payload: JSON!) { createPost(payload: $payload) { id } }" },
    { "name": "commentList", "type": "query", "model": "comment", "example": "query { commentList(limit: 50) { id data { author_name body status } } }" }
  ],
  "rest_endpoints": [
    { "method": "GET", "path": "/secured/rest/post", "description": "List posts" },
    { "method": "POST", "path": "/secured/rest/post", "description": "Create post" },
    { "method": "GET", "path": "/secured/rest/comment", "description": "List comments" }
  ],
  "sdk_examples": [
    {
      "language": "javascript",
      "title": "List published posts",
      "code": "const posts = await client.query(`query { postList(where: { status: { eq: \"published\" } }) { id data { title slug excerpt } } }`);"
    },
    {
      "language": "flutter",
      "title": "Fetch posts",
      "code": "final posts = await client.query('''query { postList(limit: 20) { id data { title slug } } }''');"
    },
    {
      "language": "go",
      "title": "Create post",
      "code": "id, err := client.Create(\"post\", map[string]any{\"title\": \"Hello\", \"slug\": \"hello\", \"status\": \"draft\", \"body\": \"...\"})"
    }
  ],
  "limitations": [
    "Static verified preview only.",
    "Clone creates a reviewable Console draft; publish is human-gated."
  ],
  "clone_requirements": ["Apito Console account", "Project create permission"],
  "smoke_tests": ["postList filters published posts", "comment create requires public role"],
  "experience": {
    "experience_type": "playground",
    "preview_modules": ["overview", "schema", "erd", "graphql", "rest", "permissions", "sdk", "download"],
    "cta_label": "Clone this backend",
    "handoff_policy": "signed_preview"
  }
}
