Skip to content

Instantly share code, notes, and snippets.

@NeroxTGC
Last active May 11, 2026 15:42
Show Gist options
  • Select an option

  • Save NeroxTGC/27a588ad5d78cf09a0b4464321eb5921 to your computer and use it in GitHub Desktop.

Select an option

Save NeroxTGC/27a588ad5d78cf09a0b4464321eb5921 to your computer and use it in GitHub Desktop.
100% SEO Score with OpenSaaS Template

πŸš€ SEO Optimization Guide for OpenSaaS template

image

πŸ“š Table of Contents


πŸ“Š Initial Assessment

After cloning and running the repository locally, an initial audit using Chrome DevTools reveals a base SEO score of 75:

Initial SEO Score

Let's optimize this score to reach 100%! πŸ’ͺ

1. πŸ“ Adding Meta Description

❗ Issue

The meta description is not appearing in the DOM because the meta tags in main.wasp are commented out:

Missing Meta Description

✨ Solution

Uncomment the meta description section in your main.wasp file:

app OpenSaaS {
  // ... other configurations ...
  
  head: [
    "<meta property='og:type' content='website' />",
    "<meta property='og:title' content='My Open SaaS App' />",
    "<meta property='og:url' content='https://opensaas.sh' />",
    "<meta property='og:description' content='I made a SaaS App. Buy my stuff.' />",
  ],
}

Result βœ…: After uncommenting these meta tags, you should see an improved SEO score:

Improved SEO Score After Meta Tags

2. πŸ€– Adding robots.txt

❗ Issue

The application lacks a valid robots.txt file:

Missing robots.txt

✨ Solution

Create a robots.txt file in your public directory (alongside the favicon) with the following content:

User-agent: *
Allow: /
Disallow: /admin/
Disallow: /api/
Disallow: /auth/

Result βœ…: This addition further improves the SEO score:

Improved SEO Score After robots.txt

3. πŸ–ΌοΈ Adding Image Alt Attributes

❗ Issue

Some image elements lack alt attributes, particularly in the testimonials section (Da boi is one of them):

Missing Alt Attributes

✨ Solution

Update the image components in @src/landing-page/components/Testimonials.tsx to include descriptive alt attributes (line 25):

<img 
  src={testimonial.avatarSrc} 
  alt={`Profile picture of ${testimonial.name}`}
  className='h-12 w-12 rounded-full' 
/>

Final Result πŸŽ‰: After implementing all these improvements, you should achieve a perfect SEO score:

Perfect SEO Score

🎯 Conclusion

Following these 3 optimizations:

  • πŸ“ Implementing proper meta descriptions with react-helmet-async
  • πŸ€– Adding a valid robots.txt file
  • πŸ–ΌοΈ Including descriptive alt attributes for images

You've successfully improved your OpenSaaS template SEO score to 100, making it more discoverable and search engine friendly! πŸš€

@rachelslurs
Copy link
Copy Markdown

This is great! I was hoping you had an idea on ways to set the metadata to be different from page to page? Some SEO validators aren't too happy my page title and description tends to be the same on every page, and that I'm missing canonical URLs. Any ideas?

@NeroxTGC
Copy link
Copy Markdown
Author

Hey @rachelslurs, It's currently not possible as it's SPA. react-helmet-async is a good solution to handle SEO but not perfect:

  • The head of main.wasp is rendered only in the initial HTML, and then React only manipulates the DOM, but generally (with the exception of Google and some other) bots/crawlers (Linkedin, Facebook, Twitter, etc. ) usually only read the initial HTML, not the DOM modified by JS.

  • react-helmet-async only changes the head in the browser DOM, but not in the HTML that the bots/crawlers receive, unless you use SSR (Server Side Rendering), which Wasp doesn't support yet.

So, even if you change any meta with Helmet, the bots only see the one in the initial HTML (the one in main.wasp).


One solution (external to Wasp) is to use some pre-render service (prerender as an example) or any Open-Source.

They act as middleware/proxy between your app and the bots/crawlers.

When a bot (Google, Facebook, Twitter, etc.) requests a page from your SPA, Prerender launches a headless browser (like Puppeteer/Chrome), loads your app, waits for the JS to run and the DOM to update (including React Helmet changes), and then returns the rendered HTML to the bot.

For normal users, the app works as usual (SPA).

But as I said at the beginning, as of today it's not possible with Wasp.


For any further questions or a more in-depth discussion, feel free to join our Wasp community on Discord! We have a great community and offer support via tickets, which usually provides a much faster response than what I've given you here. 😁

You can join us at: https://discord.gg/rzdnErX

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment