mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-11 17:46:06 +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:
@@ -208,6 +208,10 @@ bun run check
|
|||||||
|
|
||||||
Feature flags and self-hosting environment variables are documented in `.env.example` and `.env.docker.example`.
|
Feature flags and self-hosting environment variables are documented in `.env.example` and `.env.docker.example`.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
OpenFrame is Fair Source, licensed under the [Functional Source License](https://fsl.software/) (FSL-1.1-ALv2). The full source code is publicly available, you can self-host it, and every release automatically becomes Apache 2.0 open source two years after its publication. See [LICENCE](LICENCE) for the full terms.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Contributions are welcome.
|
Contributions are welcome.
|
||||||
@@ -215,3 +219,4 @@ Contributions are welcome.
|
|||||||
- Read [CONTRIBUTING.md](CONTRIBUTING.md) for workflow, conventions, and PR requirements.
|
- Read [CONTRIBUTING.md](CONTRIBUTING.md) for workflow, conventions, and PR requirements.
|
||||||
- Use [SECURITY.md](SECURITY.md) for responsible vulnerability reporting.
|
- Use [SECURITY.md](SECURITY.md) for responsible vulnerability reporting.
|
||||||
- Follow [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) in all project interactions.
|
- Follow [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) in all project interactions.
|
||||||
|
- Contact: [[email protected]](mailto:[email protected])
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const fromAddress =
|
const fromAddress =
|
||||||
process.env.SMTP_FROM ||
|
process.env.SMTP_FROM ||
|
||||||
process.env.EMAIL_FROM ||
|
process.env.EMAIL_FROM ||
|
||||||
'OpenFrame <notifications@openframe.app>';
|
'OpenFrame <info@open-frame.net>';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await transporter.sendMail({
|
await transporter.sendMail({
|
||||||
|
|||||||
+7
-3
@@ -150,7 +150,8 @@ export default function TermsOfServicePage() {
|
|||||||
<li>Interfere with or disrupt the integrity or performance of the Service.</li>
|
<li>Interfere with or disrupt the integrity or performance of the Service.</li>
|
||||||
<li>
|
<li>
|
||||||
Reverse engineer, decompile, or attempt to extract the source code of the Service
|
Reverse engineer, decompile, or attempt to extract the source code of the Service
|
||||||
(except where permitted by applicable open-source licenses).
|
(except where permitted by the applicable source license, such as the Functional
|
||||||
|
Source License covering the platform code).
|
||||||
</li>
|
</li>
|
||||||
<li>Use the Service to send spam or unsolicited communications.</li>
|
<li>Use the Service to send spam or unsolicited communications.</li>
|
||||||
<li>
|
<li>
|
||||||
@@ -174,8 +175,11 @@ export default function TermsOfServicePage() {
|
|||||||
intellectual property laws.
|
intellectual property laws.
|
||||||
</p>
|
</p>
|
||||||
<p className="mt-3">
|
<p className="mt-3">
|
||||||
The core platform code is made available as open-source software; please refer to the
|
The core platform code is made available under the Functional Source License
|
||||||
applicable license in the GitHub repository for details on permitted use.
|
(FSL-1.1-ALv2): the source code is publicly available and may be self-hosted, and
|
||||||
|
each release becomes available under the Apache 2.0 license two years after its
|
||||||
|
publication. Please refer to the license in the GitHub repository for details on
|
||||||
|
permitted use.
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
+92
-60
@@ -234,14 +234,14 @@ export function LandingPage({ isLoggedIn }: LandingPageProps) {
|
|||||||
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-primary opacity-75"></span>
|
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-primary opacity-75"></span>
|
||||||
<span className="relative inline-flex h-2 w-2 rounded-full bg-primary"></span>
|
<span className="relative inline-flex h-2 w-2 rounded-full bg-primary"></span>
|
||||||
</span>
|
</span>
|
||||||
<span className="font-mono tracking-wide uppercase">Open Source Video Review</span>
|
<span className="font-mono tracking-wide uppercase">Fair Source Video Review</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1
|
<h1
|
||||||
data-hero-copy
|
data-hero-copy
|
||||||
className="text-4xl font-semibold leading-[0.95] tracking-[-0.03em] sm:text-5xl md:text-6xl lg:text-7xl"
|
className="text-4xl font-semibold leading-[0.95] tracking-[-0.03em] sm:text-5xl md:text-6xl lg:text-7xl"
|
||||||
>
|
>
|
||||||
Cut Video Approval Time in Half. <br className="hidden md:block" />
|
Get Client Sign-off From One Link. <br className="hidden md:block" />
|
||||||
<span className="text-muted-foreground">Stop Chasing Timecodes.</span>
|
<span className="text-muted-foreground">Stop Chasing Timecodes.</span>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
@@ -249,27 +249,35 @@ export function LandingPage({ isLoggedIn }: LandingPageProps) {
|
|||||||
data-hero-copy
|
data-hero-copy
|
||||||
className="mx-auto max-w-2xl text-base text-muted-foreground md:text-xl"
|
className="mx-auto max-w-2xl text-base text-muted-foreground md:text-xl"
|
||||||
>
|
>
|
||||||
OpenFrame puts comments, voice notes, and annotations on a single timeline so clients
|
Hosted video review for editors, agencies, and small studios. Comments, voice notes,
|
||||||
say "yes" faster and your team stops guessing.
|
and annotations land on one timeline — clients review in the browser, no account
|
||||||
|
needed.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
data-hero-copy
|
data-hero-copy
|
||||||
className="mx-auto flex max-w-md flex-col items-center justify-center gap-2"
|
className="mx-auto flex max-w-md flex-col items-center justify-center gap-3"
|
||||||
>
|
>
|
||||||
<Link
|
<Link
|
||||||
href={hostedCtaHref}
|
href={hostedCtaHref}
|
||||||
className="group relative isolate inline-flex h-12 min-w-max items-center justify-center overflow-hidden border border-primary bg-primary px-10 text-sm font-medium whitespace-nowrap text-primary-foreground transition-transform duration-300 hover:scale-[1.02]"
|
className="group relative isolate inline-flex h-12 min-w-max items-center justify-center overflow-hidden border border-primary bg-primary px-10 text-sm font-medium whitespace-nowrap text-primary-foreground transition-transform duration-300 hover:scale-[1.02]"
|
||||||
>
|
>
|
||||||
Start free
|
Start free trial
|
||||||
<MoveRight className="ml-2 h-4 w-4 transition-transform group-hover:translate-x-1" />
|
<MoveRight className="ml-2 h-4 w-4 transition-transform group-hover:translate-x-1" />
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
|
7-day free trial · Flat $10/mo — no per-seat fees · No client accounts
|
||||||
|
</p>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
href="#pricing"
|
href="https://github.com/yusufipk/OpenFrame"
|
||||||
className="text-sm font-medium text-muted-foreground transition-colors hover:text-foreground"
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="text-xs font-medium text-muted-foreground/70 transition-colors hover:text-foreground"
|
||||||
>
|
>
|
||||||
Prefer self-hosting? <ArrowRight className="ml-1 inline h-3.5 w-3.5" />
|
Prefer self-hosting? View on GitHub{' '}
|
||||||
|
<ArrowRight className="ml-1 inline h-3 w-3" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -644,70 +652,33 @@ export function LandingPage({ isLoggedIn }: LandingPageProps) {
|
|||||||
className="text-3xl font-semibold md:text-5xl text-foreground"
|
className="text-3xl font-semibold md:text-5xl text-foreground"
|
||||||
style={{ fontFamily: 'monospace', letterSpacing: '-0.02em' }}
|
style={{ fontFamily: 'monospace', letterSpacing: '-0.02em' }}
|
||||||
>
|
>
|
||||||
Deploy it yourself - or let us run it for you.
|
Let us run it for you - or deploy it yourself.
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid gap-6 md:grid-cols-3">
|
<div className="grid gap-6 md:grid-cols-3">
|
||||||
{/* Card 1: Open Source */}
|
{/* Card 1: Hosted Cloud (recommended) */}
|
||||||
<div
|
|
||||||
data-reveal
|
|
||||||
className="relative flex flex-col border border-border/40 bg-[#141414] p-8"
|
|
||||||
>
|
|
||||||
<div className="mb-6">
|
|
||||||
<h3 className="text-xl font-semibold text-foreground">
|
|
||||||
Open Source (Self-hosted)
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-8 flex items-baseline gap-2">
|
|
||||||
<span className="text-3xl font-semibold text-[#06b6d4]">Free</span>
|
|
||||||
</div>
|
|
||||||
<p className="mb-8 text-sm text-muted-foreground">
|
|
||||||
For teams who want full control and can run their own infrastructure.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<ul className="mb-8 flex-1 space-y-4 text-sm text-foreground/80">
|
|
||||||
<li className="flex items-center gap-3">
|
|
||||||
<CheckSquare className="h-4 w-4 text-[#06b6d4]" />
|
|
||||||
Full codebase access
|
|
||||||
</li>
|
|
||||||
<li className="flex items-center gap-3">
|
|
||||||
<CheckSquare className="h-4 w-4 text-[#06b6d4]" />
|
|
||||||
Self-hosted infrastructure control
|
|
||||||
</li>
|
|
||||||
<li className="flex items-center gap-3">
|
|
||||||
<CheckSquare className="h-4 w-4 text-[#06b6d4]" />
|
|
||||||
Manual update cadence
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<a
|
|
||||||
href="https://github.com/yusufipk/OpenFrame"
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
className="mt-auto group relative isolate inline-flex h-12 w-full items-center justify-center overflow-hidden border border-border/50 bg-[#0a0a0a] font-medium text-foreground transition-colors hover:bg-white/5 text-sm"
|
|
||||||
>
|
|
||||||
<Github className="mr-2 h-4 w-4" /> View on GitHub
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Card 2: Hosted Cloud */}
|
|
||||||
<div
|
<div
|
||||||
data-reveal
|
data-reveal
|
||||||
className="relative flex flex-col border border-[#06b6d4]/40 bg-[#141414] p-8"
|
className="relative flex flex-col border border-[#06b6d4]/40 bg-[#141414] p-8"
|
||||||
>
|
>
|
||||||
|
<span className="absolute -top-3 left-8 bg-[#06b6d4] px-2 py-0.5 font-mono text-[10px] font-semibold uppercase tracking-widest text-black">
|
||||||
|
Recommended
|
||||||
|
</span>
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<p className="font-mono text-[10px] uppercase font-semibold text-muted-foreground tracking-widest mb-4">
|
<p className="font-mono text-[10px] uppercase font-semibold text-muted-foreground tracking-widest mb-4">
|
||||||
Best for teams who want zero setup.
|
Zero setup. Flat pricing, no per-seat fees.
|
||||||
</p>
|
</p>
|
||||||
<h3 className="text-xl font-semibold text-foreground">Hosted Cloud</h3>
|
<h3 className="text-xl font-semibold text-foreground">Hosted Cloud</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-6 flex items-baseline gap-2">
|
<div className="mb-2 flex items-baseline gap-2">
|
||||||
<span className="text-3xl font-semibold text-[#06b6d4]">$10</span>
|
<span className="text-3xl font-semibold text-[#06b6d4]">$10</span>
|
||||||
<span className="text-[#06b6d4]">/ month</span>
|
<span className="text-[#06b6d4]">/ month</span>
|
||||||
</div>
|
</div>
|
||||||
|
<p className="mb-6 text-sm text-muted-foreground">
|
||||||
|
Starts with a 7-day free trial. Cancel anytime.
|
||||||
|
</p>
|
||||||
|
|
||||||
<ul className="mb-8 flex-1 space-y-4 text-sm text-foreground/80">
|
<ul className="mb-8 flex-1 space-y-4 text-sm text-foreground/80">
|
||||||
<li className="flex items-start gap-3">
|
<li className="flex items-start gap-3">
|
||||||
@@ -751,10 +722,63 @@ export function LandingPage({ isLoggedIn }: LandingPageProps) {
|
|||||||
href={hostedCtaHref}
|
href={hostedCtaHref}
|
||||||
className="mt-auto group relative isolate inline-flex h-12 w-full items-center justify-center overflow-hidden bg-[#06b6d4] font-medium text-black transition-colors hover:bg-[#06b6d4]/90 text-sm"
|
className="mt-auto group relative isolate inline-flex h-12 w-full items-center justify-center overflow-hidden bg-[#06b6d4] font-medium text-black transition-colors hover:bg-[#06b6d4]/90 text-sm"
|
||||||
>
|
>
|
||||||
Start free
|
Start free trial
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Card 2: Fair Source (Self-hosted) */}
|
||||||
|
<div
|
||||||
|
data-reveal
|
||||||
|
className="relative flex flex-col border border-border/40 bg-[#141414] p-8"
|
||||||
|
>
|
||||||
|
<div className="mb-6">
|
||||||
|
<h3 className="text-xl font-semibold text-foreground">
|
||||||
|
Fair Source (Self-hosted)
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-8 flex items-baseline gap-2">
|
||||||
|
<span className="text-3xl font-semibold text-[#06b6d4]">Free</span>
|
||||||
|
</div>
|
||||||
|
<p className="mb-8 text-sm text-muted-foreground">
|
||||||
|
For teams who want full control and can run their own infrastructure. Licensed
|
||||||
|
under the{' '}
|
||||||
|
<a
|
||||||
|
href="https://fsl.software/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="underline underline-offset-2 hover:text-foreground"
|
||||||
|
>
|
||||||
|
Functional Source License
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul className="mb-8 flex-1 space-y-4 text-sm text-foreground/80">
|
||||||
|
<li className="flex items-start gap-3">
|
||||||
|
<CheckSquare className="mt-0.5 h-4 w-4 shrink-0 text-[#06b6d4]" />
|
||||||
|
Full source code — read it, audit it
|
||||||
|
</li>
|
||||||
|
<li className="flex items-start gap-3">
|
||||||
|
<CheckSquare className="mt-0.5 h-4 w-4 shrink-0 text-[#06b6d4]" />
|
||||||
|
Self-host on your own infrastructure
|
||||||
|
</li>
|
||||||
|
<li className="flex items-start gap-3">
|
||||||
|
<CheckSquare className="mt-0.5 h-4 w-4 shrink-0 text-[#06b6d4]" />
|
||||||
|
Every release becomes Apache 2.0 open source after two years
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href="https://github.com/yusufipk/OpenFrame"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="mt-auto group relative isolate inline-flex h-12 w-full items-center justify-center overflow-hidden border border-border/50 bg-[#0a0a0a] font-medium text-foreground transition-colors hover:bg-white/5 text-sm"
|
||||||
|
>
|
||||||
|
<Github className="mr-2 h-4 w-4" /> View on GitHub
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Card 3: Studio & Agency */}
|
{/* Card 3: Studio & Agency */}
|
||||||
<div
|
<div
|
||||||
data-reveal
|
data-reveal
|
||||||
@@ -775,7 +799,7 @@ export function LandingPage({ isLoggedIn }: LandingPageProps) {
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
href="mailto:support@openframe.com"
|
href="mailto:info@open-frame.net"
|
||||||
className="group relative isolate inline-flex h-12 w-full items-center justify-center overflow-hidden bg-[#0a0a0a] font-medium text-foreground transition-colors hover:bg-white/5 border border-border/50 text-sm"
|
className="group relative isolate inline-flex h-12 w-full items-center justify-center overflow-hidden bg-[#0a0a0a] font-medium text-foreground transition-colors hover:bg-white/5 border border-border/50 text-sm"
|
||||||
>
|
>
|
||||||
Contact us
|
Contact us
|
||||||
@@ -823,7 +847,15 @@ export function LandingPage({ isLoggedIn }: LandingPageProps) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
q: 'Can I self-host?',
|
q: 'Can I self-host?',
|
||||||
a: 'Yes. The core is open-source and self-hostable. Hosted Cloud is for teams who want zero setup.',
|
a: 'Yes. The full source code is public and ships with a Docker setup for self-hosting. Hosted Cloud is for teams who want zero setup.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
q: 'Is OpenFrame open source?',
|
||||||
|
a: 'OpenFrame is Fair Source, licensed under the Functional Source License (FSL). You can read and audit the full source code and self-host it, and every release automatically becomes Apache 2.0 open source two years after publication.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
q: 'Is there a free trial?',
|
||||||
|
a: 'Yes. Hosted Cloud starts with a 7-day free trial. After that it is a flat $10/mo — no per-seat or per-client fees.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
q: 'How is this different from sending a Google Drive link?',
|
q: 'How is this different from sending a Google Drive link?',
|
||||||
@@ -874,7 +906,7 @@ export function LandingPage({ isLoggedIn }: LandingPageProps) {
|
|||||||
href={hostedCtaHref}
|
href={hostedCtaHref}
|
||||||
className="group relative isolate inline-flex h-12 min-w-max items-center justify-center overflow-hidden border border-primary bg-primary px-10 text-sm font-medium whitespace-nowrap text-primary-foreground transition-transform duration-300 hover:scale-[1.02] md:min-w-[240px]"
|
className="group relative isolate inline-flex h-12 min-w-max items-center justify-center overflow-hidden border border-primary bg-primary px-10 text-sm font-medium whitespace-nowrap text-primary-foreground transition-transform duration-300 hover:scale-[1.02] md:min-w-[240px]"
|
||||||
>
|
>
|
||||||
Start free
|
Start free trial
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ export async function sendVerificationEmail(email: string, token: string): Promi
|
|||||||
|
|
||||||
const verifyUrl = `${baseUrl}/api/auth/verify-email?token=${encodeURIComponent(token)}`;
|
const verifyUrl = `${baseUrl}/api/auth/verify-email?token=${encodeURIComponent(token)}`;
|
||||||
const from =
|
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(
|
const html = brandedEmailTemplate(
|
||||||
`
|
`
|
||||||
|
|||||||
+1
-1
@@ -68,7 +68,7 @@ export async function sendInvitationEmail(input: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const fromAddress =
|
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 subject = `[OpenFrame] You were invited to a ${scopeLabel(input.scope)}: ${input.targetName}`;
|
||||||
const html = invitationEmailTemplate({
|
const html = invitationEmailTemplate({
|
||||||
inviterName: input.inviterName,
|
inviterName: input.inviterName,
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ export const comparisonPages: ComparisonPageDefinition[] = [
|
|||||||
title: 'Frame.io Alternative for Small Teams',
|
title: 'Frame.io Alternative for Small Teams',
|
||||||
metaDescription:
|
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.',
|
'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',
|
headline: 'Frame.io power without the enterprise bill',
|
||||||
subheadline:
|
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.',
|
'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: [
|
keywords: [
|
||||||
'self hosted frame.io alternative',
|
'self hosted frame.io alternative',
|
||||||
'self-hosted video review',
|
'self-hosted video review',
|
||||||
'open source video review',
|
'fair source video review',
|
||||||
],
|
],
|
||||||
eyebrow: 'Self-hosted review',
|
eyebrow: 'Self-hosted review',
|
||||||
headline: 'Keep client footage on your infrastructure',
|
headline: 'Keep client footage on your infrastructure',
|
||||||
@@ -270,7 +270,7 @@ export const comparisonPages: ComparisonPageDefinition[] = [
|
|||||||
bestForOpenFrame: [
|
bestForOpenFrame: [
|
||||||
'Teams with Docker ops capacity',
|
'Teams with Docker ops capacity',
|
||||||
'Privacy-sensitive client work',
|
'Privacy-sensitive client work',
|
||||||
'Studios comparing Frame.io to open/fair-source options',
|
'Studios comparing Frame.io to fair-source options',
|
||||||
],
|
],
|
||||||
bestForCompetitor: [
|
bestForCompetitor: [
|
||||||
'Teams needing Adobe enterprise integrations out of the box',
|
'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: 'Version compare', openframe: 'yes', competitor: 'yes' },
|
||||||
{ label: 'Enterprise DRM / SSO', openframe: 'no', competitor: 'yes' },
|
{ label: 'Enterprise DRM / SSO', openframe: 'no', competitor: 'yes' },
|
||||||
{ label: 'Adobe NLE integrations', 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: [
|
pricingRows: [
|
||||||
{ label: 'Self-hosted software cost', openframe: 'Free', competitor: 'Not available' },
|
{ label: 'Self-hosted software cost', openframe: 'Free', competitor: 'Not available' },
|
||||||
|
|||||||
@@ -565,7 +565,7 @@ export const openFrameProfile = {
|
|||||||
],
|
],
|
||||||
bestFor: [
|
bestFor: [
|
||||||
'Freelancers and small teams shipping client cuts',
|
'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',
|
'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> {
|
async function sendEmail(to: string, subject: string, html: string): Promise<boolean> {
|
||||||
const transporter = createSmtpTransport();
|
const transporter = createSmtpTransport();
|
||||||
const fromAddress =
|
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) {
|
if (!transporter) {
|
||||||
console.warn('SMTP not configured — skipping email notification');
|
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 {
|
function normalizeSiteUrl(rawUrl: string | undefined): string {
|
||||||
if (!rawUrl) {
|
if (!rawUrl) {
|
||||||
@@ -26,11 +26,12 @@ export function getSiteUrl(): string {
|
|||||||
|
|
||||||
export const seoConfig = {
|
export const seoConfig = {
|
||||||
name: 'OpenFrame',
|
name: 'OpenFrame',
|
||||||
title: 'Open Source Video Review Platform',
|
title: 'Fair Source Video Review Platform',
|
||||||
description:
|
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: [
|
keywords: [
|
||||||
'open source video review platform',
|
'fair source video review platform',
|
||||||
|
'video review platform',
|
||||||
'video review tool',
|
'video review tool',
|
||||||
'timestamped video feedback',
|
'timestamped video feedback',
|
||||||
'video collaboration',
|
'video collaboration',
|
||||||
|
|||||||
Reference in New Issue
Block a user