Created
February 8, 2026 22:36
-
-
Save ryanirelan/162bcc730ba59ead426b95511c61194d to your computer and use it in GitHub Desktop.
Quiz: Real World Craft CMS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "quizzes": [ | |
| { | |
| "title": "Real World Craft CMS", | |
| "passingScore": 70, | |
| "timeLimit": 0, | |
| "maxAttempts": 0, | |
| "allowRetakes": 1, | |
| "showCorrectAnswers": 1, | |
| "shuffleQuestions": 1, | |
| "shuffleAnswers": 1, | |
| "hasGuestAccess": 0, | |
| "hasFreeAccountAccess": 0, | |
| "enabled": 1, | |
| "multipleChoiceQuestions": [ | |
| { | |
| "questionText": "What are the three section types available in Craft CMS?", | |
| "quizOptions": [ | |
| { "optionText": "Page, Post, Collection", "isCorrect": 0 }, | |
| { "optionText": "Channel, Structure, Single", "isCorrect": 1 }, | |
| { "optionText": "Blog, Portfolio, Landing", "isCorrect": 0 }, | |
| { "optionText": "Entry, Category, Global", "isCorrect": 0 } | |
| ], | |
| "explanation": "Craft CMS has three section types: Channel (for grouped, non-ordered content like blog posts), Structure (for hierarchical content), and Single (for one-off pages like a homepage)." | |
| }, | |
| { | |
| "questionText": "What is a \"field instance\" in Craft CMS 5?", | |
| "quizOptions": [ | |
| { "optionText": "A copy of a field stored in the database", "isCorrect": 0 }, | |
| { "optionText": "A temporary field created during content editing", "isCorrect": 0 }, | |
| { "optionText": "When a global field is used in an entry type with entry-type-specific settings", "isCorrect": 1 }, | |
| { "optionText": "A field that only exists within a single section", "isCorrect": 0 } | |
| ], | |
| "explanation": "A field instance is when you use a global field in an entry type and give it entry-type-specific settings like label, handle, and conditions. This lets you customize how a field behaves per entry type without changing the global field." | |
| }, | |
| { | |
| "questionText": "Why is a Single section ideal for a homepage in Craft CMS?", | |
| "quizOptions": [ | |
| { "optionText": "It supports multiple entries for different homepage versions", "isCorrect": 0 }, | |
| { "optionText": "It automatically generates a navigation menu", "isCorrect": 0 }, | |
| { "optionText": "It creates a custom field layout tailored to one page", "isCorrect": 1 }, | |
| { "optionText": "It allows unlimited field types per section", "isCorrect": 0 } | |
| ], | |
| "explanation": "A Single section creates exactly one entry, making it perfect for pages like a homepage where you need a custom field layout tailored to that specific page's content needs." | |
| }, | |
| { | |
| "questionText": "When building a content builder in Craft CMS, which field type powers it?", | |
| "quizOptions": [ | |
| { "optionText": "Table field", "isCorrect": 0 }, | |
| { "optionText": "Matrix field", "isCorrect": 1 }, | |
| { "optionText": "Entries field", "isCorrect": 0 }, | |
| { "optionText": "CKEditor field", "isCorrect": 0 } | |
| ], | |
| "explanation": "The Matrix field is used to create content builders (page builders) in Craft CMS. Each block type in the Matrix field represents an available content type (rich text, CTA, stats, etc.) that content authors can add and reorder." | |
| }, | |
| { | |
| "questionText": "How do you access a Single section's entry data in a Twig template?", | |
| "quizOptions": [ | |
| { "optionText": "You must query for it using craft.entries", "isCorrect": 0 }, | |
| { "optionText": "You fetch it via a GraphQL API call", "isCorrect": 0 }, | |
| { "optionText": "You must pass it from a controller", "isCorrect": 0 }, | |
| { "optionText": "Craft automatically provides the entry object", "isCorrect": 1 } | |
| ], | |
| "explanation": "For Single sections (and individual entry view templates), Craft automatically makes the entry object available in Twig. You don't need to write an element query — Craft knows which entry to load based on the URI." | |
| }, | |
| { | |
| "questionText": "What is the correct element query to fetch the last 10 adventures from a Channel section?", | |
| "quizOptions": [ | |
| { "optionText": "craft.entries('adventures').limit(10).all()", "isCorrect": 0 }, | |
| { "optionText": "craft.entries.section('adventures').limit(10).all()", "isCorrect": 1 }, | |
| { "optionText": "craft.query.entries('adventures', 10)", "isCorrect": 0 }, | |
| { "optionText": "craft.channel('adventures').fetch(10)", "isCorrect": 0 } | |
| ], | |
| "explanation": "Element queries in Craft use a fluent/chainable API. You start with craft.entries, set the section with .section('adventures'), limit results with .limit(10), and execute the query with .all()." | |
| }, | |
| { | |
| "questionText": "Which Twig function retrieves all categories from a category group?", | |
| "quizOptions": [ | |
| { "optionText": "craft.entries.group('locations').all()", "isCorrect": 0 }, | |
| { "optionText": "craft.tags.group('locations').all()", "isCorrect": 0 }, | |
| { "optionText": "craft.categories.group('locations').all()", "isCorrect": 1 }, | |
| { "optionText": "craft.elements.categories('locations')", "isCorrect": 0 } | |
| ], | |
| "explanation": "Categories have their own element query accessed via craft.categories. You specify the category group with .group('handle') and execute with .all()." | |
| }, | |
| { | |
| "questionText": "What problem does eager loading solve in Craft CMS templates?", | |
| "quizOptions": [ | |
| { "optionText": "Slow page rendering due to large images", "isCorrect": 0 }, | |
| { "optionText": "The N+1 query problem where each loop iteration triggers additional queries", "isCorrect": 1 }, | |
| { "optionText": "Memory overflow from loading too many entries", "isCorrect": 0 }, | |
| { "optionText": "Template compilation errors with nested loops", "isCorrect": 0 } | |
| ], | |
| "explanation": "Without eager loading, each iteration in a for-loop triggers separate database queries for related elements (like images). Eager loading with .with() fetches all related elements upfront in a single query, eliminating the N+1 problem." | |
| }, | |
| { | |
| "questionText": "How do you eager load both images and their transforms in a single element query?", | |
| "quizOptions": [ | |
| { "optionText": ".with(['images']).transforms(['adventureListing'])", "isCorrect": 0 }, | |
| { "optionText": ".eagerLoad('images', 'adventureListing')", "isCorrect": 0 }, | |
| { "optionText": ".with([['images', { withTransforms: ['adventureListing'] }]])", "isCorrect": 1 }, | |
| { "optionText": ".with(['images']).withTransforms('adventureListing')", "isCorrect": 0 } | |
| ], | |
| "explanation": "To eager load transforms alongside images, you pass a nested array to .with() where the second element is an object with a withTransforms key containing an array of transform handles." | |
| }, | |
| { | |
| "questionText": "Where are conditional field rules configured in Craft CMS?", | |
| "quizOptions": [ | |
| { "optionText": "On the global field settings", "isCorrect": 0 }, | |
| { "optionText": "In the field layout (per entry type)", "isCorrect": 1 }, | |
| { "optionText": "In the section settings", "isCorrect": 0 }, | |
| { "optionText": "In the Craft config file", "isCorrect": 0 } | |
| ], | |
| "explanation": "Conditional fields are set in the Field Layout, not on the field itself. This means conditions can account for values in other fields or the current user, and the same global field can be reused across entry types with different conditions." | |
| }, | |
| { | |
| "questionText": "What does the batch filter do in Twig?", | |
| "quizOptions": [ | |
| { "optionText": "Processes items asynchronously in the background", "isCorrect": 0 }, | |
| { "optionText": "Filters out duplicate items from an array", "isCorrect": 0 }, | |
| { "optionText": "Chunks an array into groups of a specified size", "isCorrect": 1 }, | |
| { "optionText": "Sorts items into alphabetical batches", "isCorrect": 0 } | |
| ], | |
| "explanation": "The batch filter splits an array into groups of a specified size. In the course, it's used to chunk headline words into groups of 4 for line breaks, and to split categories into columns of 4 for a multi-column layout." | |
| }, | |
| { | |
| "questionText": "What is the benefit of using entry types within a single section?", | |
| "quizOptions": [ | |
| { "optionText": "Different types of content can share one section with different field layouts", "isCorrect": 1 }, | |
| { "optionText": "Each entry type generates its own URL pattern", "isCorrect": 0 }, | |
| { "optionText": "Entry types automatically create navigation menus", "isCorrect": 0 }, | |
| { "optionText": "They allow unlimited entries per section", "isCorrect": 0 } | |
| ], | |
| "explanation": "Entry types let you store different types of content in the same section, each with its own field layout. This avoids creating multiple closely related sections and provides a more normalized content model." | |
| }, | |
| { | |
| "questionText": "What does entry.image.one.url do in a Twig template?", | |
| "quizOptions": [ | |
| { "optionText": "Returns all images as an array of URLs", "isCorrect": 0 }, | |
| { "optionText": "Creates a new image upload field", "isCorrect": 0 }, | |
| { "optionText": "Executes the asset query, gets one result, and returns its URL", "isCorrect": 1 }, | |
| { "optionText": "Returns the first image from the media library", "isCorrect": 0 } | |
| ], | |
| "explanation": "entry.image accesses the asset field, .one executes the element query and returns a single asset element, and .url gets the full URL to that asset file." | |
| }, | |
| { | |
| "questionText": "Why should template directories mirror section handles in Craft CMS?", | |
| "quizOptions": [ | |
| { "optionText": "Craft requires this naming convention to function", "isCorrect": 0 }, | |
| { "optionText": "It enables automatic URL routing without configuration", "isCorrect": 0 }, | |
| { "optionText": "It makes the relationship between sections and templates intuitive and organized", "isCorrect": 1 }, | |
| { "optionText": "It allows Craft to auto-generate templates", "isCorrect": 0 } | |
| ], | |
| "explanation": "Matching template directory names to section handles (e.g., adventures/ for the adventures section) is a convention that keeps the project organized and makes it easy to find which templates belong to which sections." | |
| }, | |
| { | |
| "questionText": "What is a preview target in Craft CMS Pro?", | |
| "quizOptions": [ | |
| { "optionText": "A staging server URL for content review", "isCorrect": 0 }, | |
| { "optionText": "A URL pattern used to preview content from the control panel", "isCorrect": 1 }, | |
| { "optionText": "A field that stores preview images for social sharing", "isCorrect": 0 }, | |
| { "optionText": "A plugin that generates page screenshots", "isCorrect": 0 } | |
| ], | |
| "explanation": "Preview targets are URLs configured per section that let content authors preview their entries. You can set up multiple targets — like the entry page, a listing page, and the homepage — and they auto-refresh as content is edited." | |
| } | |
| ], | |
| "trueFalseQuestions": [ | |
| { | |
| "questionText": "In Craft CMS, you must write an element query to access a Single section's content in its template.", | |
| "correctAnswer": 0, | |
| "explanation": "Craft automatically provides the entry object in Single section templates. Because Craft knows the URI maps to a Single, it loads the entry data without requiring an explicit element query." | |
| }, | |
| { | |
| "questionText": "The Twig split filter can break a string into an array by splitting on a specified delimiter.", | |
| "correctAnswer": 1, | |
| "explanation": "The split filter divides a string into an array. For example, entry.headline | split(' ') splits a headline into individual words by splitting on spaces." | |
| }, | |
| { | |
| "questionText": "Conditional fields in Craft CMS can only be based on the values of other fields, not on user attributes.", | |
| "correctAnswer": 0, | |
| "explanation": "Conditional fields can take into account both the values in other fields AND information about the current user authoring the content, such as their user group or permissions." | |
| }, | |
| { | |
| "questionText": "When eager loading is used in Craft 4+, eagerly loaded elements are returned as collections, so existing template code that uses .one continues to work without changes.", | |
| "correctAnswer": 1, | |
| "explanation": "Craft 4 changed eagerly loaded elements to return as collections instead of arrays. The .one method works the same way, so no template code changes are needed when adding eager loading to existing queries." | |
| }, | |
| { | |
| "questionText": "Conditional field layout tabs allow you to show or hide entire tabs based on conditions, enabling tab-based content authoring workflows.", | |
| "correctAnswer": 1, | |
| "explanation": "Beyond individual conditional fields, Craft also supports conditional tabs in field layouts. This lets you create dynamic authoring experiences where tabs appear only when specific conditions are met, enabling step-based workflows." | |
| } | |
| ], | |
| "codeChallengeQuestions": [ | |
| { | |
| "questionText": "What does this Twig code output?", | |
| "codeSnippet": "{% set headline = \"Trail Running Adventures Await You\" | split(' ') %}\n{% for words in headline | batch(3) %}\n<span>{{ words | join(' ') }}</span>\n{% endfor %}", | |
| "codeLanguage": "twig", | |
| "quizOptions": [ | |
| { "optionText": "A single span with all five words", "isCorrect": 0 }, | |
| { "optionText": "Two spans: \"Trail Running Adventures\" and \"Await You\"", "isCorrect": 1 }, | |
| { "optionText": "Five spans, each with one word", "isCorrect": 0 }, | |
| { "optionText": "Three spans with one or two words each", "isCorrect": 0 } | |
| ], | |
| "explanation": "The split(' ') creates a 5-word array. The batch(3) filter groups them into chunks of 3. The first chunk has 3 words (\"Trail Running Adventures\") and the second has the remaining 2 (\"Await You\"), giving us two <span> elements." | |
| }, | |
| { | |
| "questionText": "What is wrong with this element query for eager loading?", | |
| "codeSnippet": "{% set adventures = craft.entries\n .section('adventures')\n .with('images')\n .all()\n%}", | |
| "codeLanguage": "twig", | |
| "quizOptions": [ | |
| { "optionText": ".section() should be .channel()", "isCorrect": 0 }, | |
| { "optionText": "The argument to .with() should be an array: ['images']", "isCorrect": 1 }, | |
| { "optionText": ".all() should be .collect()", "isCorrect": 0 }, | |
| { "optionText": "Nothing, this code is correct", "isCorrect": 0 } | |
| ], | |
| "explanation": "The .with() method expects an array of element handles to eager load. The correct syntax is .with(['images']) with square brackets, not .with('images') as a bare string." | |
| }, | |
| { | |
| "questionText": "What does this Matrix field template code do?", | |
| "codeSnippet": "{% for block in entry.contentBuilder.all() %}\n {% switch block.type %}\n {% case 'stats' %}\n {% for stat in block.stat %}\n <dt>{{ stat.name }}</dt>\n <dd>{{ stat.value }}</dd>\n {% endfor %}\n {% case 'richText' %}\n {{ block.text }}\n {% endswitch %}\n{% endfor %}", | |
| "codeLanguage": "twig", | |
| "quizOptions": [ | |
| { "optionText": "Displays all Matrix blocks in alphabetical order", "isCorrect": 0 }, | |
| { "optionText": "Creates new Matrix blocks from a JSON feed", "isCorrect": 0 }, | |
| { "optionText": "Iterates over content builder blocks and renders different markup based on block type", "isCorrect": 1 }, | |
| { "optionText": "Filters Matrix blocks to only show stats and rich text", "isCorrect": 0 } | |
| ], | |
| "explanation": "This code loops through all blocks in a Matrix field and uses a switch statement to render different markup depending on the block's entry type. Stats blocks iterate over table rows showing name/value pairs, while rich text blocks output their text content directly." | |
| } | |
| ] | |
| } | |
| ] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment