feat(frontend): /pricing route placeholder + UserResponse subscription fields
Two upstream additions to support private overlays implementing paid tiers without forking client code: - store/useAuthStore.ts: UserResponse extended with optional is_paid_subscriber, subscription_status, subscription_period_end. The backend now returns these in /api/auth/me; the persist middleware serialises them automatically. - pages/PricingPlaceholder.tsx (NEW): the /pricing route. Renders a polite "this image is fully free" message for self-hosters plus a data-velxio-slot="pricing-page" target where private overlays can portal-inject a real pricing page. - App.tsx: register the /pricing route after /about. Self-hosted OSS image: /pricing shows the placeholder, no behavioural change anywhere else. Production with a private overlay: /pricing shows the overlay's full pricing UI. Frontend build verified.
This commit is contained in:
parent
5f0e7523ed
commit
77b3e86b50
|
|
@ -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() {
|
|||
<Route path="/v2" element={<Velxio2Page />} />
|
||||
<Route path="/v2-5" element={<Velxio25Page />} />
|
||||
<Route path="/about" element={<AboutPage />} />
|
||||
{/* Pricing — placeholder by default; private overlays portal-inject the real page */}
|
||||
<Route path="/pricing" element={<PricingPlaceholder />} />
|
||||
{/* Canonical project URL by ID */}
|
||||
<Route path="/project/:id" element={<ProjectByIdPage />} />
|
||||
{/* Legacy slug route — redirects to /project/:id */}
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<div style={{ minHeight: '100vh', background: '#1e1e1e', color: '#e8e8e8' }}>
|
||||
<AppHeader />
|
||||
<div data-velxio-slot="pricing-page">
|
||||
{/* Default content — only visible if no overlay is mounted (i.e.
|
||||
self-hosted OSS image without a private pricing overlay). */}
|
||||
<main
|
||||
style={{
|
||||
maxWidth: 720,
|
||||
margin: '60px auto',
|
||||
padding: '0 24px',
|
||||
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
||||
lineHeight: 1.6,
|
||||
}}
|
||||
>
|
||||
<h1 style={{ marginTop: 0 }}>Pricing</h1>
|
||||
<p>
|
||||
This Velxio instance is self-hosted from the open-source image —
|
||||
all features are free for everyone using it.
|
||||
</p>
|
||||
<p>
|
||||
The hosted version at{' '}
|
||||
<a
|
||||
href="https://velxio.dev"
|
||||
style={{ color: '#4fc3f7', textDecoration: 'none' }}
|
||||
>
|
||||
velxio.dev
|
||||
</a>{' '}
|
||||
offers an optional Pro tier that helps fund development.
|
||||
</p>
|
||||
<p style={{ color: '#888', fontSize: 13, marginTop: 32 }}>
|
||||
Source code is{' '}
|
||||
<a
|
||||
href="https://github.com/davidmonterocrespo24/velxio"
|
||||
style={{ color: '#888' }}
|
||||
>
|
||||
MIT-licensed on GitHub
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PricingPlaceholder;
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue