Keystatic is a Git-backed CMS that stores content as MDX files directly in the repository — there is no external database. Blog posts live inDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/constanza101/borrissol/llms.txt
Use this file to discover all available pages before exploring further.
src/content/blog/ as .mdoc files alongside their cover images in public/blog/images/. Every publish action becomes a GitHub Pull Request, and merging that PR triggers a Netlify deployment. This keeps the entire content history in git, makes rollbacks trivial, and ensures the CMS never drifts out of sync with the codebase.
Storage modes
Keystatic switches storage backends based on theNODE_ENV environment variable. The logic lives at the top of keystatic.config.ts:
| Mode | When active | How it works |
|---|---|---|
| Local | NODE_ENV !== 'production' (i.e. npm run dev) | Reads and writes directly to the local filesystem. No authentication required — navigate to http://localhost:4321/keystatic and edit freely. |
| GitHub | NODE_ENV === 'production' (Netlify deployment) | Commits content to the constanza101/borrissol GitHub repository. New entries open a Pull Request on a branch prefixed keystatic/. Requires Keystatic Cloud authentication. |
Local storage (development)
In local mode Keystatic is effectively a local GUI for editing files undersrc/content/blog/. Changes are written directly to disk — commit or discard them with git as you would any other file.
GitHub storage (production)
In production Keystatic authenticates via Keystatic Cloud (projectborrissol/borrissol) and uses the GitHub API to:
- Create a new branch with the prefix
keystatic/(e.g.keystatic/blog-nou-taller-tufting) - Commit the new or updated MDX file and any uploaded images to that branch
- Open a Pull Request against
main
Full configuration
keystatic.config.ts
Blog collection schema
Each blog entry has five fields:| Field key | Label in UI | Type | Notes |
|---|---|---|---|
title | Títol | fields.slug | Title text + auto-generated URL slug. The slug becomes the file name and the URL path (/blog/<slug>). |
summary | Resum | fields.text (multiline) | ≤ 160 characters. Used as the card excerpt on /blog and as meta description for the post page. |
publishedAt | Data de publicació | fields.date | Required. Displayed on the post and used for sort order. |
coverImage | Imatge destacada | fields.image | Saved to public/blog/images/[slug]/. Minimum 1200×630 px recommended for Open Graph. |
content | Contingut | fields.markdoc | The full post body in Markdoc (Markdown + optional custom tags). |
The blog is Catalan-only by design. There are no translated versions of blog posts. Non-Catalan
/es/blog, /en/blog, and /fr/blog URLs 301-redirect to /blog — see the redirects in astro.config.mjs.Author workflow: publishing a new post
Open the admin UI
Navigate to
https://borrissol.com/keystatic in your browser. Keystatic Cloud will prompt for authentication if you are not already signed in. (In local dev, no login is required — go to http://localhost:4321/keystatic.)Fill in the fields
Complete all five fields:
- Títol — the post title. The URL (slug) is filled automatically from the title; edit it manually if needed (lowercase, hyphens, no accents).
- Resum — a summary of up to 160 characters. This appears as the card blurb on the blog listing page and as the SEO meta description. The field validates the character limit in real time.
- Data de publicació — choose the date the post should appear to have been published.
- Imatge destacada — upload the cover image. Minimum recommended size: 1200 × 630 px (standard Open Graph dimensions). The image is saved to
public/blog/images/in the repository. - Contingut — write the post body using the rich-text Markdoc editor.
Save the entry
Click Save. In production mode, Keystatic creates a new branch (
keystatic/...) and commits the MDX file and any uploaded images to it, then opens a Pull Request on GitHub against main.Merge the Pull Request
Review the PR on github.com/constanza101/borrissol. Once satisfied, merge it. Netlify detects the push to
main and automatically deploys the updated site — the new post is live within a few minutes.Deploy and cost considerations
Cover image bandwidth
Cover images are stored inpublic/blog/images/[slug]/ and served directly from Netlify’s CDN. On the Personal plan, bandwidth is limited to ~50 GB/month (≈ 20 credits/GB). High-resolution images multiply quickly if the blog gets traffic. Optimise images before uploading:
- Use WebP or JPEG at 80–85% quality
- Resize to no wider than 2400 px before uploading
- Astro’s
<Picture>component will still generate AVIF/WebP variants at build time
Deploy previews for keystatic/* branches
Deploy previews for keystatic/ branches are disabled to avoid consuming credits on every draft save. Only merges to main trigger a production deploy.
Local dev workflow
Innpm run dev mode, Keystatic uses local storage. Editing posts in the admin UI at http://localhost:4321/keystatic writes files directly to disk with no authentication and no Netlify credits consumed. This is the recommended way to draft and proof content before committing.