<![CDATA[Tutorials]]>https://ghost.org/tutorials/https://ghost.org/tutorials/favicon.pngTutorialshttps://ghost.org/tutorials/Ghost 5.96Wed, 16 Oct 2024 11:01:07 GMT60<![CDATA[✅ Remind me to change this title]]>https://ghost.org/tutorials/tk/65e87f801485cc000116b688Tue, 16 Apr 2024 12:54:36 GMT

Welcome to #14. In this issue, we share:

  • Our new TK reminders feature
  • Investigations into ActivityPub (we need your help!)
  • Design and code tips and tricks
  • Our interview with TechHut Media on all things Linux
🏋️
Pro tip: Quickly access the Settings menu from the dashboard with the keyboard shortcut ⌘ + , (MacOS) or CTRL + , (Windows).

Ghost is open source

Since our beginning as a Kickstarter project in 2013, we've been open source, meaning all our code is freely available for you to inspect, run, and modify in pretty much whatever way you like. It also means that hundreds of contributors have helped and continue to help build Ghost 💪

GitHub - TryGhost/Ghost: Independent technology for modern publishing, memberships, subscriptions and newsletters.
Independent technology for modern publishing, memberships, subscriptions and newsletters. - TryGhost/Ghost
✅ Remind me to change this title

But, if you're reading this newsletter, there's a good chance, you already knew all that 🤓

Just shipped 🚢

  • One of our top requested features is federating over ActivityPub, the protocol used by Mastodon, PixelFeed, and, recently, Threads. We're investigating adding protocol support to Ghost but we need your help. Please take a minute and tell us a bit about how you imagine this working 🙏
  • 🆕 TK Reminders. Ever wanted to leave yourself a reminder to update something before publishing? We've now got your back. Type TK in the editor and Ghost will remind you to add that missing image or update a statistic. See how this new feature works in our changelog.
  • On 1 March 2024, we rolled out some minor style changes to Ghost's editor cards. The gist of these changes is that we transitioned from em units to px units for font-size. We made these changes to make it easier to create custom themes without unexpected consequences. Learn more in our Forum post.

Ideas and tools 🛠️

TechHut Media

TechHut Media dives deep into the world of open source, making it the ideal spot for enthusiasts and newbs alike. We caught up with the team behind the scenes, Brandon and Nicco, to learn more about the publication and how they use Ghost.

TechHut Media
Your source for technology reviews, marketing, and content production services.
✅ Remind me to change this title

Meet the authors

Before there was a publication, there was a YouTube channel. Two, to be precise.

Brandon's channel, TechHut, focuses on various tech products and software with an overall goal of influencing people towards open-source alternatives and self-hosting.

Nicco started his channel, Nicco Loves Linux, as a way to explain how KDE works, and now covers other topics in the Linux world.

Watching either channel, it's obvious that both creators are passionate and knowledgeable about Linux, and they're both great sources for keeping up with all that's new in open source.

Learn about Linux distros

When talking about Linux, a favorite topic is distros. A distro (short for distribution) refers to the complete operating system built around the Linux kernel.

There are hundreds of Linux distros, each with its unique purpose and style. The proliferation of distros can be overwhelming, so we asked Nicco and Brandon about some of their favorites.

As mentioned, Nicco loves KDE, and, in particular, Kubuntu. This distro pairs Ubuntu with the desktop environment, KDE Plasma. Ubuntu, a key piece in the recommended production tech stack for Ghost, is built on Debian.

✅ Remind me to change this title
KDE Plasma 6

Even if some terms in the last section are new to you, they highlight the essence of open source: a collaborative environment where each piece of software evolves from its predecessors, leading to innovative creations. This continuous cycle of improvement and reinvention is unique to the open-source community, a process not found in the proprietary software world.

Oh, and for development purposes, Nicco also uses Arch, btw 😉

✅ Remind me to change this title
Neofetch output for Arch Linux

Brandon prefers yet another distro, Fedora, which uses the GNOME desktop environment. Well, to be precise, he's running an optimized version of Fedora called Nobara that he dual boots with Windows 11.1.

Windows, of course, is not an open-source distro, but it is possible to run Windows Subsystem for Linux (WSL), which allows you to run Linux distros on Windows. That's pretty cool, and, when using Windows, we recommend this approach for Ghost theme development.

✅ Remind me to change this title
Ubuntu Linux desktop

If this is all new to you, but your curiosity is piqued and you'd like to try a Linux distro yourself, Brandon recommends Ubuntu, as it's the easiest to get up and going.

If this isn't your first rodeo, then Brandon and Nicco think the most exciting Linux developments are being made with desktop environments. Of note, KDE Plasma 6 just came out and the brand-new COSMIC desktop for Pop!_OS (yep, another distro) is nearing its alpha release.

Open-source news

The TechHut newsletter, powered by Ghost and rocking the Headline theme, is a great way to keep up on all these exciting developments. Brandon chose Ghost for the newsletter because of its integrated membership features, ease of use, and, of course, because Ghost is open source.


Sites featured in the Build with Ghost newsletter are discovered through our creator network, Ghost Explore. It’s a way for creators and readers alike to discover their favorite new publications. Anyone running a Ghost site can add themselves to Explore to be featured throughout the wider Ghost ecosystem. If you’d like to be featured in this newsletter, add your site to Explore and reply to this email.

✅ Remind me to change this title

Thanks for building with us.

Have an idea for a Ghost tutorial? Reply to this email and let us know ❤️

Looking for other creators and developers working with Ghost? Join the official Ghost Forum, where we talk about all things Ghost!

]]>
<![CDATA[💌 Build with Ghost: Email is changing in a big way]]>https://ghost.org/tutorials/email-is-changing/65a6fc1d3dc82b0001c138f3Fri, 02 Feb 2024 09:00:39 GMT

Welcome to #13. In this month's issue:

  • How new email requirements affect Ghost
  • Portfolio inspiration, CSS tricks, and Copilot cheat codes
  • Casey Newtown's Platformer moves to Ghost
🏋️
Pro tip: In a recent Forum thread, users and staff shared their favorite features in Ghost like snippets, sidebar views, and more. See how you can use these features in your workflow.

New email requirements affect Ghost

Email has been around since the 1970s, but a lot has changed since the days of disco 🪩

In February 2024, Google and Yahoo are introducing new requirements that make email more secure and less spammy. These requirements fall under three categories:

  1. Authentication: Reliably know the source of your email
  2. Unsubscription: Stop getting unwanted emails easily
  3. Spam: Higher thresholds mean less spam in your inbox

We encourage you to check out the links above to learn more about these requirements, but we're going to focus here on what they mean for Ghost. (A version of this info is also available on our official Forum.)

💡
Ghost(Pro) has already implemented changes to comply with these requirements. See our help docs or reach out to support to learn more.

Who's affected by these requirements?

By and large, these new requirements apply to Ghost publications that send newsletters to at least 5,000 recipients per day. If your publication falls under this threshold, these requirements don’t apply to you.

What do Ghost sites need to do?

The good news is that many Ghost sites are likely already compliant and don’t need to do anything 🙂

  • Update Ghost to the latest version. In recent releases, we’ve updated Ghost to comply with these new requirements, including the ability for members to easily unsubscribe and better support for custom-sending domains.
  • Configure DMARC records for email domains and confirm SPF and DKIM records are configured correctly. These records are set via your DNS, not via Ghost.

Will this affect my deliverability?

Google and Yahoo’s new requirements are significant. These changes are being gradually rolled out and may initially encounter some speed bumps. With that in mind, we expect to see volatility in deliverability rates across the entire email industry for the next few months.

In the long run, though, this will be a big win for reputable newsletters with less cluttered inboxes, a better experience for readers, and more security for senders.

Where can I learn more?

These new requirements promise a better email experience that’s more secure and less spammy 💌

However, dealing with these requirements is complex. Visit the Ghost Forum with questions or if you're seeking additional guidance.

Ideas and tools 🛠️

Platformer, now on Ghost

Casey Newton's Platformer recently migrated from Substack to Ghost. Read about why they made the switch.

💌 Build with Ghost: Email is changing in a big way

Platformer publishes on social networks and their relationship with the world. They take on questions about the political, social, and technological impacts of these platforms.

If you ever wondered whether "the Taylor Swift deepfakes are a warning," whether "platforms killed Pitchfork," or whether "Facebook helps predators find each other," then you, like 140,000 others, will likely find the Platformer fascinating.

💌 Build with Ghost: Email is changing in a big way

Sites featured in the Build with Ghost newsletter are discovered through our creator network, Ghost Explore. It’s a way for creators and readers alike to discover their favorite new publications. Anyone running a Ghost site can add themselves to Explore to be featured throughout the wider Ghost ecosystem. If you’d like to be featured in this newsletter, add your site to Explore and reply to this email.

💌 Build with Ghost: Email is changing in a big way

Thanks for building with us.

Have an idea for a Ghost tutorial? Reply to this email and let us know ❤️

Looking for other creators and developers working with Ghost? Join the official Ghost Forum, where we talk about all things Ghost!

]]>
<![CDATA[🎁 Build with Ghost: Wrapped 2023]]>https://ghost.org/tutorials/build-with-ghost-wrapped-2023/657a30cb3dc82b0001c132cdMon, 18 Dec 2023 15:58:17 GMT

Welcome to the final issue of 2024 🥂 Here's what we have in store:

  • A rundown of everything that came to Ghost in 2023
  • Learn how Rob Conery transformed his Ghost site into a course platform and other resources on style and design
  • Sites featured
  • Our most popular links
  • Tutorials published

Every new feature in Ghost from 2023

It was a busy year for Ghost. Here is every major feature we shipped this year 🚢 Kind of makes you excited for what we've got planned for 2024, right?

January

February

March

April

May

June

August

October

November

Ideas and tools 🛠️

🎁 Build with Ghost: Wrapped 2023

Featured sites from the above image, starting from the upper left. Many featured sites are found on the recently redesigned Ghost Explore.

These are the most clicked links from previous issues of Build with Ghost.

🎁 Build with Ghost: Wrapped 2023

We published these tutorials in 2023 to give you a few more moves when building with Ghost 💃 (Many of these tutorials also had accompanying YouTube videos.)

Thanks for building with us.

See you again in 2024 🙂

If you're itching for a Ghost fix before then, head over to our official Forum, where we're always talking about Ghost, from debugging problems to discussing clever tips and tricks.

]]>
<![CDATA[📝 Build with Ghost: Documentation incoming]]>https://ghost.org/tutorials/build-with-ghost-documentation-incoming/6571d7ea6e3bf20001c3e027Mon, 11 Dec 2023 09:06:41 GMT

Let's turn this one up to #11. Here's what this issue is rocking:

  • Documentation in two shakes of a lamb's tail
  • This site will provide plenty of inspiration for your next theme
  • Philippe made ts-ghost and it's awesome
  • Airtable works great with Ghost (and publishes with us, too)
🏋️
Pro tip: We shared some top-tier tips and tricks on this recent Forum thread.

Ghost & Raycast: Search our docs fast

Raycast is an extendable launcher for MacOS. It's a successor to Alfred and a replacement for Spotlight. In a nutshell, it's a super efficient way to open files and apps, manage windows, jump into your next meeting, convert and transform values, and so much more.

Ghost is now part of that "so much more."

We recently shipped a Raycast plugin to provide fuzzy, typeahead search across all of our documentation.

0:00
/0:16

That means you have instant access to our help center, developer docs, tutorials, changelog, and publisher resources. You can also narrow your search to only return results from a particular source.

Head over to the Raycast store to install the extension.

😪
At the moment, Raycast is only available on MacOS, so if you're on a different OS, you'll need to sit tight.

Just shipped 🚢

  • Emoji autocomplete: The Ghost editor now streamlines your emoji input. Type a colon : and some text to search for emojis and use them in your text 😄
📝 Build with Ghost: Documentation incoming

Ideas and tools 🛠️

  • Site Inspire provides a filterable gallery of beautiful websites. It's a fantastic resource for finding design inspiration (as the name implies).
  • The annual State of JavaScript survey is out. It tracks responses from the developer community to report feature and framework usage, trends, and demographics. Also, because it's a survey built by developers, it's chockablock with some sweet bells and whistles.
  • Web Dev Simplified recently published this YouTube video about lesser-known JS array methods like groupBy and with. How many of these do you know?
  • This interactive tutorial by fffuel.co teaches you how to create an SVG spinner. And their whole site has loads of helpful tools like noise and grain generators.

From the community

We recently caught up with Philippe on his amazing ts-ghost library. It's a collection of tools for interacting with Ghost. These tools, written in Typescript, provide convenience, validation, and, of course, types when working with the Ghost Admin and Content APIs.

📝 Build with Ghost: Documentation incoming

