mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-11 09:36:08 +00:00
feat: hosted-first landing + accurate fair source licensing copy
- Replace unsubstantiated hero claim with client sign-off messaging - Rename Open Source (Self-hosted) to Fair Source (Self-hosted) with FSL explanation (source visible, self-hostable, Apache 2.0 after two years) - Put Hosted Cloud first in pricing with Recommended badge and trial note - Move self-hosting hero link to GitHub, out of primary CTA path - Add FAQ entries for FSL licensing and 7-day free trial - Align license language across landing, README, terms, SEO, comparisons - Fix contact email to [email protected] everywhere (mailto links, notification sender fallbacks) and SEO fallback domain
This commit is contained in:
@@ -111,7 +111,7 @@ export async function sendVerificationEmail(email: string, token: string): Promi
|
||||
|
||||
const verifyUrl = `${baseUrl}/api/auth/verify-email?token=${encodeURIComponent(token)}`;
|
||||
const from =
|
||||
process.env.SMTP_FROM || process.env.EMAIL_FROM || 'OpenFrame <notifications@openframe.app>';
|
||||
process.env.SMTP_FROM || process.env.EMAIL_FROM || 'OpenFrame <info@open-frame.net>';
|
||||
|
||||
const html = brandedEmailTemplate(
|
||||
`
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ export async function sendInvitationEmail(input: {
|
||||
}
|
||||
|
||||
const fromAddress =
|
||||
process.env.SMTP_FROM || process.env.EMAIL_FROM || 'OpenFrame <notifications@openframe.app>';
|
||||
process.env.SMTP_FROM || process.env.EMAIL_FROM || 'OpenFrame <info@open-frame.net>';
|
||||
const subject = `[OpenFrame] You were invited to a ${scopeLabel(input.scope)}: ${input.targetName}`;
|
||||
const html = invitationEmailTemplate({
|
||||
inviterName: input.inviterName,
|
||||
|
||||
@@ -202,7 +202,7 @@ export const comparisonPages: ComparisonPageDefinition[] = [
|
||||
title: 'Frame.io Alternative for Small Teams',
|
||||
metaDescription:
|
||||
'Compare OpenFrame vs Frame.io for freelancers and small teams. Get timestamped review, approvals, guest links, and self-hosting without per-seat enterprise pricing.',
|
||||
keywords: ['frame.io alternative', 'frame io alternative', 'open source frame.io alternative'],
|
||||
keywords: ['frame.io alternative', 'frame io alternative', 'fair source frame.io alternative'],
|
||||
headline: 'Frame.io power without the enterprise bill',
|
||||
subheadline:
|
||||
'Frame.io is the industry standard for large post teams. OpenFrame gives freelancers and small studios the review workflow they actually need: one link, one timeline, clear approvals, and optional self-hosting.',
|
||||
@@ -249,7 +249,7 @@ export const comparisonPages: ComparisonPageDefinition[] = [
|
||||
keywords: [
|
||||
'self hosted frame.io alternative',
|
||||
'self-hosted video review',
|
||||
'open source video review',
|
||||
'fair source video review',
|
||||
],
|
||||
eyebrow: 'Self-hosted review',
|
||||
headline: 'Keep client footage on your infrastructure',
|
||||
@@ -270,7 +270,7 @@ export const comparisonPages: ComparisonPageDefinition[] = [
|
||||
bestForOpenFrame: [
|
||||
'Teams with Docker ops capacity',
|
||||
'Privacy-sensitive client work',
|
||||
'Studios comparing Frame.io to open/fair-source options',
|
||||
'Studios comparing Frame.io to fair-source options',
|
||||
],
|
||||
bestForCompetitor: [
|
||||
'Teams needing Adobe enterprise integrations out of the box',
|
||||
@@ -297,7 +297,7 @@ export const comparisonPages: ComparisonPageDefinition[] = [
|
||||
{ label: 'Version compare', openframe: 'yes', competitor: 'yes' },
|
||||
{ label: 'Enterprise DRM / SSO', openframe: 'no', competitor: 'yes' },
|
||||
{ label: 'Adobe NLE integrations', openframe: 'no', competitor: 'yes' },
|
||||
{ label: 'Open/fair-source codebase', openframe: 'yes', competitor: 'no' },
|
||||
{ label: 'Fair-source codebase', openframe: 'yes', competitor: 'no' },
|
||||
],
|
||||
pricingRows: [
|
||||
{ label: 'Self-hosted software cost', openframe: 'Free', competitor: 'Not available' },
|
||||
|
||||
@@ -565,7 +565,7 @@ export const openFrameProfile = {
|
||||
],
|
||||
bestFor: [
|
||||
'Freelancers and small teams shipping client cuts',
|
||||
'Studios that want open/fair-source and optional self-hosting',
|
||||
'Studios that want fair-source licensing and optional self-hosting',
|
||||
'Teams tired of vague email and WhatsApp feedback',
|
||||
],
|
||||
};
|
||||
|
||||
@@ -84,7 +84,7 @@ function createSmtpTransport() {
|
||||
async function sendEmail(to: string, subject: string, html: string): Promise<boolean> {
|
||||
const transporter = createSmtpTransport();
|
||||
const fromAddress =
|
||||
process.env.SMTP_FROM || process.env.EMAIL_FROM || 'OpenFrame <notifications@openframe.app>';
|
||||
process.env.SMTP_FROM || process.env.EMAIL_FROM || 'OpenFrame <info@open-frame.net>';
|
||||
|
||||
if (!transporter) {
|
||||
console.warn('SMTP not configured — skipping email notification');
|
||||
|
||||
+5
-4
@@ -1,4 +1,4 @@
|
||||
const FALLBACK_SITE_URL = 'https://openframe.net';
|
||||
const FALLBACK_SITE_URL = 'https://open-frame.net';
|
||||
|
||||
function normalizeSiteUrl(rawUrl: string | undefined): string {
|
||||
if (!rawUrl) {
|
||||
@@ -26,11 +26,12 @@ export function getSiteUrl(): string {
|
||||
|
||||
export const seoConfig = {
|
||||
name: 'OpenFrame',
|
||||
title: 'Open Source Video Review Platform',
|
||||
title: 'Fair Source Video Review Platform',
|
||||
description:
|
||||
'OpenFrame is an open source video review platform for collecting timestamped feedback with text and voice comments.',
|
||||
'OpenFrame is a fair source video review platform for collecting timestamped feedback with text and voice comments.',
|
||||
keywords: [
|
||||
'open source video review platform',
|
||||
'fair source video review platform',
|
||||
'video review platform',
|
||||
'video review tool',
|
||||
'timestamped video feedback',
|
||||
'video collaboration',
|
||||
|
||||
Reference in New Issue
Block a user