Downloads
Everything Grav
Download Grav
Grav Core is the base package with core functionality and a few essential starting pages. Grav Core + Admin also includes the Administration Panel plugin. Both are easy to get started with — check out our Basic Tutorial and Guide to the Administration Panel.
Latest stable release
Production-ready. The version we recommend for every new site and every upgrade of an existing one.
Get Started
1
Quick installation
- Download either the Grav Core or Grav Core + Admin2 plugin installation package.
- Extract the zip file into your webroot.
- Point your browser at your local webserver:
http://yoursite.com
2
How to install the Admin2 plugin
If you have not already installed the admin plugin, you can do so easily with GPM:
$
This will install the admin plugin plus its dependencies (api & login). After this is complete, point your browser to your Grav installation and you will be prompted to create a new admin user.
Changelog
v2.2.28
Latest
1 day ago
-
Browser::isHuman()no longer counts link-preview fetchers (such asfacebookexternalhit, which loads a page each time a shared link or ad is shown), AI fetchers (ChatGPT-User,ClaudeBot,PerplexityBotand others), uptime and monitoring services, and headless or auditing tools like HeadlessChrome and Lighthouse as people, so page statistics stop counting requests nobody made. Facebook's and Instagram's in-app browsers are real visitors and stay human
v2.2.27 3 days ago
-
- Showing the same image twice with different
derivatives()ranges, for example in two modules on one page, no longer stretches the second set of responsive images, and the second set can now go up to the full width of the original #4389 - Cropping or resizing an image after
derivatives(), such asderivatives(400, 800, 400).cropZoom(300, 300), scales its responsive images down with it instead of making them larger than the image itself - Links and images to media files with
#,?or%in their names work again, written percent-encoded (Invoice%20%2312.pdf) or in angle brackets. Media URLs now come out percent-encoded too, so a space is%20#4388
- Showing the same image twice with different
v2.2.26 4 days ago
-
- When PHP can't start sessions (for example,
session.save_pathpoints at a folder that no longer exists after a server move), Grav now writes the reason tograv.loginstead of showing "Session corruption detected" on every page to every visitor - A session holding an unusable user object is now actually replaced with a fresh one, instead of crashing every page with an error until the visitor clears their cookies
- The debug bar no longer reports Twig deprecations on every page, one for Grav's sandbox source policy and one for how page content Twig is rendered #4387
- When PHP can't start sessions (for example,
v2.2.25 4 days ago
-
- A scheduled job that its plugin switches off with
when()(such as YetiSearch Pro's embed job while semantic search is off) is no longer run and recorded as a failure each time it comes due. The scheduler leaves it out of the run and out of the health check, andJob::passesWhen()tells other tools whether a job's condition lets it run - [security] A media link's attributes now go through the same name check as
attribute(), so page content can no longer put an event handler on the link. Thanks @R0X4R
- A scheduled job that its plugin switches off with
v2.2.24 5 days ago
-
- Running a plugin's test suite against a Grav checkout no longer leaves a
user/config/security-private.phpin the plugin's folder, where agit add -Acould commit it into the plugin's release. Grav now creates the key file only in a real Grav install, and code that loads Grav's classes from anywhere else gets a key that lasts for that process
- Running a plugin's test suite against a Grav checkout no longer leaves a
v2.2.23 6 days ago
-
- When a cache file can't be deleted, the cache purge job and
bin/grav clearnow name the file and the reason (such as "Permission denied") instead of "Unknown error", and carry on with the rest of the cache instead of stopping at the first one (#4384) - [security] The
svg_image()Twig function now escapes the classes it adds to the SVG. Thanks @manus-pi - [security] The
svg_image()Twig function only inlines real.svgfiles, so a theme that takes the image path from a page header can no longer be pointed at other files on the server
- When a cache file can't be deleted, the cache purge job and
v2.2.28
Latest
1 day ago
-
Browser::isHuman()no longer counts link-preview fetchers (such asfacebookexternalhit, which loads a page each time a shared link or ad is shown), AI fetchers (ChatGPT-User,ClaudeBot,PerplexityBotand others), uptime and monitoring services, and headless or auditing tools like HeadlessChrome and Lighthouse as people, so page statistics stop counting requests nobody made. Facebook's and Instagram's in-app browsers are real visitors and stay human
v2.2.27 3 days ago
-
- Showing the same image twice with different
derivatives()ranges, for example in two modules on one page, no longer stretches the second set of responsive images, and the second set can now go up to the full width of the original #4389 - Cropping or resizing an image after
derivatives(), such asderivatives(400, 800, 400).cropZoom(300, 300), scales its responsive images down with it instead of making them larger than the image itself - Links and images to media files with
#,?or%in their names work again, written percent-encoded (Invoice%20%2312.pdf) or in angle brackets. Media URLs now come out percent-encoded too, so a space is%20#4388
- Showing the same image twice with different
v2.2.26 4 days ago
-
- When PHP can't start sessions (for example,
session.save_pathpoints at a folder that no longer exists after a server move), Grav now writes the reason tograv.loginstead of showing "Session corruption detected" on every page to every visitor - A session holding an unusable user object is now actually replaced with a fresh one, instead of crashing every page with an error until the visitor clears their cookies
- The debug bar no longer reports Twig deprecations on every page, one for Grav's sandbox source policy and one for how page content Twig is rendered #4387
- When PHP can't start sessions (for example,
v2.2.25 4 days ago
-
- A scheduled job that its plugin switches off with
when()(such as YetiSearch Pro's embed job while semantic search is off) is no longer run and recorded as a failure each time it comes due. The scheduler leaves it out of the run and out of the health check, andJob::passesWhen()tells other tools whether a job's condition lets it run - [security] A media link's attributes now go through the same name check as
attribute(), so page content can no longer put an event handler on the link. Thanks @R0X4R
- A scheduled job that its plugin switches off with
v2.2.24 5 days ago
-
- Running a plugin's test suite against a Grav checkout no longer leaves a
user/config/security-private.phpin the plugin's folder, where agit add -Acould commit it into the plugin's release. Grav now creates the key file only in a real Grav install, and code that loads Grav's classes from anywhere else gets a key that lasts for that process
- Running a plugin's test suite against a Grav checkout no longer leaves a
v2.2.23 6 days ago
-
- When a cache file can't be deleted, the cache purge job and
bin/grav clearnow name the file and the reason (such as "Permission denied") instead of "Unknown error", and carry on with the rest of the cache instead of stopping at the first one (#4384) - [security] The
svg_image()Twig function now escapes the classes it adds to the SVG. Thanks @manus-pi - [security] The
svg_image()Twig function only inlines real.svgfiles, so a theme that takes the image path from a page header can no longer be pointed at other files on the server
- When a cache file can't be deleted, the cache purge job and