A huge benefit of this library, even if you're not using Typescript, is clever autocomplete in your code editor. For example, rather than having to check the docs for the properties available on the post object, ts-ghost will let you know it's feature_image, not featured-image.

But things don't end there.

Philippe shared his favorite aspects of the library, too. For instance, he uses a cool library called Zod to validate expressions like filter and order. For example, trying to get all posts tagged with art by using the incorrect filter, category:art, generates a validation error right in your editor. (It should be tag:art.) This feat of engineering is accompanied by other details that make using this library an absolute joy 😍

0:00
/0:58

ts-ghost in action

Philippe was inspired to build this library because he often works with the Ghost API in combination with other JS frameworks. He's the author of the Ghost/Astro integration and uses a combination of Remix and Ghost for his learning platform, Coding Dodo.

Coding Dodo - Odoo, Python & JavaScript Tutorials
Odoo, ERP, and Python Tutorials. Real-world examples and useful code snippets on all Odoo versions covered but focus on the latest releases. Join us!
📝 Build with Ghost: Documentation incoming

Philippe is currently a software engineer who works on B2B ERP (enterprise resource planning) web apps and contributes to open source in his free time. He's also a jazz musician (his original passion), and we're hoping his next contribution will be an album titled: Music to write Ghost blogs to.

Until then, find Philippe on GitHub, X, and be sure to try out ts-ghost.

Airtable is cloud-based software that combines elements of a database with the user-friendly experience of a spreadsheet. It pairs well with Ghost if you want a no-code way to present complex data.

Airtable also runs their product blog, For the Record, on Ghost.

📝 Build with Ghost: Documentation incoming

The design is clean and elegant, providing a comfortable reading experience. The blog communicates product updates, new features, best practices, and represents a perfect example of how businesses can strategically use Ghost for content marketing.

📝 Build with Ghost: Documentation incoming

Sites featured in the Build with Ghost newsletter are discovered through our creator network, Ghost Explore. It’s a way for creators and readers alike to discover their favorite new publications. Anyone running a Ghost site can add themselves to Explore to be featured throughout the wider Ghost ecosystem. If you’d like to be featured in this newsletter, add your site to Explore and reply to this email.

Thanks for building with us.

Have an idea for a Ghost tutorial? Reply to this email and let us know ❤️

Looking for other creators and developers working with Ghost? Join the official Ghost Forum, where we talk about all things Ghost!

]]>
<![CDATA[➕ Build with Ghost: Recommendations for the open web]]>https://ghost.org/tutorials/we-recommend-this-newsletter/654abfafffb3f90001db5691Fri, 10 Nov 2023 15:20:18 GMT

Welcome to issue #10! Here's what's cooking:

  • Get to know our newest feature: recommendations
  • Design inspo, advanced layouts, and pathfinding algos
  • A behind-the-scenes look at how we optimize Ghost
  • We found 404 Media and didn't go blind
🏋️
Pro tip: Our video tutorials on YouTube teach you everything you need to know to build awesome custom themes.

Recommendations

We just released an exciting new feature: recommendations. Now, it's possible to recommend your favorite sites, no matter where they live on the web. Likewise, other publications can recommend you 🤝

Access recommendations from the updated Settings page. Recommendations show you not only how many clicks or subscriptions you've referred to recommended sites, but also how many signups have been sent your way. Read the Changelog for more about the new feature, visit the Help center to understand how it works, and check out these recommendations to see the feature in action.

➕ Build with Ghost: Recommendations for the open web

But this is Build with Ghost, so we're going to get just a bit more technical.

Under the hood

One of the most exciting aspects of recommendations is that it's built on an open standard called Webmentions. By building it this way, Ghost's recommendation feature escapes walled gardens and vendor lock-in, operating, instead, across the entirety of the internet. That means you can recommend publications on other platforms — and they can recommend you 💪

1-click subscriptions

Recommendations have another trick up their sleeve. As its name implies, 1-click subscriptions streamline the membership process by allowing readers to sign up for a publication with a single click.

Currently, 1-click subscriptions are only supported between Ghost publications. However, we're eager to help other platforms implement this 1-click functionality, and Micro.blog and Steady have already expressed interest. If you're a platform that wants to build 1-click subscriptions for the open web, get in touch.

Recommendations & themes

The recommendations feature brings two new theme helpers with it.

{{recommendations}}

The recommendations helper outputs a list of your recommended sites. Highly customizable, this helper is a great way to share your favorite publications with readers. Below is the default template Ghost uses to output your recommendations (but you can create a totally customized template, too).

➕ Build with Ghost: Recommendations for the open web

Check out the docs for all the details on this new helper and see how it's already implemented in our Source theme.

{{readable_url}}

The readable_url helper outputs a human-readable URL. When linking to a recommended site, instead of showing https://www.google.com?foo=bar&dog=love, it'll just show google.com. In short, it's a glow-up for your URLs and works beautifully with the recommendations helper mentioned above.

See the docs to learn more about this helper.

Just shipped 🚢

Ideas and tools 🛠️

From the community

Ghost Forum user, Jannis, has created Myrtle, a tool to add mock data to your Ghost site using OpenAI's API.

Jannis explains the tool best:

See, as somebody who loves good design, I hate it when it’s destroyed by Lorem Ipsum content. So, I always try to put realistic content onto my theme demo sites. Something that tells a story – and actually demonstrates how it can be used.

We used Myrtle to create this mock site, Delicious Curry. The story it tells: we're hungry. If you're looking for a tool to whip up some stand-in content, this works great 🍛

➕ Build with Ghost: Recommendations for the open web
🔑
Friendly reminder: While we love celebrating community innovations, we also prioritize your safety. Please remember, when using software found online, especially those involving API keys, exercise caution. Always verify the source and understand the permissions you're granting.

Behind the scenes

Our DevOps engineer, Sam, recently wrote an article on some work he did to optimize Playwright tests in Ghost by making them run 185% faster 🏎️

In a nutshell, this means Ghost engineers can spend less time waiting for tests to run and more time building cool features, and we all get a more resilient, bug-free Ghost.

Formed by four journalists previously at VICE's Motherboard, 404 Media is a publication committed to sustainable, society-shifting tech journalism. They recently got to the top of Hacker News by publishing a story about how attendees at a Bored Ape NFT owners conference went blind with searing eye pain. Yes, you read that right.

‘Couldn’t See Anymore:’ Bored Ape Conference Attendees Wake Up With Searing Eye Pain, Vision Loss
“Been to lots of concerts, festivals, Burning Man, and never have I ever experienced fucked eyes like this.”
➕ Build with Ghost: Recommendations for the open web

Aside from the important, captivating journalism like "In Defense of RAM" and "Mastodon is the Good One," 404 Media has a simply gorgeous custom theme. The typography, layout, and post elements will make you swoon and provide some inspiration for your future themes.

➕ Build with Ghost: Recommendations for the open web

Sites featured in the Build with Ghost newsletter are discovered through our creator network, Ghost Explore. It’s a way for creators and readers alike to discover their favorite new publications. Anyone running a Ghost site can add themselves to Explore to be featured throughout the wider Ghost ecosystem. If you’d like to be featured in this newsletter, add your site to Explore and reply to this email.

Thanks for building with us.

Have an idea for a Ghost tutorial? Reply to this email and let us know ❤️

Were you spending all your time looking for other Ghost creators and developers on Omegle? Unfortunately, you may need to look somewhere else. Come and join us on the official Ghost Forum, where we talk about all things Ghost!

]]>
<![CDATA[⦿ Build with Ghost: Meet our new official theme]]>https://ghost.org/tutorials/build-with-ghost-meet-our-new-official-theme/651c3063b478c00001284e7bWed, 11 Oct 2023 08:03:08 GMT

October is a month of change 🍂, and we've got some big ones to share in this month's issue:

  • Source has launched! Our new default theme brings customization to a whole new level 🚀
  • Can you spot an AI-generated image? How much do you know about Unicode (and why does it matter)? All this and more in our "Ideas and tools" section.
  • This month's featured site, OpenSauced, combines two of our favorite things: pizza and open-source software 🍕 💻
🏋️
Pro tip: Ever wondered where to find all the available keyboard shortcuts? They're now included right in the Editor. Look for Keyboard shortcuts in the sidebar.

Meet Source, Ghost's new default theme

⦿ Build with Ghost: Meet our new official theme

That's right! Casper is no longer Ghost's default theme. (But don't sweat, it's still available from the Ghost Marketplace.)

The goal of Source is to offer a highly configurable theme that can accommodate almost any publication style — all without having to write a line of code. By turning some knobs and dials, authors can achieve radically different layouts and identities, as seen in the screenshots below:

⦿ Build with Ghost: Meet our new official theme
Highlight Layout
⦿ Build with Ghost: Meet our new official theme
Magazine Layout
⦿ Build with Ghost: Meet our new official theme
Landing Page Layout

But that's not all. Source brings some new features for theme developers, too.

Custom setting visibility

With custom setting visibility, theme developers can show custom settings to their users only when those settings are relevant. This ability makes your theme easier to navigate and the user experience more intuitive.


If you're unfamiliar with how custom settings work in Ghost, check out our tutorial for everything you need to know.

Custom settings are the ultimate power-up for Ghost themes
Want to elevate your Ghost theme? Dive into custom settings with this complete guide. Choose typefaces, color schemes, and more. Your theme, your rules!
⦿ Build with Ghost: Meet our new official theme

While custom setting visibility makes the user experience more intuitive, this feature itself might be a little unintuitive. Keeping with our pizza theme, here's an explanation.

Your user orders a pizza, so you show them the toppings option. They can choose mushrooms, pepperonis, or if they're a genius, pineapple. Showing the toppings option makes sense because they chose pizza. However, if they chose salad, showing the toppings option wouldn't make sense 🙅

⦿ Build with Ghost: Meet our new official theme

Custom setting visibility works the same way. You control which settings are visible depending on the values users choose. Let's look at a real-world example to see this concept in action.

In Source, it's possible to toggle the background image on and off — but only when the Header style option is Landing or Search.

⦿ Build with Ghost: Meet our new official theme
Search layout with background image
⦿ Build with Ghost: Meet our new official theme
Search layout without background image

For other layouts, this option doesn't make sense because there isn't a background image to toggle, like in the Magazine layout below.

⦿ Build with Ghost: Meet our new official theme
Magazine layout

Setting visibility ensures that the background-image toggle is only available when the option is relevant. The graphic below shows precisely how options change depending on the value of Header style:

⦿ Build with Ghost: Meet our new official theme

Now that you have a handle on custom setting visibility, learn how to implement it in your theme and provide a more refined, intuitive experience for your users 🤵

More custom settings

Custom settings were limited to 15. Now it's 20.

Go straight to the Source

The best way to learn how to build a Ghost theme is by checking out the open-source code that powers our official themes. This has never been more true than for Source. Not only does Source show you how to build a highly customizable theme using best practices, but it also includes lots of comments along the way that explain exactly what its code is doing.

GitHub - TryGhost/Source: The default theme for Ghost
The default theme for Ghost. Contribute to TryGhost/Source development by creating an account on GitHub.
⦿ Build with Ghost: Meet our new official theme

Ideas and tools 🛠️


⦿ Build with Ghost: Meet our new official theme

All about open source at OpenSauced

OpenSauced.pizza is not only a delicious domain name, but also a haven for open-source enthusiasts. We chatted with Bekah from OpenSauced about the company, its mission, and why they use Ghost for their newsletter about open source.

OpenSauced embraces the expansive world of open source, emphasizing that it's not just about code. Their perspective? Everyone can contribute to the open-source sphere, whether through detailed bug reports, insightful blog articles, or fostering community connections.

For those looking to get into the world of open-source software (OSS), OpenSauced offers a cool searchable database of repositories, featuring codebases that are trending and popular.

OpenSauced Insights
The open-source intelligence platform for contributors and maintainers. Unlock the power of open source with project insights by the slice.
⦿ Build with Ghost: Meet our new official theme

Ghost, too, is proudly open source. OpenSauced's decision to use Ghost for their newsletter was motivated by this fact. Bekah also notes Ghost's low barrier to entry that lets folks get started quickly, as well as more advanced approaches like using markdown, which makes her happy 🙂

Above all, we agree with OpenSauced that OSS is a great uniter, bringing people together from around the world to build "something bigger than individual projects." As Developer Experience Lead, Bekah is focused on enhancing the journey for both contributors and maintainers. Want to hear more from Bekah? Check out her recent video for deeper insights:


Sites featured in the Build with Ghost newsletter are discovered through our creator network, Ghost Explore. It’s a way for creators and readers to discover their favorite new publications. Anyone running a Ghost site can add themselves to Explore to be featured throughout the wider Ghost ecosystem. If you’d like to be featured in this newsletter, add your site to Explore and reply to this email.

