diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 384c3e73..c10c3e5c 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -28,6 +28,7 @@ import { RaspberryPiSimulatorPage } from './pages/RaspberryPiSimulatorPage';
import { Velxio2Page } from './pages/Velxio2Page';
import { Velxio25Page } from './pages/Velxio25Page';
import { AboutPage } from './pages/AboutPage';
+import { PricingPlaceholder } from './pages/PricingPlaceholder';
import { useAuthStore } from './store/useAuthStore';
import './App.css';
@@ -68,6 +69,8 @@ function App() {
} />
} />
} />
+ {/* Pricing — placeholder by default; private overlays portal-inject the real page */}
+ } />
{/* Canonical project URL by ID */}
} />
{/* Legacy slug route — redirects to /project/:id */}
diff --git a/frontend/src/pages/PricingPlaceholder.tsx b/frontend/src/pages/PricingPlaceholder.tsx
new file mode 100644
index 00000000..a5e33556
--- /dev/null
+++ b/frontend/src/pages/PricingPlaceholder.tsx
@@ -0,0 +1,69 @@
+/**
+ * PricingPlaceholder — the route at /pricing.
+ *
+ * In the open-source build this renders a minimal heading + slot div. It
+ * exists so that:
+ * 1. Private overlays can portal-inject a real PricingPage into the slot
+ * (data-velxio-slot="pricing-page") without forking this file.
+ * 2. Self-hosters who navigate to /pricing get a polite "this image
+ * doesn't sell anything" page rather than a 404.
+ *
+ * The route is registered in App.tsx. The slot pattern is the same as
+ * data-velxio-slot="user-menu" / "admin-tabs" / "admin-tab-content".
+ */
+
+import { useEffect } from 'react';
+import { AppHeader } from '../components/layout/AppHeader';
+
+export const PricingPlaceholder = () => {
+ useEffect(() => {
+ document.title = 'Pricing — Velxio';
+ }, []);
+
+ return (
+
+
+
+ {/* Default content — only visible if no overlay is mounted (i.e.
+ self-hosted OSS image without a private pricing overlay). */}
+
+ Pricing
+
+ This Velxio instance is self-hosted from the open-source image —
+ all features are free for everyone using it.
+
+
+ The hosted version at{' '}
+
+ velxio.dev
+ {' '}
+ offers an optional Pro tier that helps fund development.
+
+
+ Source code is{' '}
+
+ MIT-licensed on GitHub
+
+ .
+
+
+
+
+ );
+};
+
+export default PricingPlaceholder;
diff --git a/frontend/src/store/useAuthStore.ts b/frontend/src/store/useAuthStore.ts
index a346e23f..ee3e30b6 100644
--- a/frontend/src/store/useAuthStore.ts
+++ b/frontend/src/store/useAuthStore.ts
@@ -9,6 +9,12 @@ export interface UserResponse {
avatar_url: string | null;
is_admin: boolean;
created_at: string;
+ // Subscription state — populated by deployments that wire an external
+ // billing system (e.g. velxio.dev). Self-hosted OSS images leave these
+ // at the safe defaults (no paid features unlock).
+ is_paid_subscriber?: boolean;
+ subscription_status?: string | null;
+ subscription_period_end?: string | null;
}
interface AuthState {