Skip to content
Merged

Dev #22

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ build/
dist/
artifacts/
*.tsbuildinfo
bun.lockb
Binary file removed bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion electrobun.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export default {
app: {
name: "yafw",
identifier: "yafw.electrobun.dev",
version: "0.7.3",
version: "0.7.4",
},
build: {
// Vite builds to dist/, Electrobun copies from there into the bundle
Expand Down
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@
"dev:hmr": "concurrently \"bun run hmr\" \"bun run start\"",
"hmr": "vite --port 5173",
"build:canary": "bun run scripts/patch-win-icons.js && vite build && electrobun build --env=canary",
"build:stable": "bun run scripts/patch-win-icons.js && vite build && electrobun build --env=stable"
"build:stable": "bun run scripts/patch-win-icons.js && vite build && electrobun build --env=stable",
"build:web": "vite-react-ssg build"
},
"dependencies": {
"@ffmpeg/ffmpeg": "^0.12.15",
"@ffmpeg/util": "^0.12.2",
"electrobun": "^1.18.4-beta.3",
"react": "^18.3.1",
"react-dom": "^18.3.1"
"react-dom": "^18.3.1",
"react-router-dom": "^6.28.0"
},
"devDependencies": {
"@types/bun": "latest",
Expand All @@ -27,6 +29,7 @@
"postcss": "^8.4.49",
"tailwindcss": "^3.4.16",
"typescript": "^5.7.2",
"vite": "^6.0.3"
"vite": "^6.0.3",
"vite-react-ssg": "^0.9.1-beta.1"
}
}
4 changes: 4 additions & 0 deletions public/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
User-agent: *
Allow: /

Sitemap: https://yafw.valentinrapp.fr/sitemap.xml
9 changes: 9 additions & 0 deletions public/sitemap.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://yafw.valentinrapp.fr/</loc>
<lastmod>2026-06-23</lastmod>
<changefreq>monthly</changefreq>
<priority>1.0</priority>
</url>
</urlset>
39 changes: 38 additions & 1 deletion src/mainview/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useElectrobun } from "./hooks/useElectrobun";
import { Updating } from "./components/Updating";
import { isMac } from "./env";

