All blog data access in the Hector Portfolio is funnelled through a single static class:Documentation Index
Fetch the complete documentation index at: https://mintlify.com/iwinser117/react-portafolio/llms.txt
Use this file to discover all available pages before exploring further.
BlogService, defined in src/services/blogService.js. The class imports src/data/posts.json at module level and provides async methods that mirror what a real REST API would expose — complete with simulated network latency. Swapping in a live backend later requires changing only this file.
Data Source
BlogService imports src/data/posts.json directly at the top of the module:
postsData itself.
src/data/posts.json currently contains one live post: “Consumo de API Flow de SAP Build desde Bruno” (slug: consumo-api-sap-build-bruno, category: SAP). Add new post objects to this array to make them available through every BlogService method immediately.
The Post Type
Every method returns Post objects (or arrays of them). The shape is defined by src/data/posts.json and documented in EXAMPLE_POST.json:
Static Methods
BlogService.getAllPosts()
date descending (newest first). Simulates a 300 ms network delay before resolving.
BlogService.getPostBySlug(slug)
post.slug === slug. Throws Error('Post no encontrado') if no match exists. Use inside a try/catch or let the calling hook surface the error.
The URL-safe slug string that uniquely identifies the post, e.g.
"consumo-api-sap-build-bruno".BlogService.getPostsByCategory(category)
post.category exactly matches the provided string. Returns an empty array if no posts belong to that category.
Category label to filter by, e.g.
"SAP".BlogService.getPostsByTag(tag)
post.tags.includes(tag). The comparison is exact (not case-insensitive).
A single tag string to match against each post’s
tags array, e.g. "OAuth2".BlogService.getCategories()
Set internally to guarantee uniqueness. Simulates a 200 ms delay.
BlogService.getTags()
post.tags arrays from every post, then deduplicates them with Set. Returns a single unique list of all tags in the data set. Simulates a 200 ms delay.
BlogService.searchPosts(query)
title, excerpt, and the tags array. A post is included in results if any one of those three fields contains the query string.
The search term. Matched case-insensitively against
title, excerpt, and each entry in tags.BlogService.addComment(slug, comment)
Comment object. The comment is not persisted — in the current implementation it is returned to the caller but not appended to postsData. Persistence should be handled by a backend endpoint in production.
Slug of the post the comment belongs to.
Display name of the commenter. Throws
Error('El nombre es requerido') if absent.Comment body text. Throws
Error('El comentario es requerido') if absent, or Error('El comentario es muy corto') if fewer than 3 characters.Optional commenter email. Stored as
null if not provided.Auto-generated ID using
comment-{Date.now()}.Commenter’s display name.
Email address, or
null if not provided.The comment body.
ISO 8601 date string for today’s date (date portion only, e.g.
"2026-02-05").Always
false on creation — moderation is required before the comment is shown publicly.BlogService.incrementViewCount(slug)
views counter in-memory. The change is not persisted to disk or any external store — it resets on every page reload. Simulates a 200 ms delay. Does not throw if the post is not found; the error is swallowed with console.error.
The Simulated Delay
Each method uses an internal
delay(ms) helper before resolving. The exact delays are: getAllPosts, getPostBySlug, getPostsByCategory, getPostsByTag, and searchPosts each use 300 ms; getCategories, getTags, and incrementViewCount use 200 ms; addComment uses 500 ms to simulate a heavier write operation. This intentional pause mimics real API latency so that loading states in the UI are visible during development.When you connect a real backend, replace each await delay(ms) with the appropriate fetch() (or Axios / SDK) call. No other code needs to change — the public API surface of BlogService stays identical.Replacing with a Real API
When you are ready to connect a live REST backend, updategetAllPosts() as a model for all other methods:
await delay(...), replace the postsData operation with a fetch() call to the corresponding endpoint, and propagate HTTP errors by checking response.ok. The hooks in src/hooks/useBlog.js require zero changes because they depend only on the BlogService interface, not its implementation.