One thing that is annoying to my staff is that wherever we post anything the WYSWYG never seems to look as expected. Is there a way to apply the css of the website to the edit view. It would be nice if it gave a more realistic preview.
Questions
Card/ Component:
I’d like to create components to reuse exposed I’m the editor. I realize this can be done with a custom theme. If I want to say create a carousel using bootstrap. Is there a way to allow the user to add that element to a page with a custom element? Or how would one send data from the editor to a custom page to say iterate over and construct the weekends elements.
I know this can be done with pure html and a custom page but it makes the editor pointless as it’s doing what I’ve coded and can’t be updated without replacing the theme with an update.
RSS Feed injection.
I was wondering if I could create page that pulls posts from another ghost instance.
Example I’d like to subscribe to somehost.com/events/rss and have those rendered as posts/ on main website/posts.
I can understand the desire for the editor to be a 1:1 instance of the published post, but I also think there’s merit in having them display separately: the writing experience and the reading experience are not the same. In many cases, I like the simplified view of content in the editor that lets me focus on writing without the distraction of extra CSS markup.
If I do want a preview of what the post is going to look like, I use the keyboard shortcut to launch a preview (cmd/ctrl + p) and then esc to exit it.
I think the closest you can get right now for custom components is to use snippets.
For rendering posts from one Ghost site to another, I’d reach for the Content API. You can fetch the posts and render them to the page in JS. You’d need an API key from the site you’re fetching from, of course, to make it work.
The Content API JS seems really promising. I can execute the JS code in the tutorial, getting the titles and such. Is there a way to utilize the code in conjunction with the handlebar templates?
I’m omitting some of the content but GH link above has the entire file. The part I’m looking at below is what renders the cards teaser for the posts.
{{#foreach posts}}
{{!-- The tag below includes the markup for each post - partials/post-card.hbs --}}
{{> "post-card"}}
{{/foreach}}
Is there a way to leverage the JS code and create a ‘posts’ equivalent variable I can use handle bars to extend the behavior on?
Essentially, what I’m asking is where is posts coming from? Is that a JS variable? could I do something like:
<script>
var remote_posts = getRemotePosts()
</script>
{{#foreach remote_posts }}
{{!-- The tag below includes the markup for each post - partials/post-card.hbs --}}
{{> "post-card"}}
{{/foreach}}
I’m trying to understand the architecture and the internal of ghost a bit more so I can try to extend the behavior.
The {{#get}} helper is the content API equivalent in handlebars. Handlebars is a templating language that allows you to take a rendering context to convert a template into HTML. A “rendering context” is the data that Ghost provides to handlebars when generating the output, such as the site title, or the current post. The data available in a rendering context depends on the resource that’s being requested (a post, tag, index, etc.). In the case of a tag page, the rendering context will include a list of posts associated with the tag.
Coming to your example, remote_posts won’t be defined, because the script tag you’re using would be part of the handlebars output, and not executed. Handlebars will not execute arbitrary code from the template because that would remove the separation of concerns, and could lead to security issues.
If you need to render remote content, you can always use client-side javascript to fetch the data and render it into a specific location.
The {{#get}} helper fetches posts and renders them on the server, before the client receives the page. This allows you to use Handlebars to create templates.
When you use the Content API, you fetch the posts on the client, after the page has been received. Therefore, you have to implement your own template since Handlebars is only rendered on the server.
You could do something like this:
<!-- in your html -->
<div class="post-container"></div>
<script src="https://unpkg.com/@tryghost/content-api@1.7.3/umd/content-api.min.js"></script
<script src="index.js"></script>
// index.js
// Instantiate the Content API
const api = new GhostContentAPI({
url: 'https://demo.ghost.io',
key: '22444f78447824223cefc48062',
version: "canary"
});
// Get the container where you'll render the posts
const postContainer = document.querySelector('.post-container');
// Create a template render function
const postTemplate = postData => `
<article>
<header>
<img src="${postData.feature_image}">
</header>
<h2>${postData.title}</h2>
<p>${postData.primary_author.name}</p>
<footer>
<p>${postData.primary_tag.name}</p>
</footer>
</article>`
// Fetch the content with the Content API.
api.posts
.browse({limit: 5, include: 'tags,authors'})
.then((posts) => {
// Render your template with the post data
const formattedPosts = posts.map(post => postTemplate(post));
// Write your HTML to the page
postContainer.innerHTML = formattedPosts.join("");
})
.catch((err) => {
console.error(err);
});
Please note that this approach uses innerHTML, which can be unsafe if you can’t verify the origin of the HTML