⦿ Build with Ghost: Meet our new official theme

Thanks for building with us.

Have an idea for a Ghost tutorial? Reply to this email and let us know ❤️

Looking for other creators and developers working with Ghost? Join the official Ghost Forum, where we talk about all things Ghost!

]]>
<![CDATA[👩‍🎨 Build with Ghost: The art of the post template]]>https://ghost.org/tutorials/post-time/64de29799de13a0001cdb4a8Tue, 22 Aug 2023 08:31:05 GMT

Welcome to Issue #8! Some of what we have in store:

  • Our new tutorial shows you how to showcase your content by building the perfect post template
  • Updates to CSS that will blow your mind 🤯
  • Taking Ghost headless with Thimira

The art of the post template

👩‍🎨 Build with Ghost: The art of the post template

It's the heart and soul of your theme. It's where authors bring their creative content to life, and where readers immerse themselves in these narratives.

It's the post template, and, in our latest tutorial, we cover everything you need to know to build one. We focus on the following:

  • The basic anatomy of a post template
  • Understanding the data available in the post context
  • Steps to designing a captivating post header
  • Bringing in your content
  • Tips & tricks for creating a beautiful reading experience

Check it out 👉

The art of the post template in Ghost
Creating gorgeous post layouts has never been easier in Ghost. Dive into our step-by-step guide to learn everything you need to know about creating a custom post template.
👩‍🎨 Build with Ghost: The art of the post template

But wait! There's more.

We also released tutorials on using custom settings and building custom sign-up forms.

Custom settings are the ultimate power-up for Ghost themes
Want to elevate your Ghost theme? Dive into custom settings with this complete guide. Choose typefaces, color schemes, and more. Your theme, your rules!
👩‍🎨 Build with Ghost: The art of the post template
🏋️
Pro tip: When adding custom settings to your theme, use the new description key to communicate the setting's purpose to your users
How to build custom sign-up forms in Ghost
Learn to create a custom sign-up form with Ghost. This guide covers all steps, including HTML integration, CSS styling, and user engagement strategies.
👩‍🎨 Build with Ghost: The art of the post template

Did you know we have a YouTube channel? Our most recent video includes a complete guide to using partials in Ghost. Don't forget to like and subscribe 😜

Just shipped 🚢

  • Header cards got a massive upgrade, giving you more power to create beautiful pages and posts. (Header cards are full-width cards perfect for creating a division between sections or making a large call to action.)
  • In the same spirit, it's now possible to hide the title and feature image for pages, making it possible to build radically different landing pages.
🚧
Custom theme developers will need to update their themes to support the new @page helper that makes toggling the title and feature image possible.

Ideas and tools 🛠️

Getting technical with Thimira

Thimira Thenuwara recently relaunched Android Wedakarayo, a Sinhala publication about technology based in Sri Lanka. The relaunch is notable because Thimira shifted to using Ghost headlessly, implementing a Nuxt frontend with Tailwind styling, oAuth sign-in, and Algolia search. We'll explain all of this in a minute, but let's start at the beginning.

👩‍🎨 Build with Ghost: The art of the post template
Android Wedakarayo

By day, Thimira is a Deputy Manager of Finance for a group of companies in Sri Lanka. By night, certified Ghost Expert 🦸

His foray into Ghost development began when Android Wedakarayo transitioned from WordPress to Ghost. At first, the publication used stock Casper (always a good place to start). Here and there, Thimira began customizing it to suit the publication's needs, eventually developing a totally bespoke theme.

Before hacking on his Ghost theme, Thimira didn't know web development at all! He taught himself HTML, CSS, and JS and says, "The platform taught me the ropes of web design." He also had a great support network to help him: another Ghost Expert, Kasun Jayarathna, got him up to speed on Ghost, Srilal Sachintha taught him Linux servers, and his fiancée, Shenaya Hewagama, cheered him on throughout.

Ghost is truly a fantastic gateway to learning web development. The cost of entry is low and the payoff is high: a totally customized, beautiful publication. Just be careful because before you know it, you'll be building a headless Ghost site with Nuxt, Algolia, oAuth, and a handful of other custom features 😏 Let's talk about what all this means.

Running Ghost headlessly means using Ghost's API with a frontend other than Ghost's native theme layer. While it enables advanced functionality, headless is not the way to go for most users. Ghost's theme layer, for example, includes the metadata that optimizes your site for SEO. Going headless means you need to code that functionality yourself.

Using a framework like Nuxt (based on Vue) for your frontend can ease some of the burden by providing plugins and packages to help you rebuild features from Ghost's theme layer.

Algolia is an advanced search-as-a-service. It can be used with any Ghost site, and we use it on our Tutorials site. Learn more about setting up Algolia on Ghost in our docs.

oAuth (open authorization) is a protocol that allows third-party apps to access user data without exposing user credentials. A common example, and the one Thimira implemented, is using Google or Apple to sign into a third-party website.

To see the whole thing in action, go check out Android Wedakarayo. We'd also be remiss if we didn't mention Thimira's Apple-inspired personal site, which has lots of clever animations.

👩‍🎨 Build with Ghost: The art of the post template

Sites featured in the Build with Ghost newsletter are discovered through our creator network, Ghost Explore. It’s a way for creators and readers alike to discover their favorite new publications. Anyone running a Ghost site can add themselves to Explore to be featured throughout the wider Ghost ecosystem. If you’d like to be featured in this newsletter, add your site to Explore and reply to this email.

👩‍🎨 Build with Ghost: The art of the post template

Thanks for building with us.

Have an idea for a Ghost tutorial? Reply to this email and let us know ❤️

Looking for other creators and developers working with Ghost? Join the official Ghost Forum, where we talk about all things Ghost!

]]>
<![CDATA[Build a custom sign-up form]]>https://ghost.org/tutorials/form/64d3ad903bf35a000198a7ccThu, 10 Aug 2023 19:25:49 GMT

For publications with a strong brand identity or those looking to fully optimize their Ghost site, a custom sign-up form is more than just a tool — it's an extension of the brand itself.

Using Of Record, a publication focusing on vinyl collecting and music listening, as our example, we'll delve into:

  • The reasons for going bespoke
  • The anatomy of a custom sign-up form
  • A peek into what makes an engaging sign-up form

Here's a preview of the sign-up form we'll build in this tutorial:

0:00
/0:13

Ready to elevate your sign-up form into a memorable experience? Let's dive in!

It may be simpler than you think

For most publications, Ghost already offers a simple solution that works out of the box and without any custom code.

Embeddable signup forms
Start growing your audience from anywhere on the web, using the new embeddable signup forms. It’s now even easier attract new subscribers from any website, while keeping Ghost as the hub for your memberships. Branded Include your logo, publication name, and description in your signup form, and…
Build a custom sign-up form

Head to SettingsMembership, select a layout, and color, apply your labels, then simply copy the embed code for use anywhere on the web. Here's a live example:



However, for advanced users, Ghost provides tools for creating a completely custom sign-up form that allows you to:

  • Fully align the form with your brand's visual identity.
  • Provide a unique user experience.
  • Optimize performance.

Let's see these tools at work by analyzing Of Record's sign-up form, shown below.

Build a custom sign-up form

Anatomy of a custom sign-up form

The beauty of building a custom sign-up form is that it's exactly the same as building one with standard HTML elements. Integrating it with Ghost is as simple as adding a few custom data attributes. Here's the code for Of Record's sign-up form:

<form data-members-form= >
    <input data-members-label type="hidden" value="Turntable buying guide" />
    <label>
        Name
        <input data-members-name />
    </label>
    <label>
        Email
        <input data-members-email type="email" required />
    </label>
    <button>
        Sign up
    </button>
    <p class="loading">⏲️ Please hold while we check our collection.</p>
    <p class="error">❗Something's gone wrong. Please try again.</p>
    <p class="success">🎸 Success! Check your inbox for our email.</p>
</form>

Putting this form anywhere in your theme or on your site via an HTML card will instantly create a custom sign-up form ✨

Let's talk about the necessary attributes that make it work.

Activate the form

To make Ghost aware of your custom form, add the data-members-form attribute to the form. Note that you can change the language of the email that a new member will receive by adding a value to the attribute:

  • data-members-form="signup": new members receive an email with "sign up" language
  • data-members-form="subscribe" (default): new members receive an email with "subscribe" language

Functionally, both of these options are identical. Opting for one or the other will depend entirely on your publication's identity. See additional options for the data-members-form attribute in the docs.

💡
Use the match helper with the @member object to only show the sign-up form to nonmembers. Learn more.

Get a name

<label>
    Name
    <input data-members-name />
</label>

In Of Record's form, we wrap the input with a label element. This approach is optional, but it's a convenient method to associate the label and input, which makes the form more accessible.

The data-members-name attribute tells Ghost to collect the member's name. However, because required is omitted from the input, this field is optional. A member will be able to sign up without giving their name. To require a name, use the required attribute as seen in the next section.

Get an email

<label>
    Email
    <input data-members-email type="email" required />
</label>

On this input, we include the type="email" and required attributes. These help with validation (the browser checks if the email is valid) and required ensures a value is present before submitting.

The magic comes in with the addition of the data-members-email attribute, which Ghost uses to capture the submitted email.

Add a label

In addition to capturing a name and email, it's also possible to add a label to members who sign up with your custom form. These labels appear on the member's profile in Ghost Admin and are filterable via the Members menu. Also, when sending an email, you can use these labels as recipient groups. This works great if your sign-up form is coupled with particular content, and you want to send an update related to that content. With labels, you already have a list of everyone interested in that content!

Here's what the member profile looks like in Ghost Admin. Note the "Turntable buying guide" label.

Build a custom sign-up form

And, here's the code to add to set a label.

<input data-members-label type="hidden" value="Turntable buying guide" />

It works by adding a hidden input type (meaning it won't appear to the user) along with the data-members-label attribute. Then, set the value to the label you want to add. That's it!

Now, whenever someone signs up with your custom form, this label will be applied automatically.

💡
Bright Themes has an advanced tutorial on letting users choose which labels are associated with their signup. Check out how it's done.

Form states and CSS styling

<p class="loading">⏲️ Please hold while we check our collection.</p>
<p class="error">❗Something's gone wrong. Please try again.</p>
<p class="success">🎸 Success! Check your inbox for our email.</p>

Not only does adding Ghost's custom data attributes ensure your form gets your members signed up, but it also adds relevant classes as the user signs up. These classes, added to the form element, reflect its state: loading, success, and error.

Build a custom sign-up form
Build a custom sign-up form
Build a custom sign-up form

These classes enable you to convey the form's state to your user. How you want to do this is completely up to you, but we'll show you the basic logic to implement in CSS.


/* Form states */
:where(.loading, .success, .error)  {
    display: none;
}

.loading .loading, .success .success, .error .error {
    display: block;
}

We set the default style of the states (like <p class="success">) to display: none. Then, we override these states when Ghost adds the class to the form element. For example, here's what the form HTML looks like when the sign up is loading:

<form data-members-form class="loading">
  ...
</form>

The loading class on the form and the same class on the p element makes the selector .loading .loading match and updates the display property to show the state.

Because it's just CSS controlling whether elements are shown, you can simulate the different states by adding and removing the different classes from the form, rather than having to actually sign up over and over again.

Keeping the user apprised of where they are in the sign-up process is possible with just a few lines of CSS and opens up lots of creative possibilities when creating a custom form.

Designing content for your form

Now that you know how to make a custom sign-up form, you may be faced with the tricky task of what actually to put in it 🤔

With a custom sign-up form, you can take any approach you want:

  • Minimalist: Simple, clean typography focuses on essential values
  • Visual storytelling: Imagery tells a story and connects with the audience
  • All about the benefits: Bullet points or icons convey the value position instantly
  • Interactive experience: Animations, transitions, and interactive elements engage the user and make signing up a blast

These are but a few of the approaches you can take, which makes things difficult. How can you create an effective sign-up form? Don't worry! We've got you covered over on Ghost Resources.

We share evidence-based best practices to support creators, businesses, and publishers. For example, check out this formula for creating powerful copy or these strategies for building a sign-up form that converts.

Summary

Whether you're a publication with a strong brand identity like Of Record or someone looking to fully optimize your Ghost site, a custom sign-up form is a powerful tool to build your audience.

With knowledge of Ghost's custom data attributes and the styles to show and hide form states, you now have everything you need to create gorgeous, custom sign-up forms.

If you create one, don't hesitate to share it with the Ghost community. We like to hang out on the official Forum. It's also a great place to get ideas and learn more about building with Ghost.

Oh, and don't forget to sign up 💌

Build a custom sign-up form

Make your inbox fire

Build a better internet with early access to features, tools, and tutorials.

No spam. Once a month. Unsubscribe any time.

]]>
<![CDATA[Custom settings are the ultimate power-up for themes]]>https://ghost.org/tutorials/custom-settings/64d133e3ea74ed000169d127Mon, 07 Aug 2023 23:04:43 GMT

