diff --git a/lib/openinary-loader.ts b/lib/openinary-loader.ts
new file mode 100644
index 0000000..8ae36b0
--- /dev/null
+++ b/lib/openinary-loader.ts
@@ -0,0 +1,39 @@
+'use client'
+
+export default function openinaryLoader({ src, width, quality }: { src: string, width: number, quality?: number }) {
+ // Handle already absolute openinary URLs
+ let path = src;
+ if (src.startsWith('https://media.ayris.tech/t/')) {
+ // format: https://media.ayris.tech/t/w_800,h_800/{project_name}/img.jpg
+ const parts = src.split('/');
+ path = parts.slice(5).join('/');
+ } else if (src.startsWith('https://media.ayris.tech/upload/')) {
+ // format: https://media.ayris.tech/upload/{project_name}/img.jpg
+ const parts = src.split('/');
+ path = parts.slice(4).join('/');
+ } else if (src.includes('res.cloudinary.com')) {
+ // Correctly apply width & quality for unmigrated Cloudinary URLs
+ // e.g. https://res.cloudinary.com/domain/image/upload/v1234/path.jpg
+ // becomes: https://res.cloudinary.com/domain/image/upload/w_800,f_webp,q_75/v1234/path.jpg
+ const parts = src.split('/upload/');
+ if (parts.length === 2) {
+ return `${parts[0]}/upload/w_${width},f_webp,q_${quality || 75}/${parts[1]}`;
+ }
+ return src;
+ } else if (src.startsWith('http')) {
+ // For other external URLs, we append the width as a query parameter to satisfy Next.js.
+ const url = new URL(src);
+ url.searchParams.set('w', width.toString());
+ if (quality) {
+ url.searchParams.set('q', quality.toString());
+ }
+ return url.toString();
+ }
+
+ // Clean up any leading slash
+ if (path.startsWith('/')) {
+ path = path.substring(1);
+ }
+
+ return `https://media.ayris.tech/t/w_${width},f_webp,q_${quality || 75}/${path}`
+}
diff --git a/lib/openinary-url.ts b/lib/openinary-url.ts
new file mode 100644
index 0000000..d8eb533
--- /dev/null
+++ b/lib/openinary-url.ts
@@ -0,0 +1,5 @@
+const BASE = process.env.NEXT_PUBLIC_OPENINARY_URL;
+
+export function optimizedImage(path: string, params: string) {
+ return `${BASE}/t/${params}/${path}`;
+}
diff --git a/lib/openinary.ts b/lib/openinary.ts
new file mode 100644
index 0000000..36fcb13
--- /dev/null
+++ b/lib/openinary.ts
@@ -0,0 +1,19 @@
+export async function uploadToOpeninary(file: File, folder: string) {
+ const formData = new FormData();
+ formData.append("files", file);
+ formData.append("folder", folder);
+
+ const res = await fetch(`${process.env.OPENINARY_API_URL}/api/upload`, {
+ method: "POST",
+ headers: { Authorization: `Bearer ${process.env.OPENINARY_API_KEY}` },
+ body: formData,
+ });
+
+ if (!res.ok) {
+ const errorText = await res.text();
+ console.error("Openinary upload error:", errorText);
+ throw new Error("Upload başarısız: " + errorText);
+ }
+ const data = await res.json();
+ return data.files[0]; // { path, url, size, ... }
+}
diff --git a/next-env.d.ts b/next-env.d.ts
index 9edff1c..c4b7818 100644
--- a/next-env.d.ts
+++ b/next-env.d.ts
@@ -1,6 +1,6 @@
///
///
-import "./.next/types/routes.d.ts";
+import "./.next/dev/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.