const App = () => {
const ClientApp = () => {
const editorState = useVideoEditor();
const {
videoSrc,
Expand Down Expand Up @@ -65,6 +65,7 @@ const App = () => {
setCurrentPage={setCurrentPage}
videoSrc={videoSrc}
onChangeVideo={handleChangeVideo}
isStandalone={isStandalone}
/>

{/* Main Content Area */}
Expand All @@ -90,6 +91,7 @@ const App = () => {
onFileSelect={handleFileSelect}
onNativeBrowse={handleNativeBrowse}
onNavigateDownload={() => setCurrentPage("download")}
isStandalone={isStandalone}
/>
)}
</div>
Expand All @@ -108,4 +110,39 @@ const App = () => {
);
};

const ServerApp = () => {
return (
<div className="flex flex-col bg-mocha-base min-h-screen text-mocha-text relative overflow-hidden">
<div className="absolute top-1/4 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[500px] h-[500px] bg-mocha-mauve/5 rounded-full blur-[120px] pointer-events-none" />
<div className="absolute bottom-1/4 left-1/3 w-[300px] h-[300px] bg-mocha-blue/3 rounded-full blur-[100px] pointer-events-none" />

<Header
currentPage="editor"
setCurrentPage={() => {}}
videoSrc={null}
onChangeVideo={() => {}}
isStandalone={false}
/>

<div className="flex-1 flex flex-col items-center justify-center p-6 relative z-10 w-full">
<div className="bg-mocha-surface0/60 backdrop-blur-md rounded-2xl border border-mocha-surface0 shadow-2xl w-full max-w-2xl p-8 md:p-12">
<LandingPage
onFileSelect={() => {}}
onNativeBrowse={() => {}}
onNavigateDownload={() => {}}
isStandalone={false}
/>
</div>
</div>
</div>
);
};

const App = () => {
if (import.meta.env.SSR) {
return <ServerApp />;
}
return <ClientApp />;
};

export default App;
8 changes: 6 additions & 2 deletions src/mainview/components/FileDropZone.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { useRef, useState } from "react";
import { isStandalone } from "../env";

interface FileDropZoneProps {
onFileSelect: (file: File) => void;
onNativeBrowse?: () => void;
isStandalone: boolean;
}

export const FileDropZone = ({ onFileSelect, onNativeBrowse }: FileDropZoneProps) => {
export const FileDropZone = ({
onFileSelect,
onNativeBrowse,
isStandalone,
}: FileDropZoneProps) => {
const [isDragging, setIsDragging] = useState(false);
const fileInputRef = useRef<HTMLInputElement>(null);

Expand Down
4 changes: 3 additions & 1 deletion src/mainview/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import { isStandalone, isMac } from "../env";
import { isMac } from "../env";
import logoUrl from "../assets/logo.png";

interface HeaderProps {
currentPage: "editor" | "download";
setCurrentPage: (page: "editor" | "download") => void;
videoSrc: string | null;
onChangeVideo: () => void;
isStandalone: boolean;
}

export const Header = ({
currentPage,
setCurrentPage,
videoSrc,
onChangeVideo,
isStandalone,
}: HeaderProps) => (
<header className={`${isStandalone && isMac ? "electrobun-webkit-app-region-drag pl-20" : ""} bg-mocha-crust/80 backdrop-blur border-b border-mocha-surface0 px-6 py-4 flex items-center justify-between z-20`}>
<div className="flex items-center gap-3 select-none">
Expand Down
4 changes: 3 additions & 1 deletion src/mainview/components/LandingPage.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { FileDropZone } from "./FileDropZone";
import { isStandalone } from "../env";
import logoUrl from "../assets/logo.png";

interface LandingPageProps {
onFileSelect: (file: File) => void;
onNativeBrowse: () => void;
onNavigateDownload: () => void;
isStandalone: boolean;
}

export const LandingPage = ({
onFileSelect,
onNativeBrowse,
onNavigateDownload,
isStandalone,
}: LandingPageProps) => (
<>
<div className="text-center mb-8">
Expand Down Expand Up @@ -48,6 +49,7 @@ export const LandingPage = ({
onNativeBrowse={
isStandalone ? onNativeBrowse : undefined
}
isStandalone={isStandalone}
/>
</div>

Expand Down
9 changes: 7 additions & 2 deletions src/mainview/hooks/useElectrobun.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect, useRef, useState } from "react";
import { isStandalone } from "../env";
import { isStandalone as rawIsStandalone } from "../env";
import { type AppRPCType } from "../../shared/types";

let sharedElectroview: any = null;
Expand All @@ -10,9 +10,14 @@ const listeners = new Set<(ev: any, encoders: string[]) => void>();
export const useElectrobun = () => {
const [supportedEncoders, setSupportedEncoders] = useState<string[]>(sharedSupportedEncoders);
const [electroview, setElectroview] = useState<any>(sharedElectroview);
const [isStandalone, setIsStandalone] = useState(false);

useEffect(() => {
if (!isStandalone) return;
if (rawIsStandalone) {
setIsStandalone(true);
}

if (!rawIsStandalone) return;

if (sharedElectroview) {
setElectroview(sharedElectroview);
Expand Down
37 changes: 37 additions & 0 deletions src/mainview/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,44 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<!-- Primary SEO Metadata -->
<title>YAFW - Yet Another FFmpeg Wrapper</title>
<meta name="description" content="trim, convert, adjust, compress, and re-encode videos in your browser in a modern, lightweight, and completely private video editor, running on the web, or on your desktop. 100% local, fast, and gorgeous." />
<meta name="keywords" content="ffmpeg, video editor, video trimmer, video convertor, video compressor, MP4 to WebM, trim video online, local video editor, private video editor, desktop video editor" />
<meta name="robots" content="index, follow" />

<!-- Open Graph / Facebook / Discord -->
<meta property="og:type" content="website" />
<meta property="og:title" content="YAFW - Yet Another FFmpeg Wrapper" />
<meta property="og:description" content="Trim, convert, adjust, compress, and re-encode videos in seconds. Completely private, fast, and gorgeous web & desktop video editor." />
<meta property="og:image" content="./assets/logo.png" />
<meta property="og:url" content="https://yafw.valentinrapp.fr/" />

<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="YAFW - Yet Another FFmpeg Wrapper" />
<meta name="twitter:description" content="Trim, convert, adjust, compress, and re-encode videos in seconds. Completely private, fast, and gorgeous web & desktop video editor." />
<meta name="twitter:image" content="./assets/logo.png" />

<!-- Structured Data (JSON-LD) for SEO -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "YAFW",
"operatingSystem": "Windows, macOS, Linux",
"applicationCategory": "MultimediaApplication",
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "USD"
},
"url": "https://yafw.valentinrapp.fr/",
"description": "Yet Another FFmpeg Wrapper - A modern, lightweight, and completely private video editor to trim, convert, adjust, compress, and re-encode videos."
}
</script>

<link rel="icon" type="image/x-icon" href="./assets/logo.ico" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
Expand Down
9 changes: 2 additions & 7 deletions src/mainview/main.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { ViteReactSSG } from "vite-react-ssg/single-page";
import "./index.css";
import App from "./App";

createRoot(document.getElementById("root")!).render(
<StrictMode>
<App />
</StrictMode>,
);
export const createRoot = ViteReactSSG(<App />);
1 change: 1 addition & 0 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
root: "src/mainview",
publicDir: "../../public",
build: {
outDir: "../../dist",
emptyOutDir: true,
Expand Down
Loading