Custom settings are perfect for developers building themes because users can tailor their theme to match their publication without having to touch a line of code. Even if you’re building a theme for yourself, custom settings give you instant control over aspects like typeface, layout, colors, and much more. The following guide will walk you through everything you need to know to make the most of custom settings in your Ghost theme.

An overview of custom settings

Use custom settings to create different possibilities for your theme — possibilities that users can configure right from Ghost Admin. For example, let users choose the tone for their publication by giving the option to have a refined serif typeface or a modern sans serif one.

While we’ll go into the details below, here are the essential points to know about custom settings:

  • Define custom settings in your theme’s package.json file
  • Access the values with the @custom helper
  • You can have up to 20 custom settings

How to configure custom settings

Set up custom settings in the theme’s package.json file, under the config.custom key. Add each setting as a new key, using snake_case. Here’s an example of a custom setting called “typography”:

{
    "config": {
        "custom": {
            "typography": {
                "type": "select",
                "options": ["Modern sans-serif", "Elegant serif"],
                "default": "Modern sans-serif",
  			    "description": "Define your site's typography"
            }
        }
    }
}

The most important option to set for each setting is its type because it determines which other keys are required.

Understanding types

There are five possible types. Let's look at each in detail.

Select

As seen in the example, the select type presents the user with a dropdown of options you define in the required options key. A default key is also required. It must contain a value that matches one of the defined options.

Boolean

The boolean type presents the user with a true/false toggle. When using the boolean type, you must also specify a default value (true or false).

Color

The color type presents the user with a color picker. A default hex color must be provided when using this type.

💡
Remember that Ghost already provides the ability for a user to set an accent color in Design settings that can be accessed via the @site.accent_color helper.

Image

The image type presents the user with an image uploader. The output from this type is either an image URL or a blank string. The image type works great with the img_url helper, which allows you to optimize the uploaded image automatically!

Text

The text type presents the user with a text input. The default value is optional, meaning that it’s possible for the output of this type to be empty.

Find a full overview of these types in the docs.

Add descriptions to share the purpose of custom settings

For each type, it's possible to add an optional description. The value provided for this key appears in Ghost Admin with the custom setting. It's a great way to communicate to users what the custom setting is for.

By giving the setting a name, description, type, and any additional required keys, you've defined a custom setting. Oh, yeah! Let's see how to access its user-defined value in the theme.

Access custom settings within the theme

Gain access to the user-defined value with the @custom helper plus the setting name. To access the typography setting above, use @custom.typeface anywhere in the theme.

To then change the typeface for the theme, use the custom setting to modify the CSS class on the body tag in default.hbs.

<body class="{{#match @custom.typeface "Modern sans-serif"}} has-sans-serif-font{{else}} has-serif-font{{/match}}</body>

Use the match helper

We use the match helper above to test the value of the custom setting. Specifically, we’re testing whether the typeface value equals “Modern sans-serif.” (When using the match helper to test equality, the = sign can be omitted.) It’s also possible to test other conditions by using different operators: !=, <, >, >=, and <=. If the custom setting equals "Modern sans-serif," then the has-sans-serif-font class is output. Otherwise, has-serif-font is output.

The only other required action on your part is to include the classes in your CSS:

.has-sans-serif-font {
  font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
}

.has-serif-font {
  font-family: Iowan Old Style, Apple Garamond, Baskerville, Times New Roman, Droid Serif, Times, Source Serif Pro, serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;;
}

Now, the user can set their desired typeface right from Ghost Admin (and change it any time if they’re so inclined) 🔠

💡
Remembering the exact value you used to name a custom setting can be a drag, requiring you to jump back into your package.json file. Use our official VS Code extension to autocomplete your custom settings. When in a Handlebars file, type custom, and the extension will autocomplete the property with your settings, even adding the @ sign.

Grouping custom settings

There’s one last bit of configuration possible for custom settings: groups. By default, all custom settings are put in the Site-wide group, meaning that the setting is applicable across the whole publication.

However, specific groups exist for settings that only apply to the homepage or post pages. For example, with Casper, it’s possible to specify three different layouts on the homepage. Here’s how that option is defined in package.json and its group defined:

"feed_layout": {
    "type": "select",
    "options": [
        "Classic",
        "Grid",
        "List"
    ],
    "default": "Classic",
    "group": "homepage"
}

For settings applicable to post pages, set the group to post.

And that’s everything you need to know about custom settings. Here’s a visual to help bring it all together.

Custom settings are the ultimate power-up for themes

Custom settings in the wild

Eager for a few more examples? Let's check out two different ways custom settings are used in Ghost’s default theme, Casper.

Dynamic color scheme

Imagine giving your users the power to switch between light and dark modes, or even automate the color scheme based on OS preferences. Casper does just that!

"color_scheme": {
    "type": "select",
    "options": [
        "Light",
        "Dark",
        "Auto"
    ],
    "default": "Light"
}

The color_scheme custom setting allows users to choose whether they want their site to display in light, dark, or auto mode.

The custom setting is accessed in default.hbs on the html tag:

<html lang="{{@site.locale}}"{{#match @custom.color_scheme "Dark"}} class="dark-mode"{{else match @custom.color_scheme "Auto"}} class="auto-color"{{/match}}>

When the color scheme is set to “Dark,” the dark-mode class is added to the element (and auto-color is added when that option is chosen). Then, in the theme’s CSS, styles are added with classes to reflect these choices. For example, here’s the rule that sets the background to a dark color and the text to a light color:

html.dark-mode body {
    color: rgba(255, 255, 255, 0.75);
    background: var(--color-darkmode);
}

The takeaway? You can dynamically add and remove CSS classes based on user preferences, creating multiple styles within a single theme.

Personalize the sign-up call to action

Custom text for the sign-up CTA (call to action) on Casper’s post page makes the experience more engaging. Here's the setting:

"email_signup_text": {
    "type": "text",
    "default": "Sign up for more like this.",
    "group": "post"
},

Key insights:

  • Fallback text: If the user doesn’t provide their own, a default is provided to ensure the CTA text isn’t blank.
  • Group definition: This setting shows up under the "post" dropdown, making it specific to post pages.

The screenshots below show how this setting appears in Ghost Admin and the default and personalized call-to-actions on the post.

These examples illustrate a few of the many possibilities offered by custom settings. Dive in and explore these features and other custom settings in Casper. Learning from official Ghost themes is a fantastic way to level up your theme-building skills 💪

Summary

With custom settings, you can hand the creative reins to your users, allowing them to make your theme their own. Through this guide, you've learned how to define, access, and leverage various types of custom settings, seen practical examples, and grasped precisely how these settings can transform a user's interaction with your theme.

But your adventure is just beginning.

Visit our official Forum to see what other developers are up to or subscribe to our Build with Ghost Newsletter, the best way to keep up with changes in Ghost and find inspiration for your next gorgeous theme.

]]>
<![CDATA[The art of the post template]]>https://ghost.org/tutorials/post-template/64cab735602c87000170a39cThu, 03 Aug 2023 23:00:48 GMT

The post template is the heart and soul of a theme. It’s where authors bring their creative content to life, and where readers immerse themselves in these narratives. In this comprehensive tutorial, we'll guide you through each stage of creating a stunning post template. By the end of it, you'll be well-equipped to construct your own unique post templates in Ghost.

Using the post template from the fictional music publication, Of Record, as a guide, we'll delve into:

  • The essence of a post template
  • Understanding the data available in the post context
  • Steps to design a captivating post header
  • Bringing in your post content
  • Tips and tricks for creating a beautiful reading experience

Are you ready to create the perfect post template with us? Let's get started! To help you better visualize what we're working on, we've included a short video of the post page we're about to create.

0:00
/0:10

Of Record's post template

What's the post template?

The post template, aptly named post.hbs, is responsible for rendering your post content, that is, anything and everything you write in the editor. The template file must be placed in the root of your theme. (If a theme doesn't have a page.hbs template, Ghost will use the post template to render pages, too.)

.
├── LICENSE
├── README.md
├── assets
├── author.hbs
├── default.hbs
├── error-404.hbs
├── error.hbs
├── gulpfile.js
├── index.hbs
├── package.json
├── page.hbs
├── partials
├── post.hbs # The post template
└── tag.hbs

Theme file structure

Accessing post data

The post template opens with two essential bits of Handlebars code.

{!< default}}

