0

I'm using Firebase & Vue to create a dynamic site. One section of the site will contain hundreds of article pages in the form:

<article>
<!-- order of these elements will not change -->
<h1>Article title</h1>
<div id="date">1/1/2021</div>
<div id="author">Author</div>
<div id="tags">Tag1, Tag2, Tag3</div>

<div id="content">

    <!-- order of elements varies based on needs of article. sample elements below -->
    <h2 class="subtitle>Subtitle 1</h2>
    <p class="text"><span class="smallcaps">Lorem ipsum dolor</span> sit amet, consectetur adipiscing elit, <a href="https://example.com/">link</a>.</p>
    <blockquote>"An embedded tweet"</blockquote><script async src="https://platform.twitter.com/widgets.js"></script>
    <h2 class="subtitle>Subtitle 2</h2>
    <p class="text">Excepteur sint occaecat cupidatat non:</p>
    <figure><img src="img.jpg"/><figcaption>Caption</figcaption></figure>
    <h2 class="subtitle>Subtitle 3</h2>
    etc...

</div>

</article>
<!-- comments feature below -->

In terms of storing the article content, I've come across three options, none of which seem ideal:

  1. Store the HTML tags and content within <div id="content"> inside a field in each article's Firebase document, then use innerHTML to inject the contents of that field into <div id="content">. Use one Article.vue file to pipe in and display each article document from the Firebase collection. While this is easy and solves my problem, I'm afraid of XSS attacks, especially since I'll sometimes be using <script> to embed content from social media sites like Twitter and YouTube.

  2. Create a field in Firebase for each HTML element that I expect within the article (e.g., subtitle1, paragraph1, blockquote1, subtitle2, paragraph2, etc.). Use one Article.vue file to pipe in and display an article's elements. I already planned to do this with the standardized elements, like title, date, and author, but doing so for elements within <div id="content"> would remove variability in the structure of the articles. Even dealing with external links (i.e., <a href="https://example.com/">) within paragraphs would be painful, if not impossible.

  3. Make a separate .vue file for each article. This allows for full customization of each article, but doesn't scale well with hundreds or thousands of articles.

Is there a better option, or am I stuck with one of these three? I'd prefer not to install CMS software like WordPress in order to keep a consistent feel to my site.

Taco
  • 11
  • 3

1 Answers1

1

I think answers to this question will largely be opinion based. With that said, just based off of some research and personal experience professionally, I can give some general advice!

Opinions

  1. First, I would say option 2 isn't deal in any scenario, unless the articles are going to be exactly the same across the board. You already touched on this, but from a user-interface stand point, every article created on the site would have to be structured the exact same way, and any users creating their own articles (or blog posts) would lose that freedom to create their own thing.
  2. Secondly, I can't actually think of a way that option 3 would work. How would you render a completely separate vue component for each article? How would you determine which article gets what view? If every article got their own entire vue component, you'd have thousands (hundreds of thousands, etc. for a bigger app) of components inside of your project, and I can't imagine the load that would put on the server you host it on. I doubt most servers could even handle that.

Questions

  1. Instead of having an article be one big HTML block, have you thought of Markdown? There's a decent SO question about how viable Markdown is in your database. Have you ever used a Github wiki before? All of those pages are also in markdown, and I absolutely love Github's Wiki features! Here's an example Github Wiki. There's definitely a ton of JavaScript libraries out there for rendering markdown once it gets back from the server, and it's about the same process as sending HTML to your server: just make sure things are escaped properly. Here's some examples: MarkedJS, ShowdownJS

  2. Within the realm of Firebase, have you looked into Flamelink? It looks like it could be a pretty good option for attempting to do a CMS engine inside of Firebase / Firestore.

Summary

This is definitely my opinion, and I am in no way an expert or master in my craft.

If it were me, I probably wouldn't be building a CMS engine inside of Firebase / Firestore, only because Firebase was built for fast, ever-changing data, ideally for mobile apps, small web applications, and microservices. The Firebase Wiki has some great history and info on this. Using it as a CMS is probably absolutely possible, but you'd be pushing it to it's limits, and probably getting a huge bill based off of database usage in a production app, compared to a separate API being hosted on Heroku or something similar.

I've been developing professionally for about 4 years now, and in my experience, CMS-level architecture is difficult in any platform, even powerful frameworks like Rails, .NET, and Django.

With all of that being said, I would probably go for your first option, if nothing else is considered in this answer. It will allow the user the most freedom, is the most maintainable (you only have to have one article_content component or div, and handle all styling there), and as long as your database can handle it, and you escape your HTML properly (most frameworks do this automatically), you should be good to go.

Otter
  • 240
  • 2
  • 11
  • Otter, this is super helpful. I was unfamiliar with the Markdown and Flamelink options you mentioned. Time to research! Thank you. – Taco May 07 '21 at 13:35