++ );
++}
diff --git a/opensaas-sh/app_diff/src/landing-page/contentSections.tsx.diff b/opensaas-sh/app_diff/src/landing-page/contentSections.tsx.diff
index 8be0d2796..5ab6f5502 100644
--- a/opensaas-sh/app_diff/src/landing-page/contentSections.tsx.diff
+++ b/opensaas-sh/app_diff/src/landing-page/contentSections.tsx.diff
@@ -11,7 +11,7 @@
import kivo from "../client/static/examples/kivo.webp";
import messync from "../client/static/examples/messync.webp";
import microinfluencerClub from "../client/static/examples/microinfluencers.webp";
-@@ -6,161 +11,253 @@
+@@ -6,161 +11,248 @@
import reviewradar from "../client/static/examples/reviewradar.webp";
import scribeist from "../client/static/examples/scribeist.webp";
import searchcraft from "../client/static/examples/searchcraft.webp";
@@ -21,11 +21,6 @@
+import { BlogUrl, DocsUrl, GithubUrl, WaspUrl } from "../shared/common";
+import { GridFeature } from "./components/FeaturesGrid";
-+export const landingPageNavigationItems: NavigationItem[] = [
-+ { name: "Features", to: "#features" },
-+ { name: "Documentation", to: DocsUrl },
-+ { name: "Blog", to: BlogUrl },
-+];
export const features: GridFeature[] = [
{
- name: "Cool Feature 1",
diff --git a/opensaas-sh/app_diff/src/landing-page/operations.ts.diff b/opensaas-sh/app_diff/src/landing-page/operations.ts.diff
new file mode 100644
index 000000000..3fec58ad3
--- /dev/null
+++ b/opensaas-sh/app_diff/src/landing-page/operations.ts.diff
@@ -0,0 +1,211 @@
+--- template/app/src/landing-page/operations.ts
++++ opensaas-sh/app/src/landing-page/operations.ts
+@@ -0,0 +1,208 @@
++import type { GetGithubRoadmap } from 'wasp/server/operations'
++import * as z from 'zod'
++
++const ORG_NAME = "wasp-lang"
++const PROJECT_NUMBER = 6
++
++const GithubIssueSchema = z.object({
++ title: z.string(),
++ url: z.string(),
++ number: z.number(),
++ issueType: z.object({
++ name: z.string()
++ }).nullish(),
++ subIssues: z.object({
++ totalCount: z.number(),
++ nodes: z.array(z.object({
++ state: z.string(),
++ number: z.number()
++ }))
++ }).nullish()
++})
++
++const ProjectV2ItemFieldValueSchema = z.object({
++ name: z.string().nullish(),
++ field: z.object({
++ name: z.string()
++ }).nullish()
++})
++
++const ProjectV2ItemSchema = z.object({
++ id: z.string(),
++ databaseId: z.number().nullish(),
++ fieldValues: z.object({
++ nodes: z.array(ProjectV2ItemFieldValueSchema)
++ }),
++ content: GithubIssueSchema
++})
++
++const GithubGraphQLResponseSchema = z.object({
++ data: z.object({
++ organization: z.object({
++ projectV2: z.object({
++ items: z.object({
++ nodes: z.array(ProjectV2ItemSchema)
++ }).nullish()
++ }).nullish()
++ }).nullish()
++ }).nullish(),
++ errors: z.array(z.any()).nullish()
++})
++
++export enum EpicStatus {
++ Ideas = "Ideas",
++ Planned = "Planned",
++ InProgress = "In progress",
++ Done = "Done"
++}
++
++export type EpicStats = {
++ name: string
++ total: number
++ done: number
++ status: EpicStatus
++ url: string
++}
++
++type RoadmapData = EpicStats[]
++
++let cachedData: RoadmapData | null = null
++let lastFetchTime = 0
++const CACHE_DURATION = 4 * 60 * 60 * 1000
++
++export const getGithubRoadmap: GetGithubRoadmap = async () => {
++ const currentTime = Date.now()
++
++ if (cachedData && currentTime - lastFetchTime < CACHE_DURATION) {
++ return cachedData
++ }
++
++ const token = process.env.GITHUB_ROADMAP_TOKEN
++ if (!token) {
++ console.warn("GITHUB_ROADMAP_TOKEN is not set")
++ return []
++ }
++
++ const query = `
++ query($org: String!, $number: Int!) {
++ organization(login: $org) {
++ projectV2(number: $number) {
++ items(first: 100) {
++ nodes {
++ id
++ databaseId
++ fieldValues(first: 50) {
++ nodes {
++ ... on ProjectV2ItemFieldSingleSelectValue {
++ name
++ field { ... on ProjectV2FieldCommon { name } }
++ }
++ }
++ }
++ content {
++ ... on Issue {
++ title
++ url
++ number
++ issueType { name }
++ subIssues(first: 100) {
++ totalCount
++ nodes {
++ state
++ number
++ }
++ }
++ }
++ }
++ }
++ }
++ }
++ }
++ }
++ `
++
++ try {
++ const response = await fetch("https://api.github.com/graphql", {
++ method: "POST",
++ headers: {
++ "Content-Type": "application/json",
++ Authorization: `Bearer ${token}`,
++ },
++ body: JSON.stringify({
++ query,
++ variables: { org: ORG_NAME, number: PROJECT_NUMBER },
++ }),
++ })
++
++ const json = await response.json()
++
++ const parseResult = GithubGraphQLResponseSchema.safeParse(json)
++ if (!parseResult.success) {
++ console.error("GitHub API response validation failed:", parseResult.error)
++ return cachedData || []
++ }
++
++ const validatedResponse = parseResult.data
++
++ if (validatedResponse.errors) {
++ console.error("GitHub API Errors:", validatedResponse.errors)
++ throw new Error("GitHub API returned errors")
++ }
++
++ const nodes = validatedResponse.data?.organization?.projectV2?.items?.nodes || []
++ const statusFieldName = "Status"
++
++ const BASE_PROJECT_URL = "https://github.com/orgs/wasp-lang/projects/6/views/1?pane=issue&itemId="
++
++ const epics: EpicStats[] = nodes
++ .filter((node) => {
++ const issue = node.content
++ return issue && issue.issueType?.name === "Epic"
++ })
++ .map((node) => {
++ const issue = node.content
++
++ const statusField = node.fieldValues.nodes.find(
++ (f) => f.field?.name === statusFieldName
++ )
++ const statusName = statusField?.name || "Ideas"
++
++ let status: EpicStatus = EpicStatus.Ideas
++ if (Object.values(EpicStatus).includes(statusName as EpicStatus)) {
++ status = statusName as EpicStatus
++ }
++
++ const subIssues = issue.subIssues?.nodes || []
++ const total = issue.subIssues?.totalCount ?? subIssues.length
++ const done = subIssues.filter((sub) => sub.state === "CLOSED").length
++
++ return {
++ name: issue.title,
++ total,
++ done,
++ status,
++ url: `${BASE_PROJECT_URL}${node.databaseId}`
++ }
++ })
++
++ const statusOrder = {
++ [EpicStatus.InProgress]: 0,
++ [EpicStatus.Planned]: 1,
++ [EpicStatus.Ideas]: 2,
++ [EpicStatus.Done]: 3
++ }
++
++ epics.sort((a, b) => {
++ const orderA = statusOrder[a.status] ?? 99
++ const orderB = statusOrder[b.status] ?? 99
++ return orderA - orderB
++ })
++
++ cachedData = epics
++ lastFetchTime = currentTime
++ return epics
++ } catch (error) {
++ console.error("Failed to fetch GitHub roadmap:", error)
++ return cachedData || []
++ }
++}
diff --git a/opensaas-sh/blog/public/banner-images/2025-11-21-open-saas-public-roadmap.webp b/opensaas-sh/blog/public/banner-images/2025-11-21-open-saas-public-roadmap.webp
new file mode 100644
index 000000000..66eaa2027
Binary files /dev/null and b/opensaas-sh/blog/public/banner-images/2025-11-21-open-saas-public-roadmap.webp differ
diff --git a/opensaas-sh/blog/src/assets/roadmap/open-saas-ai-ready.webp b/opensaas-sh/blog/src/assets/roadmap/open-saas-ai-ready.webp
new file mode 100644
index 000000000..26ab1dc1c
Binary files /dev/null and b/opensaas-sh/blog/src/assets/roadmap/open-saas-ai-ready.webp differ
diff --git a/opensaas-sh/blog/src/assets/roadmap/open-saas-epic-detail.webp b/opensaas-sh/blog/src/assets/roadmap/open-saas-epic-detail.webp
new file mode 100644
index 000000000..2674291dd
Binary files /dev/null and b/opensaas-sh/blog/src/assets/roadmap/open-saas-epic-detail.webp differ
diff --git a/opensaas-sh/blog/src/assets/roadmap/open-saas-epic.webp b/opensaas-sh/blog/src/assets/roadmap/open-saas-epic.webp
new file mode 100644
index 000000000..5beaf43b0
Binary files /dev/null and b/opensaas-sh/blog/src/assets/roadmap/open-saas-epic.webp differ
diff --git a/opensaas-sh/blog/src/assets/roadmap/open-saas-roadmap.webp b/opensaas-sh/blog/src/assets/roadmap/open-saas-roadmap.webp
new file mode 100644
index 000000000..a3ad26df9
Binary files /dev/null and b/opensaas-sh/blog/src/assets/roadmap/open-saas-roadmap.webp differ
diff --git a/opensaas-sh/blog/src/assets/roadmap/open-saas-used-by.webp b/opensaas-sh/blog/src/assets/roadmap/open-saas-used-by.webp
new file mode 100644
index 000000000..bd51df914
Binary files /dev/null and b/opensaas-sh/blog/src/assets/roadmap/open-saas-used-by.webp differ
diff --git a/opensaas-sh/blog/src/content/docs/blog/2025-11-21-open-saas-public-roadmap.mdx b/opensaas-sh/blog/src/content/docs/blog/2025-11-21-open-saas-public-roadmap.mdx
new file mode 100644
index 000000000..4916486c3
--- /dev/null
+++ b/opensaas-sh/blog/src/content/docs/blog/2025-11-21-open-saas-public-roadmap.mdx
@@ -0,0 +1,193 @@
+---
+title: "Open SaaS — Public Development Roadmap"
+date: 2025-11-21
+tags:
+ - roadmap
+ - open-saas
+ - wasp
+ - open-source
+authors: vince
+---
+import { Image } from 'astro:assets';
+import openSaasUsedBy from '../../../assets/roadmap/open-saas-used-by.webp';
+import openSaasRoadmap from '../../../assets/roadmap/open-saas-roadmap.webp';
+import epicExample from '../../../assets/roadmap/open-saas-epic.webp';
+import epicDetailExample from '../../../assets/roadmap/open-saas-epic-detail.webp';
+import aiReady from '../../../assets/roadmap/open-saas-ai-ready.webp';
+import Tweet from '../../../components/Tweet.astro';
+import { Aside } from '@astrojs/starlight/components';
+
+We created Open SaaS to help developers launch full-featured SaaS products faster. As an open-source project powered by [Wasp](https://wasp.sh), we thought it was important to have two things:
+1. A solid roadmap so that development is focused.
+2. A roadmap that's public, so that the community can see what's coming next and get involved.
+
+So we created just that. Behold, the [Open SaaS public roadmap](https://github.com/orgs/wasp-lang/projects/6)!
+
+
+
+
+
+---
+
+## Why a roadmap?
+
+Open SaaS is becoming a beast of its own. At 13k GitHub stars and growing, and with constant feature additions and improvements, we thought it was time to make future development more organized, transparent, and community-driven.
+
+
+
+
+
+
+
+With thousands of SaaS apps being deployed with Open SaaS, the needs of its users are also becoming more diverse. It would be impossible to address all of them, but we needed a way to track and prioritize the most important features and improvements.
+
+Up until now, it was just me basically deciding which issues to work on and when. This was pretty inefficent to begin with, and then with more contributors joining the project, it became even more so.
+
+The roadmap is thus a great way to make sense of all the different possible directions we can go in, help focus our efforts, and make development and contributions more meaningful.
+
+## How it works
+
+Open SaaS currently has about [100 open GitHub issues](https://github.com/wasp-lang/open-saas/issues), so it would be crazy to organize and track them all in the roadmap.
+
+
+
+
+
+
+
+So to make things overseeable, the roadmap is a GitHub project with a collection of "Epics". An Epic is just a GitHub issue with a bunch of sub-issues. Each Epic has a status and a progress bar to show you how many of its sub-issues are completed.
+
+
+
+
+
+
+
+No regular issues are allowed in it, only epics, of which we don't want too many. This way, its easy to understand the current themes and priorities of the project, as well as what's currently underway.
+
+---
+
+## Guiding themes
+
+When creating epics within the roadmap, there are a few categories we're focusing on at the moment. These guiding themes inform the epics we create, and help us make sure we're addressing the most important needs of our users.
+
+### 1. Real-world launch readiness
+
+Open SaaS should not just be a polished demo, or a flimsy template. It should be something you can deploy and scale. We want to make sure Open SaaS is a production-ready starter that can be used to build real-world SaaS products.
+This means having a solid architecture, a clean codebase, and a set of features that are robust and ready to be used in production.
+
+
+
+### 2. Modularity & flexibility
+
+Different [auth methods](https://docs.opensaas.sh/guides/authentication/), [billing providers](https://docs.opensaas.sh/guides/payment-integrations/), file uploads, AI integrations, analytics, and more. We want to make sure Open SaaS is a flexible and modular platform that can be tailored to the needs of (almost) any SaaS product.
+This means having the most essential features you need to launch your SaaS quickly, and being able to easily remove the things you don't.
+
+### 3. AI-first developer experience
+
+
+
+
+
+
+
+Whether you use Cursor, VSCode + Copilot, Claude, or others, Open SaaS should have top-notch code quality and be able to “explain itself” well to AI-driven coding tools, making it enjoyable to develop with in 2026 and beyond.
+
+We also want to provide demos and templates for AI-powered SaaS products, so you can get started building SaaS apps that leverage the newest technologies to create powerful and innovative products.
+
+
+
+### 4. Community-powered evolution
+
+We want Open SaaS to be shaped by real feedback, real PRs, and real use cases. Roadmap ideas are only valuable when they reflect what people actually need.
+So your [feedback and contributions](https://github.com/wasp-lang/open-saas/issues) are important to us!
+
+---
+
+## What's in the roadmap
+
+We just got finished with a major UI redesign, which we dubbed "Open SaaS v2.0". Take a look at the announcement below.
+
+
+With the new UI, based on [Shadcn UI](https://ui.shadcn.com/), finished and tucked away, we've turned back towards adding highly-requested features, and improving the codebase with smaller fixes.
+
+### 1. Payment Provider Expansion
+
+Today, Open SaaS supports Stripe, Polar, and Lemon Squeezy as payment providers. It's super [easy to get started](https://docs.opensaas.sh/guides/payment-integrations/) with one -- just plug and play.
+
+**Upcoming features:**
+
+* Polar.sh integration (merged in [#461](https://github.com/wasp-lang/open-saas/pull/461))
+* Paddle, and additional gateways (especially regional-friendly options)
+* Supporting up- or down-grading between different billing plans and models (proration)
+
+---
+
+### 2. AI-First Workflows & Templates
+
+Open SaaS already includes a simple OpenAI integration example, but we’re looking to expand and improve it.
+
+**Coming soon:**
+
+* Exploring using Vercel's AI SDK within our demo app (issue [#567](https://github.com/wasp-lang/open-saas/issues/567)).
+* Cursor / Claude prompt presets for smoother onboarding (issue [#579](https://github.com/wasp-lang/open-saas/issues/579))
+* Creating better docs and guides for AI-powered SaaS development
+
+---
+
+### 3. Core Development Improvements
+
+We want to keep Open SaaS relevant and up-to-date with the latest trends, as well as with the latest Wasp (the framework it's built on) features and improvements .
+
+**Efforts underway:**
+
+* Improving OpenSaaS.sh development workflows (issue [#552](https://github.com/wasp-lang/open-saas/issues/552))
+* Improving e2e tests (issue [#558](https://github.com/wasp-lang/open-saas/issues/558))
+
+---
+
+# How to Participate
+
+So that's just a quick overview of the current state of the roadmap. But we're not done yet!
+
+Open SaaS is community-driven — and we’d love your help.
+
+### ⭐ Star the repo
+
+This is super easy and helps a ton!
+
+[https://github.com/wasp-lang/open-saas](https://github.com/wasp-lang/open-saas)
+
+### 🧩 File issues or feature requests
+
+Especially around real-world SaaS requirements you’re running into.
+
+[https://github.com/wasp-lang/open-saas/issues](https://github.com/wasp-lang/open-saas/issues)
+
+### 🔧 Contribute code
+
+If you’re interested in payments, dashboarding, AI workflows, or dev-experience improvements — we’ll happily support and guide.
+
+[https://github.com/orgs/wasp-lang/projects/6](https://github.com/orgs/wasp-lang/projects/6)
+
+### 🚀 Build with it
+
+The best feedback always comes from people deploying real products.
+Drop us a line on [Discord](https://discord.com/invite/aCamt5wCpS) or [Twitter](https://x.com/wasplang) and let us know what you're building!
+
+---
+
+# Roadmap Updates
+
+We’ll keep updating this roadmap alongside major releases and aim for a quarterly revision cycle.
+
+You can follow progress in the GitHub Project board:
+
+👉 **[https://github.com/orgs/wasp-lang/projects/6](https://github.com/orgs/wasp-lang/projects/6)**
+
+See you there!