{{#post}}

{{!< default}} instructs Ghost to embed the post template into the default layout. If you imagine your webpage as a sandwich, then your default template serves as the slices of bread, while the post template is the filling. For more details, check out our tutorial on the default template.

Moving on to {{#post}}, this command opens the post context, granting you access to post data and helpers. This means you can now tap into crucial data like the post title, feature image, author, and more. As we traverse through Of Record’s post template, we’ll elucidate the data and helpers that are most likely to come in handy. For a comprehensive list of all available data and helpers, visit the post context docs.

Dynamic styling with post_class

Here's the next line of the post template:

<main class="or-post or-container {{post_class}}">

There are two key aspects to focus on in this tag:

  1. Static classes: We use two static classes. or-post defines the max width of the post content, and or-container pads and centers the content.
  2. Dynamic classes with {{post_class}}: This helper dynamically outputs classes based on the post data. Here's how it works:
  • All posts automatically get the post class
  • Featured posts get the featured class
  • Pages get the page class
  • Every tag associated with the post provides a class in the format tag-{slug}.

For the example post, "The Role of Independent Record Stores," which has the "industry" tag, {{post_class}} is rendered as post tag-industry. The screenshot below shows the final output of the post's static and dynamic classes.

The art of the post template
Output of {{post_class}}

These dynamic classes open the door for you to target posts, programmatically changing styles based on a tag or featured status.

Create the post header

The art of the post template

The next part of the template is the post header. It contains all the metadata about your post, including its title, publication date, author(s), tags, feature image, and more.

Above, we've shared a diagram that shows the code underlying each header element. Let's walk through this code to understand it better:

<header class="or-post-header">
    <div class="or-post-header-text">
        {{#match primary_tag}}
            <div class="or-post-header-tag" style="--color: {{primary_tag.accent_color}}">
                <a href="{{primary_tag.url}}">{{primary_tag.name}}</a>
            </div>
        {{/match}}
        
        <h1 class="or-post-header-title">{{title}}</h1>
        
        {{#match custom_excerpt}}<p>{{custom_excerpt}}</p>{{/match}}

        {{#is "post"}}
        <div class="or-post-header-meta or-flex">
            <div>
                <p class="or-post-header-label or-text-light">{{plural authors.length empty="" singular="Author" plural="Authors"}}</p>
                <p class="or-post-header-value">{{authors}}</p>
            </div>
            <div>
                <p class="or-post-header-label or-text-light">Published</p>
                <p class="or-post-header-value">{{date}}</p>
            </div>
            {{#match feature_image_caption}}
            <div>
                <p class="or-post-header-label or-text-light">Image credit</p>
                <p class="or-post-header-value">{{feature_image_caption}}</p>
            </div>
            {{/match}}
        </div>
        {{/is}}
    </div>
...

The primary tag

{{#match primary_tag}} 

Inside the post context, we have access to the primary_tag object, that is, the first tag on a post. The match helper is then employed to check whether a post has a primary tag. If you're unfamiliar with the match helper, think of it as a gatekeeper. It only allows the code within the match tags to run if the post has a primary tag. Otherwise, it instructs the code to skip this block.

When the post has a primary tag, the following code displays the tag's name and provides a link to it:

<div class="or-post-header-tag" style="--color: {{primary_tag.accent_color}}">
    <a href="{{primary_tag.url}}">{{primary_tag.name}}</a>
</div>

There are a few interesting things happening here.

In Ghost Admin, it’s possible to set an accent color for each tag, which is why “Industry” has a red color. By using an inline style tag, we can dynamically define the color with CSS custom properties.

Here's a diagram that walks through the process of how this works:

The art of the post template

We then create a link to the tag page with an anchor link, setting the href via the primary_tag's URL property.

Finally, we display the tag’s name: {{primary_tag.name}}.

This dynamic feature allows you to draw attention to the main topic of the post, providing readers with a clear understanding of the post's theme at first glance.

Post title

<h1 class="or-post-header-title">{{title}}</h1>

The next line of code brings in the post title with the {{title}} helper. This one is about as straightforward as it gets!

Custom excerpt

{{#match custom_excerpt}}<p>{{custom_excerpt}}</p>{{/match}}

The match usage here is identical to the one above: we’re testing for the existence of a custom excerpt, which means an excerpt that’s deliberately set by the author (not automatically generated). If set, we show the custom excerpt. Using the match helper ensures that we don’t have an empty p tag on our rendered page.

Here's our example post with and without a custom excerpt:

Working with post metadata

Adding rich, relevant metadata to your posts can greatly enhance your site's SEO and make your content more discoverable. Thankfully, Ghost provides a convenient way to include post metadata, which encompasses elements such as authors, publication date, and the caption for the featured image.

Let's break down each element:

Authors

<div>
    <p class="or-post-header-label or-text-light">{{plural authors.length empty="" singular="Author" plural="Authors"}}</p>
    <p class="or-post-header-value">{{authors}}</p>
</div>

The metadata element follows a basic structure: a label on top and the value beneath it. For authors, we leverage two handy Handlebars helpers: plural and authors.

The plural helper smartly adjusts the label text based on the number of items (or authors, in this case). When there's just one author, it reads "Author," but for multiple authors, it changes to "Authors."

The authors helper, on the other hand, generates a comma-separated list of authors, each linking to their respective profile pages. This is a great way to acknowledge authors and make it easy for readers to explore more of their work.

Publication date

<div>
    <p class="or-post-header-label or-text-light">Published</p>
    <p class="or-post-header-value">{{date}}</p>
</div>

Next up, we show the publication date with the {{date}} helper. While this helper may seem simple, there’s a lot of power under the hood. Not only can you format the date however you want, but Ghost will also default to outputting the date based on the language you enter in General settings.

The screenshot below shows how the date format changes based on the language set in Ghost Admin.

The art of the post template

Image credit

{{#match feature_image_caption}}
    <div>
        <p class="or-post-header-label or-text-light">Image credit</p>
        <p class="or-post-header-value">{{feature_image_caption}}</p>
    </div>
{{/match}}

Our last bit of metadata is the image credit or caption for the feature image. We use the match helper to check whether this value has been set. If so, we display it.

💡
If you use Ghost’s built-in Unsplash integration (a free library of high-quality images), the photographer’s name and link will be automatically added as the image caption. Not only does this save you from some manual work, but it also helps you give proper credit where it's due!

Feel free to experiment with these helpers and see how you can customize them to suit your site's style and requirements.

Picture perfect with a feature image

The feature image is the first visual your reader encounters, setting the tone for the rest of your post. Let's see how we handle this critical component in Ghost.

{{#match feature_image}}
    <div class="or-post-header-image">
        <picture class="">
            <source 
            srcset="
            {{img_url feature_image size="xxs" format="avif"}} 30w,
            {{img_url feature_image size="xs" format="avif"}} 100w,
            {{img_url feature_image size="s" format="avif"}} 300w,
            {{img_url feature_image size="m" format="avif"}} 600w,
            {{img_url feature_image size="l" format="avif"}} 1200w,
            {{img_url feature_image size="xl" format="avif"}} 2000w"
            sizes="(max-width: 350px) 300px, (max-width: 700px) 600px, (max-width: 800px) 1200px, (max-width: 1200px) 300px, 600px"
            type="image/avif"
            >
            <source 
            srcset="
            {{img_url feature_image size="xxs" format="webp"}} 30w,
            {{img_url feature_image size="xs" format="webp"}} 100w,
            {{img_url feature_image size="s" format="webp"}} 300w,
            {{img_url feature_image size="m" format="webp"}} 600w,
            {{img_url feature_image size="l" format="webp"}} 1200w,
            {{img_url feature_image size="xl" format="webp"}} 2000w"
            sizes="(max-width: 350px) 300px, (max-width: 700px) 600px, (max-width: 800px) 1200px, (max-width: 1200px) 300px, 600px"
            type="image/webp"
            >
            <img
            srcset="
            {{img_url feature_image size="xxs"}} 30w,
            {{img_url feature_image size="xs"}} 100w,
            {{img_url feature_image size="s"}} 300w,
            {{img_url feature_image size="m"}} 600w,
            {{img_url feature_image size="l"}} 1200w,
            {{img_url feature_image size="xl"}} 2000w"
            sizes="(max-width: 350px) 300px, (max-width: 700px) 600px, (max-width: 800px) 1200px, (max-width: 1200px) 300px, 600px"
            src="{{img_url feature_image size="xxs"}}"
            alt="{{#match feature_image_alt}}{{feature_image_alt}}{{else}}{{title}}{{/match}}"
            >
        </picture>
    </div>
{{/match}}

Once more, we make use of the match helper to check if a feature image is set. Without one, this entire block of code is simply skipped. But, if there's an image ready to shine, we employ Ghost's img_url helper.

What's brilliant about the img_url helper is that it automatically constructs optimized, responsive images. This ensures that no matter what device a user is on, they'll receive the appropriately sized image — be it for a smartwatch or a high-definition 4K monitor.

Images can significantly contribute to the load time of a webpage, but this optimization strategy ensures your Ghost site remains blazingly fast 🏎️

If the concept of responsive images sounds a bit daunting, don't worry — it's a complex topic! You can delve into how the picture tag works and the benefits it offers. Our documentation also provides valuable insights on implementing responsive images in Ghost and utilizing the img_url helper.

And if you're looking for a shortcut, Ghost's VS Code extension is your best friend. It can automatically generate this responsive image code for you ✨

Presenting your content

When it comes to your publication, the main content is the star of the show. But it's the side features that complete the experience, providing context, navigation, and engagement opportunities. So let's dive into how we structure the content and these additional components in Ghost.

The diagram below lays out the post content and sidebar, showing the code behind these elements.

The art of the post template

We start with the primary content:

<article class="or-post-content">
    {{content}}
</article>

To help lay out our content, we wrap it in an article tag. Next, the magic of the content helper comes into play. It brings in all the content written in the editor, including text, images, cards, and more.

But a great post isn't only about the main text. Let's turn our attention to the aside section that houses additional features: a table of contents placeholder, share buttons, and a read-next section.

<aside class="or-post-aside">
    <!-- Content for table of contents, share buttons, and read-next section -->
</aside>

This aside tag introduces a sidebar of handy features. Here you can integrate a table of contents for easy navigation, share buttons for spreading the word on social media, and a read-next section to keep your audience hooked with more content.

But you might be wondering how to get these features up and running on your template. Well, you're in luck! We have comprehensive tutorials to guide you:

How to add a table of contents to your Ghost site
Let your readers know what to expect in your posts and give them quick links to navigate content quickly by adding a table of contents with the Tocbot library.
The art of the post template
How to create a read-next section in your Ghost theme
In this tutorial, learn to build a read-next section for your Ghost theme so that your audience always knows what they should be reading next.
The art of the post template

There's also a full download of the post template file at the end of this post.

We don’t have a tutorial on adding share buttons to your template yet. Let us know if you’d like to see it!

How to enable comments

One of the keys to a lively website is engagement and nothing does that better than a robust comments section. This part of your site allows your readers to share their thoughts, engage with other readers, and even provide valuable feedback.

Now, let's take a look at how to incorporate this crucial component into your Ghost site:

The art of the post template
{{comments}}

The simplicity of the comments helper belies its impact. When comments are enabled, this helper outputs the comments user interface (UI) onto your site. What's more, you have the ability to customize certain aspects of the UI to better fit your site's look and feel.

For a deeper dive into the options available to you, check out our docs, which provide extensive guidance on how to customize the comments section.

As a final note, remember to close your post block with the {{/post}} helper. This marks the end of your post and ensures all your code stays neatly organized.

And that's it! You've got a fully-featured Ghost template ready for your posts. Here's the full template for reference and available for download.

Summary

Whew! That's a lot of ground we covered, from understanding the basic structure of the post template to diving into the post context, Handlebars helpers, and the nuances of setting tags and authors. We've looked at how to display post metadata, optimize feature images, and even tackled some advanced aspects, like custom excerpts and adding an aside section for share buttons and a read-next feature. And, of course, we've explored the important task of fostering engagement through a comments section.

The next step is yours. Take what you've learned here and put it into practice. Experiment with the different helpers and design elements to realize your vision. Ghost is a powerful and flexible platform that can help your content really sing.

And remember, you're not alone! If you have questions, need help, or simply want to share the dope Ghost theme you created, come join us on the official Ghost Forum. It's a lively and supportive community full of people who are passionate about Ghost and eager to help each other out. We look forward to seeing you there!

]]>
<![CDATA[🥯 Build with Ghost: A partial guide to everything]]>https://ghost.org/tutorials/partial-guide/6478bb121275730001011c94Tue, 18 Jul 2023 07:00:28 GMT

Welcome to issue #7! Seven is the most popular lucky number in the world, so this issue is packed with a whole lot of good fortune 🥠

Here's what else this issue includes:

  • Build beautiful themes with three new tutorials to help you
  • Grow engagement with new signup cards and embeddable forms
  • Gain insights from Erin Mikail Staples, a renowned developer advocate, tech educator, and comedian, as she shares the secrets behind her vibrant, stylish Ghost site
🏋️

Pro tip: Bring up the card menu in the editor by typing / on a new line. Start typing to filter card types and quickly find the one you want 🎴

Use partials to simplify your theme development

Partials are an essential tool for quick, maintainable theme development. These partial templates encompass bits of code that you can use throughout your theme. Typical use cases include cards, CTAs, headers, navbars, or any other elements you find yourself using repeatedly. (Those links all point to real-world examples in official Ghost themes.)

A complete guide to partials in Ghost
Learn partials in Ghost for better code maintenance and consistency. This tutorial will teach you what a partial is, how it’s used, and some advanced tips and tricks.
🥯 Build with Ghost: A partial guide to everything

Our new tutorial lays out everything you need to know about partials, from the very basics to advanced properties. In particular, we use a partial to create a card for a fictional music publication, Of Record, and walk through every line of code that makes it work.

🥯 Build with Ghost: A partial guide to everything

This tutorial complements two others we just released:

A comprehensive guide to Ghost’s index template
Learn to create and customize your Ghost theme’s index template in this comprehensive tutorial. Understand the index template functionality, the power of the post loop, and bonus theme customization techniques.
🥯 Build with Ghost: A partial guide to everything
A comprehensive guide to Ghost’s default template
Discover the secrets of Ghost’s default.hbs template. Learn how to optimize your site’s common elements and become an efficient theme-creation machine 🤖
🥯 Build with Ghost: A partial guide to everything

Just shipped 🚢

We've recently shipped two related, exciting features: signup cards and embeddable signup forms.

Signup cards, available to users on the beta editor, give you new ways to grow your audience. Add them to a post by selecting the Signup card from the card menu or by typing / on a new line. Customize the card to fit your publication.

🚨

Important note for theme developers. Signup cards require updates to a theme's CSS to display properly. In particular, cards that are full-width or have a split layout with a contained image add a kg-content-wide class that requires styling. Additionally, the container for post content may also need to be updated. See our docs for more info. All official themes have been updated, so they are also a great resource for understanding these changes.

Whereas signup cards are for use across your Ghost publication, embeddable signup forms can be used anywhere on the web. Customize the form and use the provided code to grow your audience on any platform.

Ideas and tools 🛠️

Erin Mikail is here for the rise of the personal blog (again)

🥯 Build with Ghost: A partial guide to everything

As the Sr. Developer Community Advocate at HumanSignal, Erin empowers the open-source community behind the Label Studio project. Working from NYC, Erin creates educational materials like tutorials, speaks at events, runs workshops, and maintains community channels to improve user experience.

While doing all of that, Erin also has a kick-ass Ghost site! It's rocking a slightly modified version of the Groovy theme, which showcases some clever uses of partials and an engaging index template.

Erin has been on Ghost for a while because, as an open-source platform, it provides flexibility and control over content and appearance. Also, the fact that Ghost is a nonprofit aligns with Erin's values. She says, "Ghost.org offers a genuine commitment to the public good rather than focusing on creating profits for shareholders. They reinvest their revenue into their platform, continually improving and upgrading. This has given me the confidence that they truly value their community, not a group of external investors" ❤️

🥯 Build with Ghost: A partial guide to everything
Meet Erin's coding partner, Q

If Erin could pass on one bit of advice when working with Ghost, it's not to be afraid to ask for help. Ghost's Forum and GitHub are open and responsive. They're full of people willing to help. Erin says she has found the answer she needed on the Forum too many times to count.

done > perfect

And, when possible, Erin says to remember that done is better than perfect. Rather than letting posts linger as drafts, "embrace the joy of constantly improving and being a work in progress." Amen!

👉 Follow Erin (and Q) on the web


Sites featured in the Build with Ghost newsletter are discovered through our creator network, Ghost Explore. It’s a way for creators and readers alike to discover their favorite new publications. Anyone running a Ghost site can add themselves to Explore to be featured throughout the wider Ghost ecosystem. If you’d like to be featured in this newsletter, add your site to Explore and reply to this email.

🥯 Build with Ghost: A partial guide to everything

Thanks for building with us.

Have an idea for a Ghost tutorial? Reply to this email and let us know ❤️

Looking for other creators and developers working with Ghost? Join the official Ghost Forum, where we talk about all things Ghost!

]]>
<![CDATA[A complete guide to partials]]>https://ghost.org/tutorials/partials/6499e6926ab27c000136adddTue, 27 Jun 2023 19:09:18 GMT A complete guide to partials

Imagine creating an eye-catching card for your homepage posts, only to realize you need the same card in your post’s read-more section. Copy, paste, and repeat, right? Not so fast! Any change to the card means updating it everywhere you used it—a repetitive and error-prone task.

Enter partials: the solution to your copy-paste woes.

Partials are a helper for reusing chunks of code across your Ghost theme. In this tutorial, we’ll spill the beans on everything you need to know about partials by looking at an example from the fictional publication Of Record. By the end of this tutorial, you’ll know:

  • What a partial is and how to use it
  • Advanced options with props
  • Tips and tricks for excelling with partials

Let’s go 👟

What’s a partial?

A partial is a Handlebars helper for reusing chunks of a template. Think of “partial” as being short for “partial template”—a partial can’t stand alone like a post or index template but is intended to be used as a component of those templates.

Ghost Handlebars Theme Helpers: partials
Create reusable pieces of markup with Handlebars partials. Read more about Ghost themes! 👻
A complete guide to partials

Many theme devs find partials helpful in two situations. First, they’re great for any repeating element like a card or CTA, especially when used in multiple templates. You get a single source of truth for the component that doesn’t need to be kept in sync!

Second, partials are useful for splitting out complex elements (like a header) into more manageable components. Instead of a template file with a 100 lines of code, using a partial can cut the file in half and make it easier to work with.

Common use cases for partials include (but aren’t limited to):

Whenever you ever find yourself copying and pasting a lot or seeing a file become long and messy, a partial is likely the perfect solution.

How to use a partial

We covered what a partial is and some common use cases. But how do we use it?

Partials are individual Handlebars files. The file's name is up to you. For a card partial, you can be creative and call it card.hbs. Crucially, however, all your partials need to be in a folder called partials that’s at the root of your theme.

Here is the folder structure for Casper with the partials folder at the top level.

.
├── LICENSE
├── README.md
├── assets
├── author.hbs
├── default.hbs
├── error-404.hbs
├── error.hbs
├── gulpfile.js
├── index.hbs
├── package.json
├── page.hbs
├── partials
├── post.hbs
└── tag.hbs

And, here are the contents of that partials folder:

partials
├── icons
│   ├── avatar.hbs
│   ├── facebook.hbs
│   ├── fire.hbs
│   ├── loader.hbs
│   ├── lock.hbs
│   ├── rss.hbs
│   ├── search.hbs
│   └── twitter.hbs
└── post-card.hbs

Once you’ve created your partial, it’s time to bring it into your template. Use Handlebars curly brackets with a right angle bracket and the partial name. Or, more simply, like this:

{{> "partial-name"}}

For example, referencing the partials folder from Casper above, here’s how to bring in the search icon:

{{> "icons/search"}}

Wherever you add this bit of code, Ghost will render the SVG search icon.

With the fundamentals under our belt, let’s walk through a partial from Of Record, a publication that focuses on vinyl records.

Create a post card with a partial

A complete guide to partials
A complete guide to partials
single card from of record theme

In the screenshots above, you can see a grid of cards from the publication’s homepage and an individual card in isolation. (See our tutorial on creating an index template for more info about the post loop.)

Here’s the entire code for the partial card:

<article class="or-post-card {{classes}}" style="--accent: {{primary_tag.accent_color}}">
    {{#if feature_image}}
    <a href="{{url}}">
        <picture class="or-post-card-image">
            <source 
                srcset="
                {{img_url feature_image size="xxs" format="avif"}} 30w,
                {{img_url feature_image size="xs" format="avif"}} 100w,
                {{img_url feature_image size="s" format="avif"}} 300w,
                {{img_url feature_image size="m" format="avif"}} 600w,
                {{img_url feature_image size="l" format="avif"}} 1200w,
                {{img_url feature_image size="xl" format="avif"}} 2000w"
                sizes="(min-width: 1200px) 1200px, 100vw" 
                type="image/avif"
            >
            <source 
                srcset="
                {{img_url feature_image size="xxs" format="webp"}} 30w,
                {{img_url feature_image size="xs" format="webp"}} 100w,
                {{img_url feature_image size="s" format="webp"}} 300w,
                {{img_url feature_image size="m" format="webp"}} 600w,
                {{img_url feature_image size="l" format="webp"}} 1200w,
                {{img_url feature_image size="xl" format="webp"}} 2000w"
                sizes="(min-width: 1200px) 1200px, 100vw" 
                type="image/webp"
            >
            <img
                srcset="
                {{img_url feature_image size="xxs"}} 30w,
                {{img_url feature_image size="xs"}} 100w,
                {{img_url feature_image size="s"}} 300w,
                {{img_url feature_image size="m"}} 600w,
                {{img_url feature_image size="l"}} 1200w,
                {{img_url feature_image size="xl"}} 2000w"
                sizes="(min-width: 1200px) 1200px, 100vw" 
                src="{{img_url feature_image size="l"}}"
                alt="{{#if feature_image_alt}}{{feature_image_alt}}{{else}}{{title}}{{/if}}"
            >
        </picture>
    </a>
    {{else}}
    <div class="or-post-card-image or-post-card-image-placeholder">
        <p>{{excerpt}}</p>
    </div>
    {{/if}}

    <div class="or-post-card-content">
        <h2><a href="{{url}}">{{title}}</a></h2>
        <footer class="or-post-card-footer or-text-light">
            <p class="or-text-light">by <strong>{{authors}}</strong></p>
            {{comment_count}}
        </footer>
    </div>
</article>

There’s a lot there, so let’s walk through it line by line.

Using partials with custom properties

<article class="or-post-card {{classes}}" style="--accent: {{primary_tag.accent_color}}">

The card partial opens with an HTML article tag. We include a CSS class to help with styling, but you may have noticed that some Handlebars syntax has snuck into our class name: {{classes}}.

classes refers to a custom property that’s defined on the partial. It’s a way for you to pass additional data to the partial wherever it’s invoked in your theme. In Of Record’s home template, we emphasize certain cards by adding the or-large-text class, which increases the size of the title.

A complete guide to partials

Here’s what that looks like in the home template:

{{! In home.hbs, for a section of posts we want to emphasize }}
{{#foreach posts}}
  {{> "card" classes="or-large-text"}}
{{/foreach}}

The classes property is then available to use within the partial file. When the property is included, it’s added to the class list. Otherwise, the class list only includes or-post-card.

{{> "card" class="or-large-text"}}

{{! outputs }}
<article class="or-post-card or-large-text">
...
</article>
 
{{> "card"}}

{{! outputs }}
<article class="or-post-card">
...
</article>

We also include a style attribute on the article element.

style="--accent: {{primary_tag.accent_color}}"

By defining the CSS custom property --accent via the style attribute, we can dynamically change the color of the title text on hover. {{primary_tag.accent_color}} is a value available on the tag object that provides a hex color defined in Ghost Admin. That’s the reason for the red color in the screenshot above.

Putting this all together, the partial is rendered as follows:

<article class="or-post-card" style="--accent: #349234">...</article>

Let’s now move on to the card image.

Constructing the card image

{{#if feature_image}}
<a href="{{url}}">
    <picture class="or-post-card-image">
        <source 
            srcset="
            {{img_url feature_image size="xxs" format="avif"}} 30w,
            {{img_url feature_image size="xs" format="avif"}} 100w,
            {{img_url feature_image size="s" format="avif"}} 300w,
            {{img_url feature_image size="m" format="avif"}} 600w,
            {{img_url feature_image size="l" format="avif"}} 1200w,
            {{img_url feature_image size="xl" format="avif"}} 2000w"
            sizes="(min-width: 1200px) 1200px, 100vw" 
            type="image/avif"
        >
        <source 
            srcset="
            {{img_url feature_image size="xxs" format="webp"}} 30w,
            {{img_url feature_image size="xs" format="webp"}} 100w,
            {{img_url feature_image size="s" format="webp"}} 300w,
            {{img_url feature_image size="m" format="webp"}} 600w,
            {{img_url feature_image size="l" format="webp"}} 1200w,
            {{img_url feature_image size="xl" format="webp"}} 2000w"
            sizes="(min-width: 1200px) 1200px, 100vw" 
            type="image/webp"
        >
        <img
            srcset="
            {{img_url feature_image size="xxs"}} 30w,
            {{img_url feature_image size="xs"}} 100w,
            {{img_url feature_image size="s"}} 300w,
            {{img_url feature_image size="m"}} 600w,
            {{img_url feature_image size="l"}} 1200w,
            {{img_url feature_image size="xl"}} 2000w"
            sizes="(min-width: 1200px) 1200px, 100vw" 
            src="{{img_url feature_image size="l"}}"
            alt="{{#if feature_image_alt}}{{feature_image_alt}}{{else}}{{title}}{{/if}}"
        >
    </picture>
</a>
{{else}}
<div class="or-post-card-image or-post-card-image-placeholder">
    <p>{{excerpt}}</p>
</div>
{{/if}}

This part of the card begins with a test: does the post in question have a feature image? In the code, we use the Handlebars if helper. This helper tests whether a value exists or is true. If so, then the image code is rendered. Otherwise, the card shows a post excerpt. This ensures that the card always looks great, no matter the situation 💅

In the screenshot below, the card on the left doesn’t have a feature image, so we display the excerpt instead. The other cards all have feature images.

A complete guide to partials

To display the image, we use the img_url helper. While there’s a lot going on with the image code, all that markup is worth the trouble because it's the best way to optimize your site, and, best of all, with our VS Code Extension, you can generate most of it automatically 🤖

<picture class="or-post-card-image">
    <source 
        srcset="
        {{img_url feature_image size="xxs" format="avif"}} 30w,
        {{img_url feature_image size="xs" format="avif"}} 100w,
        {{img_url feature_image size="s" format="avif"}} 300w,
        {{img_url feature_image size="m" format="avif"}} 600w,
        {{img_url feature_image size="l" format="avif"}} 1200w,
        {{img_url feature_image size="xl" format="avif"}} 2000w"
        sizes="(min-width: 1200px) 1200px, 100vw" 
        type="image/avif"
    >
    <source 
        srcset="
        {{img_url feature_image size="xxs" format="webp"}} 30w,
        {{img_url feature_image size="xs" format="webp"}} 100w,
        {{img_url feature_image size="s" format="webp"}} 300w,
        {{img_url feature_image size="m" format="webp"}} 600w,
        {{img_url feature_image size="l" format="webp"}} 1200w,
        {{img_url feature_image size="xl" format="webp"}} 2000w"
        sizes="(min-width: 1200px) 1200px, 100vw" 
        type="image/webp"
    >
    <img
        srcset="
        {{img_url feature_image size="xxs"}} 30w,
        {{img_url feature_image size="xs"}} 100w,
        {{img_url feature_image size="s"}} 300w,
        {{img_url feature_image size="m"}} 600w,
        {{img_url feature_image size="l"}} 1200w,
        {{img_url feature_image size="xl"}} 2000w"
        sizes="(min-width: 1200px) 1200px, 100vw" 
        src="{{img_url feature_image size="l"}}"
        alt="{{#if feature_image_alt}}{{feature_image_alt}}{{else}}{{title}}{{/if}}"
    >
</picture>

We use the standard HTML picture tag. Inside it, there are two source elements and an img element. We use each of these to bring in different sizes and formats of images. Image sizes are defined on a theme-by-theme basis in the package.json file.

The important item to note here is the values for the srcset attribute. The img_url helper is used to generate specific image sizes and formats. The first two formats are defined as AVIF and WEBP, which are high-efficiency image formats. However, some older browsers don’t support these formats, so the img element provides a fallback to whatever format the image was originally uploaded in. The sizes are defined to match your design with the goal of loading the right-sized image depending on the device’s screen. The sizes attribute is a complex media query that lets the browser know which image should be chosen from the set.

💡
Responsive images an entire onto itself. Check out this overview and guide to learn more.

You’re probably thinking, “Why does image loading gotta be so complex?” We hear ya! As mentioned, make things a lot easier for yourself by using the official Ghost VS Code extension to generate a lot of this code for you. And, remember: while optimizing images for the web is a complex process, the payoff is huge: a blazingly fast website.

The last bit of code to cover is the expression used for the alt tag, which provides a textual description of the image for improved accessibility. This code tests whether the author has set an alt tag. If so, that’s rendered. Otherwise, the tag falls back to the post title.

Adding the card text content

<div class="or-post-card-content">
    <h2><a href="{{url}}">{{title}}</a></h2>
    <footer class="or-post-card-footer or-text-light">
        <p class="or-text-light">by <strong>{{authors}}</strong></p>
        {{comment_count}}
    </footer>
</div>

Bringing in the card text content is comparatively simple.

We wrap the h2 tag in an anchor tag so that we can provide a link to the post. {{url}} renders the post’s URL and {{title}} the title.

Next, the post footer includes the post’s byline, with a link to the author. Ghost’s {{authors}} helper automatically renders a list of authors, each linked to their profile page. Finally, comment_count shows the number of comments a post has. If there aren’t any comments yet, nothing is rendered.

This is only a limited example of the data available to render. Some other exciting possibilities include reading time, member access, and featured status. Check out the docs to see what kind of trouble you can get up to 😉

Summary

Partials are now part of your theme development repertoire. You’ve learned what they are, how to use them, and how they benefit code maintainability and consistency. By looking at the use of the card partial in Of Record’s theme, you saw how it operates in the context of a real-world problem along with some tips and tricks for when you create your own.

Speaking of, we have lots more tutorials on nearly every aspect of creating a custom Ghost theme. If you come up against a nut you just can’t crack, hop on over to the official Forum, where an active community is eager to help you build the theme of your dreams and discuss all things Ghost.

]]>
<![CDATA[A comprehensive guide to the index template]]>https://ghost.org/tutorials/index/6490913fed7acb0001470b55Mon, 19 Jun 2023 20:16:40 GMT

It’s your site’s homepage. It brings together all the posts you’ve written into one place. It’s an essential part of all Ghost themes. It’s the index template, a VIP among your theme files.

In this tutorial, we’ll show you how to create your own index template by looking at an example from Of Record, a fictional publication focusing on vinyl records. By the end, you will:

  1. Understand what the index template is and how it functions
  2. Learn how to harness the power of the post loop effectively
  3. Discover bonus techniques to keep your theme on point

Let’s roll up our sleeves and dig in.

What’s the index template?

The primary job of the index template is to elegantly display your posts to your audience, guiding them to their next captivating read.

Technically speaking, the index template is a Handlebars file at the root of your theme with the filename index.hbs. With post.hbs and package.json, it’s one of three required files in a Ghost theme. It acts as the template for your homepage, author, tag, and subsequent pages like yoursite.com/page/2/.

💡
Ghost is supremely customizable, so you can supersede index.hbs by providing specialized templates like author.hbs and tag.hbs. Even with these specialized templates, the concepts discussed here still apply.

But enough with the abstract descriptions! Let’s look at the index template from Of Record’s theme.

A comprehensive guide to the index template

And here’s the code for the entire file. We’ll discuss each line of it below.

{{!< default}}

<main id="#main" class="or-container or-spacing-y">
    <div class="or-post-grid">
        {{!-- Loop through posts 1 to 5 --}}
        {{#foreach posts from="1" to="5"}}
          {{> "card"}}
        {{/foreach}}

        {{!-- If a visitor isn't a member, show a CTA to sign up --}}
        {{^if @member}}
            {{> "cta"}}
        {{/if}}
        
        {{!-- Loop through the rest of the posts--}}
        {{#foreach posts from="6" to="15"}}
          {{> "card"}}
        {{/foreach}}
    </div>

    {{!-- Show the pagination helper when there's more than one page --}}
    {{#match pagination.pages ">" 1}}
       {{pagination}}
    {{/match}}
</main>

What’s up with the default tag?

The top of the file begins with a seemingly strange mix of characters: {{!< default}}. This is one of Ghost’s Handlebars helpers. It tells Ghost to insert the contents of the current file into the default template, which simplifies theme development. You’ll generally find this helper at the top of root templates. We have an entire tutorial that explains how to use the default template.

A comprehensive guide to Ghost’s default template
Discover the secrets of Ghost’s default.hbs template. Learn how to optimize your site’s common elements and become an efficient theme-creation machine 🤖
A comprehensive guide to the index template

The finer points of spacing

Next up is a bit of standard HTML:

<main id="#main" class="or-container or-spacing-y">
    <div class="or-post-grid">

There’s nothing Ghost specific here. The theme uses the main tag to indicate that you’ve reached the main event on the page, generally the content of a page. Using this tag benefits your site’s accessibility and overall structure, but it’s totally optional in terms of Ghost.

On the main tag, we find two CSS classes that help with layout and spacing:

.or-container {
    width: min(100%, var(--max-width)); // --max-width = 80rem (~1280 px)
    padding: var(--gutter); // --gutter = max(2.5rem, 4vmax)
    margin-inline: auto;
}

.or-spacing-y {
    display: grid;
    gap: var(--spacing-large); // --spacing-large = 2rem
}

.or-spacing-y > *:first-child {
    margin-block-start: var(--spacing); // --spacing = 1rem
}

.or-container sets the width of the content. It ensures that the container has some padding, is centered, and is equal to 100% of the viewport and no larger than ~1280 px. .or-spacing-y creates vertical space between the elements.

It’s beyond the scope of the tutorial to discuss this CSS in detail, but the gist of it is to create a nice container for our content to live in.

Let’s see what goes inside.

A comprehensive guide to the index template

Make your inbox fire

Build a better internet with early access to features, tools, and tutorials.

No spam. Once a month. Unsubscribe any time.

The magic of the foreach loop

The purpose of index.hbs is to output a list of posts. How you choose to output that list of posts is entirely up to your imagination. You can use a collection of cards, a list of text, or some combination thereof.

Here are some examples from official Ghost themes.

Of Record outputs the post list with cards and uses CSS grid to achieve its layout.

A comprehensive guide to the index template
A comprehensive guide to the index template
CSS grid layout for index template

Here’s the CSS that controls the grid.

.or-post-grid {
    display: grid;
    grid-template-columns: repeat(6, 1fr); // Make 6 columns that take up the available width
    gap: var(--gap);
}

.or-post-card {
    grid-column: span 6; // On smaller viewports, cards take up the whole width
   
}

@media (--tablet) { // Above tablet viewports, cards span 2 or 3 cols 
    .or-post-card {
        grid-column: span 2;
    }
    
// Target card 1, 2, 5, 6
    .or-post-card:where(:nth-of-type(5n + 1), :nth-of-type(5n + 2)) {
        grid-column: span 3;
    }
}

And, as exciting as the options are for styling this list of posts, it’s important to understand what’s happening in the template to make this possible: the post loop!

The data available to the index template includes a collection of posts (via the posts array). The exact number of posts available per page is set in the theme's package.json file. Of Record sets this number to 15. This means the homepage will have 15 posts, and Ghost will automatically create additional pages, each with 15 posts, as necessary (at page/2, page/3) until the post list is exhausted.

To loop through these posts, use the foreach Handlebars helper. Its most basic usage looks like this:

{{#foreach posts}}
    {{!-- Do something with each post --}}
{{/foreach}}

The foreach helper renders the code between its open and closing tags for each post. If you’re not working with loops every day, this concept might seem a little obscure, so let’s look at a basic example.

Suppose we have a collection of three posts with the following titles:

  1. I’m post #1
  2. I’m post #2
  3. I’m post #3

In our template, then, we create the post loop:

{{#foreach posts}}
  <p>{{title}}</p>
{{/foreach}}

And Ghost renders it to HTML, which is sent to the browser:

<p>I'm post #1</p>
<p>I'm post #2</p>
<p>I'm post #3</p>

Inside the loop, you have access to all post data, including the title, feature image, excerpt, tags, and more. In Of Record’s template, a card partial is used to render this data. Partials or partial templates are bits of code that can be reused across your Ghost theme. Learn more about using partials.

In the loop from Of Record’s theme, the foreach includes additional attributes that enhance its functionality. (See all available attributes in the docs).

Specifically, instead of looping through all the posts, we only loop through the first five. Remember that there are a total of 15 posts on the page, so this only represents a third of the collection.

{{!-- Loop through posts 1 to 5 --}}
{{#foreach posts from="1" to="5"}}
    {{> "card"}}
{{/foreach}}

Why would we want to do this, though? It provides an opportunity to pause the post loop and introduce a call to action (CTA).

Dynamic CTA

A comprehensive guide to the index template

The code to introduce this CTA is included in the index.hbs template.

{{!-- If a visitor isn't a member, show a CTA to sign up --}}
{{^if @member}}
  {{> "cta"}}
{{/if}}

What’s clever is that the CTA only shows for visitors who aren’t logged in. This saves us from being tacky and asking already logged-in members to sign up again 🙃

It’s possible to check for a user’s logged-in status by using Ghost’s if helper in conjunction with the member object. Usually, you use the if helper like this:

{{#if value_to_check}}

Notice that if is preceded by “#.” This is the default way to use the helper, checking if a value is true or not. However, in the index.hbs file, we use {{^if value_to_check}}. That little caret (^) does a lot of work. Instead of saying, “if so and so is true,” it says the opposite, “if so and so is not true.”

It can take a minute to wrap your head around it, but the caret can be used with many Ghost helpers to check for the inverse state of things. Our CTA, {{^if @member}}, is checking whether the current visitor is not a member. If they aren’t, then we show them the CTA, via the cta partial. If they are a member, then we hide it and carry on with the regularly scheduled programming, the remainder of the posts.

{{!-- Loop through the rest of the posts--}}
{{#foreach posts from="6" to="15"}}
    {{> "card"}}
{{/foreach}}

The template then closes up the grid, which leaves us with one remaining element to discuss: pagination.

Pagination

As noted, Of Record is configured to include 15 posts per page. But these are ardent vinyl aficionados. They’re going to have a lot more than 15 posts. So, where do they all go?

Ghost automatically paginates your content, which means that since Of Record has 150 posts total, they’ll have 10 pages of posts. The final part of the index template renders the UI for visitors to get to those pages.

A comprehensive guide to the index template

Here’s the code in the template.

{{!-- Show the pagination helper when there's more than one page --}}
{{#match pagination.pages ">" 1}}
    {{pagination}}
{{/match}}

We first check whether there’s more than one page. No use in showing the pagination element if there’s only one page! This check is done by using the match helper. It’s like the if helper above, except that it’s able to check for more than just true and false values. In this case, we’re checking whether the number of pages is greater than one. The syntax of the match helper takes two values separated by an operator like <, >=, and <=.

If the expression evaluates to true, then the code between the match helper tags is rendered. For Of Record, their total number of pages is greater than 1, so the pagination helper is shown. It provides pagination metadata and links to previous and next pages.

And, speaking of pages, we have just about reached the end of the index.hbs template. The only thing that’s left is to close up the main tag and recap our progress.

Summary

In this tutorial, you've gained a comprehensive understanding of how the index.hbs template works in Ghost. We've explored how it functions to assemble and display your posts, and how to utilize the power of the post loop effectively. We also dipped our toes into some advanced techniques to customize your Ghost theme. You learned how to break up your post loop to insert a dynamic call to action (CTA), style your layout with CSS, and implement pagination to manage your content effectively.

With this newfound knowledge, you are well-equipped to start customizing your own Ghost site 💪 Consider experimenting with different layouts for your posts to find out what works for your publication. If you're in need of some inspiration, subscribe to the monthly Build with Ghost newsletter. In addition to providing tips and tricks for creating custom themes, we always feature a Ghost site of the month and some other gorgeous sites sure to get the creativity flowing.

]]>
<![CDATA[A comprehensive guide to the default template]]>https://ghost.org/tutorials/default/6488f607ed7acb00014709e8Thu, 15 Jun 2023 01:11:06 GMT A comprehensive guide to the default template

When visiting a website, many elements are shared across its different pages, like the navigation bar, footer, meta tags, scripts, and stylesheets. Including these elements individually on every page of your theme is time-consuming, error-prone, and, let’s face it, tedious 🫠 Save yourself time, effort, and errors by utilizing Ghost’s default template. It packs all these common elements of your site into one powerful, reusable base layer.

In this tutorial, you’ll learn everything you need to know about this exceedingly convenient template. The first order of business will be to understand what the default template is and how to use it. Then, the tutorial will cover common elements included in it, based on an example from Of Record, a publication specializing in vinyl records. Let’s dive in!

What’s the default template?

The default template is a special file in a Ghost theme. Using it is simple. Add a file to the theme folder called default.hbs. Doing so makes the Handlebars file the base layer for your theme, meaning that all other content gets inserted into it.

Think of the default template as a picture frame. Although you might change the content inside it, the frame stays the same. Likewise, default.hbs frames all your content, from the homepage to the post page to everything else.

0:00
/0:36

Ghost doesn’t require the default.hbs file for a theme to be valid, but almost all developers include it because it’s fantastically useful.

default.hbs is rendered on every page of your site. That means the template should include those elements that typically appear on every page. In the next section, we’ll look at an example of the default.hbs template and the elements included in it.

What to include in the default template

The default.hbs file below is taken from Of Record’s custom theme. As mentioned, they’re a fictional publication that focuses on vinyl records — listening to them, collecting them, and cursing that collection when they move into a tiny house.

Here’s a screenshot of the site's homepage:

A comprehensive guide to the default template

And here's the code for its default.hbs file:

<!DOCTYPE html>
<html lang="{{@site.locale}}">
    <head>

        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>{{meta_title}}</title>

        <link rel="stylesheet" href="{{asset "built/index.css"}}" />
        <script src="{{asset "built/index.js"}}" defer></script>

        {{ghost_head}}
        {{!-- Outputs important meta data and settings, should always be in <head> --}}

    </head>
    <body class="{{body_class}}">

        <div class="or-viewport">
            {{#is "post,page"}}
                {{> "navbar"}}  
            {{else}}
                {{> "header"}}
            {{/is}}

            {{{body}}}
            {{!-- All content gets inserted here, index.hbs, post.hbs, etc --}}

            <footer class="or-footer">
                <div class="or-flex or-container">
                    <p>{{@site.title}} &copy; {{date format="YYYY"}}</p>
                    {{navigation type="secondary"}}
                    <p>Published with <a href="<https://ghost.org>" target="_blank" rel="noopener">Ghost</a></p>
                </div>
            </footer>
        </div>

        {{ghost_foot}}
        {{!-- Outputs important scripts - should always be included before closing body tag --}}
    </body>
</html>

In the above default.hbs file, the overall structure can be simplified into this:

<!DOCTYPE html>
<html>
  <head></head>
  <body></body>
</html>

Remember that the whole point of the template is to capture elements that are mandatory on every page. From that perspective, the elements included here make sense because, on every page, we need these elements to have valid HTML.

Here's what each of these elements does. <!DOCTYPE html> informs the browser we’re using HTML or, for the longwinded, hypertext markup language.

Next, we open the HTML document with <html lang="{{@site.locale}}">. On this HTML tag, we include the lang attribute, which tells the browser your site’s language. But what’s that {{@site.locale}} doing in there? It’s a Ghost Handlebars helper that dynamically inserts the right language based on what’s entered in Ghost Admin.

Now, let's dissect the head and body and see the guts of this thing.

Inside the head

The head tag is used to include metadata about the page and load assets (styles and scripts) for it. Let’s go through each line of it and explain what’s happening.

<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

The first two lines are meta tags, vital for your site's look and feel. The first one, <meta charset="utf-8">, informs the browser of the character encoding used on your page. It ensures your text appears as intended. The second, <meta name="viewport" content="width=device-width, initial-scale=1">, is the cornerstone of responsive design. It controls page dimensions and scaling to ensure your site looks fantastic on any device.

<title>{{meta_title}}</title>

The title tag, powered by Ghost’s meta_title helper, furnishes the page’s title that shows up in browser tabs and search results.

<link rel="stylesheet" href="{{asset "built/index.css"}}" />
<script src="{{asset "built/index.js"}}" defer></script>

The link and script tags are the workhorses that bring your CSS and JS files to life. Ghost requires the use of the asset helper to load them. This ensures your assets are cached (and cache-busted) to boost your site's performance.

{{ghost_head}}

ghost_head, the final element in the head tag, is a special helper Ghost uses to load crucial metadata for SEO and additional scripts and styles.

Using default.hbs means that these elements need not be repeated with every template file, saving you time and a lot of copying and pasting 😰

Into the body

Let’s now hop on the Magic School Bus and get into the body. This is where all the content visible to the user appears.

On the body tag, we find another Ghost helper: <body class="{{body_class}}">. This helper outputs different class names based on the page and context. That means, for example, that when you're on the homepage, the body will have the home-template class. But when on a post page, it’ll have the post-template class. These classes are supremely helpful for targeting different contexts with conditional styles.

Next up is <div class="or-viewport">. This div wraps the page's content and helps with the layout. Note that its inclusion here is dependent on the current theme and totally optional, but let's spell out its purpose for the curious.

A comprehensive guide to the default template
Keep the page from looking like this 🙃

Have you ever visited a website that has a footer that shows up in the middle of the page, like someone who has their pants pulled up way too high? In this theme, <div class="or-viewport"></div> is used to prevent that through the following CSS:

.or-viewport {
    display: flex;
    flex-direction: column;
    justify-content: space-between; // Make the footer stick to the bottom
    min-height: 100vh; // Make the div at least as tall as the viewport
}
💡

Why is the class prefixed with "or-"? Great question! The prefix "or-" is short for "Of Record," the theme’s name. There are two reasons for the convention of prefixing classes like this. First, it ensures that the class doesn’t interfere with any Ghost or user classes. Second, it makes it easy to identify when a class is coming from the theme, rather than from some other source.

{{#is "post,page"}}
  {{> "navbar"}}  
{{else}}
  {{> "header"}}
{{/is}}
A comprehensive guide to the default template
Default navigation on post page
A comprehensive guide to the default template
Full-size hero image with navigation on tag page

We finally come to some content! This block of code introduces the site’s navigation bar. However, because the navigation bar text color needs to change when on a post or page, we use the is helper to conditionally render the output.

Ghost Handlebars Theme Helpers: is
The #is helper allows theme developers to check the context of the current route. Read more about custom Ghost themes! 👻
A comprehensive guide to the default template

{{#is "post,page"}} checks whether the current context is a post or not. If so, it renders the simple navbar with dark text. Otherwise, it renders the header partial.

A comprehensive guide to the default template

Make your inbox fire

Build a better internet with early access to features, tools, and tutorials.

No spam. Once a month. Unsubscribe any time.

Bringing in the body

A concept reiterated in this tutorial is that the default template is a base layer that gets included on every page. This means that the specific content for each of those pages — like an author page or post — needs somewhere to go. The {{{body}}} helper does exactly that: it tells Ghost where to render the template’s content. You can imagine copying the entire code of the post template and pasting it over the {{{body}}} helper, except Ghost does it for you. Everything in the post template will be rendered between the navbar and footer in the default template. This is also why you’ll see {{!< default}} at the top of most templates. It’s telling Ghost to put the template’s contents into the default file.

A comprehensive guide to the default template

The final bit of content for default.hbs is the footer:

<footer class="or-footer">
  <div class="or-flex or-container">
    <p>{{@site.title}} &copy; {{date format="YYYY"}}</p>
    {{navigation type="secondary"}}
    <p>Powered by <a href="<https://ghost.org>" target="_blank" rel="noopener">Ghost</a></p>
  </div>
</footer>

The markup for the footer begins with the footer tag followed by a div. The styling for these elements reduces the font size and text opacity. .or-container is an important class that helps define the max width of the element, provide padding, and center it. Again, its inclusion is dependent on the current theme, but its use illustrates a method of keeping sizing consistent across a theme. Here's the CSS for the class:

.or-container {
    width: min(100%, var(--max-width)); // max-width = 80rem
    padding: var(--gutter); // gutter = max(2.5rem, 4vmax);
    margin-inline: auto; // logical prop for margin-left: auto; margin-right: auto;
}

Inside the footer, there are three items:

  1. The copyright
  2. The secondary navigation
  3. The "Powered by Ghost" tagline

Let's walk through each one.

<p>{{@site.title}} &copy; {{date format="YYYY"}}</p>

The copyright uses a standard paragraph tag. The @site object is used to bring in the site’s title. &copy; is the HTML code for the copyright symbol (©). {{date format="YYYY"}} is Ghost’s date helper. Usually, you use it to output the date an article is published. However, when it’s used without a property (like published_at), then it defaults to the current date. It also accepts a wide variety of formatting options. Here, we opt for the four-digit year. The benefit of using the helper, as opposed to just saying “My Site © 2023” is that it’ll always be current — you won’t have to manually update it every year. One less thing to worry about 😅

Next, we use the navigation helper to output the secondary navigation items, as set in Ghost Admin. While these links can be whatever you want, we see users often opt to use the secondary navigation area for things like their privacy policy, terms and conditions, contact form, and similar pages. The actual markup Ghost uses to output the navigation is listed in the docs but can also be fully customized.

The final element is a “Powered by Ghost” link, set to open in a new tab. There’s nothing special here. It’s just straight HTML.

Then, a few closing tags bring us to the end of the default.hbs file. You made it 🥳

Summary

You now have a comprehensive overview of Ghost’s default template. This base layer is a key building block for any and all theme development. Since it provides the underlying structure for every page, it’s the perfect place for any element that shows up everywhere like meta tags, scripts, stylesheets, navigation bars, and footers. The real reason to use it, though, is its practicality: default.hbs saves you time, minimizes errors, and makes you an efficient theme-creation machine.

And now that you’ve completed this tutorial and have a better understanding of how Ghost themes work, you’re well on your way to becoming that machine. So don’t let the learning stop here 🤖

Explore other tutorials to learn more tips and tricks, sign up for the Build with Ghost newsletter for a monthly dose of inspiration, or connect with a vibrant community of Ghost enthusiasts over on the Forum.

]]>
<![CDATA[🧠 Build with Ghost: Do you know these essential concepts?]]>https://ghost.org/tutorials/3-things/645d0381f995f00001a90cdaTue, 06 Jun 2023 10:34:34 GMT

Welcome to Issue #6! Some highlights from this issue by the numbers:

  • Our new tutorial lays out 3 essential concepts to know when building a Ghost theme
  • Ghost is on its way to supporting 33 different languages
  • 25 examples of jaw-dropping typography
  • Get to know the systems powering our daily lives from the 1 and only Architecture Notes
🏋️

Pro tip: Hopefully, you're already using snippets, Ghost's feature that allows you to reuse content across posts and pages. But did you know you can also turn an entire post or email into a snippet? For example, if you send out a weekly newsletter that always follows the same format, you can create a snippet from the entirety of an existing email to jump-start a new issue. (Additionally, use our new duplicate post feature to achieve this functionality. A bonus here is that tags and authors are retained across copies.)

Essential concepts to know when building a Ghost theme

Our newest tutorial covers three essential concepts to know when building a Ghost theme. Here are the concepts:

  1. What a templating language is and the basics of Ghost's templating language, Handlebars
  2. The three required files — index.hbs, post.hbs, and package.json — that contribute to a theme's structure
  3. How contexts connect your site's data with the right template

These concepts will give you the foundational knowledge you need to build a killer custom theme 💪

Essential concepts to know when building a Ghost theme
In this tutorial, learn to wield the powerful Handlebars templating language, unravel the core structure of a theme, and understand the crucial role contexts play in theme development.
🧠 Build with Ghost: Do you know these essential concepts?

Just shipped 🚢

Ideas and tools 🛠️

On the beautiful site, Architecture Notes, Mahdi Yusuf publishes content about the systems we use every day. As a Senior Staff Engineer at 1Password, former CTO at Gyroscope, and technical researcher, Mahdi is no stranger to system design and software architecture. Recent posts discuss technical debt and database sharding, and there's even a capture-the-flag event that challenges participants to solve a series of encryption-related puzzles.

Architecture Notes — System Design & Software Architectures Explained
Engineering architecture notes about system design and software architectures explained by engineers for engineers.
🧠 Build with Ghost: Do you know these essential concepts?

If you were looking for somewhere to start with Mahdi's content, he recommends two posts in particular: Redis Explainedwhich offers an awesome introduction to the open-source key-value database server — and Relational Databases Explained, which includes this awesome infographic:

🧠 Build with Ghost: Do you know these essential concepts?

Of all the possible systems and platforms out there, we asked Mahdi why he uses Ghost. He says that he's followed Ghost since day one (10 years ago), and when version five dropped, it became his choice for a publication and newsletter service all in one. Also, he says, "The community is incredible and the built in subscription system is a no brainer as my platform of choice."

When working with Ghost, he advises keeping the setup simple, posting consistently, and leveraging snippets (see the tip above) for reusable elements. We agree with all of this and recommend heading over to Architecture Notes to finally learn what database sharding is — turns out it's more than just a funny word 😜


Many sites featured in the Build with Ghost newsletter are discovered through our creator network, Ghost Explore. It’s a way for creators and readers alike to discover their favorite new publications. Anyone running a Ghost site can add themselves to Explore to be featured throughout the wider Ghost ecosystem. If you’d like to be featured in this newsletter, add your site to Explore and reply to this email.

🧠 Build with Ghost: Do you know these essential concepts?

Thanks for building with us.

Have an idea for a Ghost tutorial? Reply to this email and let us know ❤️

Looking for other creators and developers working with Ghost? Join the official Ghost Forum, where we talk about all things Ghost!

]]>