Grav Lifecycle

It is often useful to know how Grav processes in order to fully understand how best to extend Grav via plugins. This is the Grav lifecycle:


  1. Check PHP version to ensure we're running at least version 7.1.3
  2. Class loader initialization
  3. Obtain Grav instance


    1. No instance exists, so call load()
    2. Add loader
    3. Add and initialize debugger
    4. Add grav (deprecated)
    5. Register Services
      1. Accounts Service Provider
        1. Add accounts
        2. Add users (deprecated)
      2. Assets Service Provider
        1. Add assets
      3. Backups Service Provider
        1. Add backups
      4. Config Service Provider
        1. Add setup
        2. Add blueprints
        3. Add config
        4. Add languages
        5. Add language
      5. Error Service Provider
        1. Add error
      6. Filesystem Service Provider
        1. Add filesystem
      7. Inflector Service Provider
        1. Add inflector
      8. Logger Service Provider
        1. Add log
      9. Output Service Provider
        1. Add output
      10. Pages Service Provider
        1. Add pages
        2. Add page
      11. Request Service Provider
        1. Add request
      12. Scheduler Service Provider
        1. Add scheduler
      13. Session Service Provider
        1. Add session
        2. Add messages
      14. Streams Service Provider
        1. Add locator
        2. Add streams
      15. Task Service Provider
        1. Add task
        2. Add action
      16. Other Service Providers
        1. Add browser
        2. Add cache
        3. Add events
        4. Add exif
        5. Add plugins
        6. Add taxonomy
        7. Add themes
        8. Add twig
        9. Add uri
  4. call Grav::process()


    1. Run Configuration Processor
      1. Initialize $grav['config']
      2. Load plugins and their configuration $grav['plugins']
    2. Run Logger Processor
      1. Initialize $grav['log']
    3. Run Errors Processor
      1. Initialize $grav['errors']
      2. Registers PHP error handlers
    4. Run Debugger Processor
      1. Initialize $grav['debugger']
    5. Run Initialize Processor
      1. Start output buffering
      2. Initialize the timezone
      3. Initialize $grav['session'] if system.session.initialize is true
      4. Initialize $grav['uri']
        1. Add $grav['base_url_absolute']
        2. Add $grav['base_url_relative']
        3. Add $grav['base_url']
      5. Redirect if system.pages.redirect_trailing_slash is true and trailing slash in URL
    6. Run Plugins Processor
      1. Initialize $grav['accounts']
      2. Initialize $grav['plugins']
      3. Fire onPluginsInitialized event
    7. Run Themes Processor
      1. Initialize $grav['themes']
      2. Fire onThemeInitialized event
    8. Run Request Processor
      1. Initialize $grav['request']
      2. Fire onRequestHandlerInit event with [request, handler]
      3. If response is set inside the event, stop further processing and output the response
    9. Run Tasks Processor
      1. If request has attribute controller.class and either task or action:
        1. Run the controller
        2. If NotFoundException: continue (check task and action)
        3. If response code 418: continue (ignore task and action)
        4. Else: stop further processing and output the response
      2. If task:
        1. Fire onTask event
        2. Fire onTask.[TASK] event
      3. If action:
        1. Fire onAction event
        2. Fire onAction.[ACTION] event
    10. Run Backups Processor
      1. Initialize $grav['backups']
      2. Fire onBackupsInitialized event
    11. Run Scheduler Processor
      1. Initialize $grav['scheduler']
      2. Fire onSchedulerInitialized event
    12. Run Assets Processor
      1. Initialize $grav['assets']
      2. Fire onAssetsInitialized event
    13. Run Twig Processor
      1. Initialize $grav['twig']


        1. Set Twig template paths based on configuration
        2. Handle language templates if available
        3. Fire onTwigTemplatePaths event
        4. Fire onTwigLoader event
        5. Load Twig configuration and loader chain
        6. Fire onTwigInitialized event
        7. Load Twig extensions
        8. Fire onTwigExtensions event
        9. Set standard Twig variables (config, uri, taxonomy, assets, browser, etc)
    14. Run Pages Processor
      1. Initialize $grav['pages']


        1. Call buildPages()
        2. Check if cache is good
        3. If cache is good load pages date from
        4. If cache is not good call recurse()
        5. Fire onBuildPagesInitialized event in recurse()
        6. If a .md file is found:


          1. Call init() to load the file details
          2. Set the filePath, modified, id
          3. Call header() to initialize the header variables
          4. Call slug() to set the URL slug
          5. Call visible() to set visible state
          6. Set modularTwig() status based on if folder starts with _
        7. Fire onPageProcessed event
        8. If a folder found recurse() the children
        9. Fire onFolderProcessed event
        10. Call buildRoutes()
        11. Initialize taxonomy for all pages
        12. Build route table for fast lookup
      2. Fire onPagesInitialized event with [pages]
      3. Fire onPageInitialized event with [page]
      4. If page is not routable:
        1. Fire onPageNotFount event with [page]
      5. If task:
        1. Fire onPageTask event with [task, page]
        2. Fire onPageTask.[TASK] event with [task, page]
      6. If action:
        1. Fire onPageAction event with [action, page]
        2. Fire onPageAction.[ACTION] event with [action, page]
    15. Run Debugger Assets Processor
      1. Add the debugger CSS/JS to the assets
    16. Run Render Processor
      1. Initialize $grav['output']
      2. If output instanceof ResponseInterface:
        1. Stop further processing and output the response
      3. Else:
        1. Render page with Twig's processSite() method


          1. Fire onTwigSiteVariables event
          2. Get the page output
          3. Fire onTwigPageVariables, also called for each modular subpage
          4. If a page is not found or not routable, first fire the onPageFallBackUrl event to see if we have a fallback for a media asset and then fire onPageNotFound if not
          5. Set all Twig variables on the Twig object
          6. Set the template name based on file/header/extension information
          7. Call render() method
          8. Return resulting HTML
        2. Fire onOutputGenerated event
        3. Echo the output into output buffer
        4. Fire onOutputRendered event
        5. Build Response object
        6. Stop further processing and output the response
    17. Output HTTP header and body
    18. Render debugger (if enabled)
    19. Shutdown
      1. Close session
      2. Close connection to client
      3. Fire onShutdown event

Whenever a page has its content() method called, the following lifecycle occurs:


  1. If content is NOT cached:
    1. Fire onPageContentRaw event
    2. Process the page according to Markdown and Twig settings. Fire onMarkdownInitialized event
    3. Fire onPageContentProcessed event
  2. Fire onPageContent event

Found errors? Think you can improve this documentation? Simply click the Edit link at the top of the page, and then the icon on Github to make your changes.