Using Shortcodes in Markdown
Shortcodes are simple snippets that let you embed complex functionality into your Markdown documents without writing HTML or complex code. They're commonly used in static site generators.
What are Shortcodes?
Shortcodes are placeholders that get replaced with rendered content during the build process. They typically look like this:
markdown
{{< shortcode-name param1="value1" >}}
or
{{% shortcode-name %}}
Content here
{{% /shortcode-name %}}Common Shortcode Syntax Formats
Hugo Syntax
markdown
<!-- Self-closing -->
{{< youtube id="dQw4w9WgXcQ" >}}
<!-- With content -->
{{% note type="warning" %}}
This is important information!
{{% /note %}}Jekyll/Liquid Syntax
markdown
{% youtube "dQw4w9WgXcQ" %}
{% highlight javascript %}
console.log("Hello World");
{% endhighlight %}Gatsby/MDX Components
markdown
<YouTube videoId="dQw4w9WgXcQ" />
<Note type="warning">
This is important information!
</Note>Built-in Shortcodes
Hugo Built-in Shortcodes
Figure/Image
markdown
{{< figure src="/images/sunset.jpg"
title="Beautiful Sunset"
caption="Taken in California"
alt="Sunset over ocean"
width="800" >}}YouTube
markdown
{{< youtube dQw4w9WgXcQ >}}
<!-- With parameters -->
{{< youtube id="dQw4w9WgXcQ" autoplay="true" >}}Twitter
markdown
{{< twitter user="github" id="1234567890" >}}Instagram
markdown
{{< instagram BWNjjyYFxVx >}}Gist
markdown
{{< gist username 0123456789abcdef >}}Jekyll Built-in Tags
Highlight Code
markdown
{% highlight ruby linenos %}
def hello
puts "Hello World"
end
{% endhighlight %}Include Files
markdown
{% include header.html %}
{% include_relative ../shared/footer.html %}Link to Posts
markdown
{% post_url 2024-01-15-my-post %}
{% link _posts/2024-01-15-my-post.md %}Creating Custom Shortcodes
Hugo Custom Shortcodes
Create a file in layouts/shortcodes/button.html:
html
<a href="{{ .Get "url" }}" class="button {{ .Get "style" }}">
{{ .Inner }}
</a>Usage:
markdown
{{< button url="/docs" style="primary" >}}
Read Documentation
{{< /button >}}More Complex Example
layouts/shortcodes/callout.html:
html
{{ $type := .Get "type" | default "info" }}
<div class="callout callout-{{ $type }}">
<div class="callout-title">
{{ with .Get "title" }}{{ . }}{{ end }}
</div>
<div class="callout-content">
{{ .Inner | markdownify }}
</div>
</div>Usage:
markdown
{{% callout type="warning" title="Important" %}}
This is a **warning** message with *Markdown* support.
{{% /callout %}}Jekyll Custom Tag
Create a plugin in _plugins/custom_tag.rb:
ruby
module Jekyll
class CustomTag < Liquid::Tag
def initialize(tag_name, params, tokens)
super
@params = params
end
def render(context)
"<div class='custom-tag'>#{@params}</div>"
end
end
end
Liquid::Template.register_tag('custom', Jekyll::CustomTag)Usage:
markdown
{% custom "My custom content" %}Practical Shortcode Examples
Alert/Notice Boxes
markdown
{{% alert type="info" %}}
ℹ️ This is an informational message.
{{% /alert %}}
{{% alert type="warning" %}}
⚠️ This is a warning message.
{{% /alert %}}
{{% alert type="danger" %}}
🚨 This is a danger message.
{{% /alert %}}Code Tabs
markdown
{{< tabs >}}
{{< tab "JavaScript" >}}
```javascript
console.log("Hello");{{< /tab >}}
{{< tab "Python" >}}
python
print("Hello"){{< /tab >}} {{< /tabs >}}
### Expandable Sections
```markdown
{{< expand "Click to expand" >}}
This content is hidden by default and can be expanded.
It can contain **any Markdown** including:
- Lists
- Code blocks
- Images
{{< /expand >}}Embed External Content
markdown
<!-- CodePen -->
{{< codepen user="username" id="abcdefg" >}}
<!-- JSFiddle -->
{{< jsfiddle url="https://jsfiddle.net/username/abc123" >}}
<!-- CodeSandbox -->
{{< codesandbox id="abc123" >}}Gallery/Lightbox
markdown
{{< gallery >}}
{{< img src="image1.jpg" caption="First image" >}}
{{< img src="image2.jpg" caption="Second image" >}}
{{< img src="image3.jpg" caption="Third image" >}}
{{< /gallery >}}Table of Contents
markdown
{{< toc >}}
<!-- With options -->
{{< toc levels="2,3" >}}Mermaid Diagrams
markdown
{{< mermaid >}}
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
{{< /mermaid >}}Advanced Shortcode Patterns
Parameterized Shortcodes
markdown
<!-- Named parameters -->
{{< card title="My Title"
image="/images/card.jpg"
link="/read-more"
button="Learn More" >}}
<!-- Positional parameters -->
{{< youtube "dQw4w9WgXcQ" "16:9" >}}Nested Shortcodes
markdown
{{< columns >}}
{{< column size="6" >}}
Left column content
{{< /column >}}
{{< column size="6" >}}
Right column content
{{< /column >}}
{{< /columns >}}Conditional Rendering
Hugo example:
html
{{ if .Get "show" }}
<div class="optional-content">
{{ .Inner }}
</div>
{{ end }}Accessing Page Variables
html
<!-- In shortcode template -->
<div class="page-info">
<h3>{{ .Page.Title }}</h3>
<p>Last modified: {{ .Page.Lastmod }}</p>
<p>Reading time: {{ .Page.ReadingTime }} minutes</p>
</div>Shortcode Best Practices
- Keep It Simple: Shortcodes should be easy to remember and use
- Clear Naming: Use descriptive names that indicate functionality
- Documentation: Document all parameters and usage examples
- Error Handling: Provide sensible defaults and handle missing parameters
- Performance: Avoid complex computations in frequently used shortcodes
- Accessibility: Ensure generated HTML is accessible
- Mobile Friendly: Test shortcodes on mobile devices
Common Use Cases
Documentation
markdown
<!-- API endpoint documentation -->
{{< api method="GET" path="/api/users" >}}
Returns a list of all users.
{{< /api >}}
<!-- Parameter documentation -->
{{< param name="userId" type="string" required="true" >}}
The unique identifier for the user.
{{< /param >}}E-learning
markdown
<!-- Quiz questions -->
{{< quiz >}}
{{< question "What is 2+2?" >}}
{{< answer correct="true" >}}4{{< /answer >}}
{{< answer >}}3{{< /answer >}}
{{< answer >}}5{{< /answer >}}
{{< /question >}}
{{< /quiz >}}Product Showcase
markdown
{{< product-card
name="Premium Widget"
price="$99.99"
image="/products/widget.jpg"
rating="4.5"
reviews="245" >}}Shortcodes vs. Components
| Feature | Shortcodes | React Components |
|---|---|---|
| Build Time | ✅ Rendered at build | ❌ Runtime |
| Interactivity | ❌ Static | ✅ Dynamic |
| Learning Curve | ✅ Simple | ⚠️ Moderate |
| Flexibility | ⚠️ Limited | ✅ High |
| Performance | ✅ Fast | ⚠️ Depends on bundle |
Migrating from HTML to Shortcodes
Before (Raw HTML)
markdown
<div class="alert alert-warning" role="alert">
<h4 class="alert-heading">Warning!</h4>
<p>This is a warning message.</p>
</div>After (Shortcode)
markdown
{{% alert type="warning" title="Warning!" %}}
This is a warning message.
{{% /alert %}}Debugging Shortcodes
Hugo Debug
html
<!-- In shortcode template -->
{{ printf "%#v" . }}
<!-- Print all params -->
{{ range $key, $value := .Params }}
{{ $key }}: {{ $value }}
{{ end }}Jekyll Debug
ruby
def render(context)
puts "Debug: #{@params.inspect}"
# ... rest of code
endPerformance Considerations
- Caching: Cache expensive computations
- Lazy Loading: Defer non-critical content
- Minimize API Calls: Batch requests when possible
- Optimize Images: Use appropriate sizes and formats
- Code Splitting: Load JavaScript only when needed
Conclusion
Shortcodes provide a powerful way to extend Markdown with custom functionality while keeping content files clean and maintainable. They're an essential tool for building modern static sites and documentation systems.