app/(public)/projects/page.tsx CHANGED
@@ -1,11 +1,31 @@
 
1
  import { redirect } from "next/navigation";
2
 
 
 
3
  import { MyProjects } from "@/components/my-projects";
4
- import { getProjects } from "@/app/actions/projects";
5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  export default async function ProjectsPage() {
7
- const { ok, projects } = await getProjects();
8
- if (!ok) {
9
  redirect("/");
10
  }
11
 
 
1
+ import { cookies } from "next/headers";
2
  import { redirect } from "next/navigation";
3
 
4
+ import { apiServer } from "@/lib/api";
5
+ import MY_TOKEN_KEY from "@/lib/get-cookie-name";
6
  import { MyProjects } from "@/components/my-projects";
 
7
 
8
+ async function getMyProjects() {
9
+ const cookieStore = await cookies();
10
+ const token = cookieStore.get(MY_TOKEN_KEY())?.value;
11
+ if (!token) return { redirectUrl: true, projects: [] };
12
+ try {
13
+ const { data } = await apiServer.get("/me/projects", {
14
+ headers: {
15
+ Authorization: `Bearer ${token}`,
16
+ },
17
+ });
18
+
19
+ return {
20
+ projects: data.projects,
21
+ };
22
+ } catch {
23
+ return { projects: [] };
24
+ }
25
+ }
26
  export default async function ProjectsPage() {
27
+ const { redirectUrl, projects } = await getMyProjects();
28
+ if (redirectUrl) {
29
  redirect("/");
30
  }
31
 
app/actions/auth.ts CHANGED
@@ -5,12 +5,9 @@ import { headers } from "next/headers";
5
  export async function getAuth() {
6
  const authList = await headers();
7
  const host = authList.get("host") ?? "localhost:3000";
8
- const url = host.includes("/spaces/enzostvs")
9
- ? "enzostvs-deepsite.hf.space"
10
- : host;
11
  const redirect_uri =
12
  `${host.includes("localhost") ? "http://" : "https://"}` +
13
- url +
14
  "/auth/callback";
15
 
16
  const loginRedirectUrl = `https://huggingface.co/oauth/authorize?client_id=${process.env.OAUTH_CLIENT_ID}&redirect_uri=${redirect_uri}&response_type=code&scope=openid%20profile%20write-repos%20manage-repos%20inference-api&prompt=consent&state=1234567890`;
 
5
  export async function getAuth() {
6
  const authList = await headers();
7
  const host = authList.get("host") ?? "localhost:3000";
 
 
 
8
  const redirect_uri =
9
  `${host.includes("localhost") ? "http://" : "https://"}` +
10
+ host +
11
  "/auth/callback";
12
 
13
  const loginRedirectUrl = `https://huggingface.co/oauth/authorize?client_id=${process.env.OAUTH_CLIENT_ID}&redirect_uri=${redirect_uri}&response_type=code&scope=openid%20profile%20write-repos%20manage-repos%20inference-api&prompt=consent&state=1234567890`;
app/actions/projects.ts DELETED
@@ -1,63 +0,0 @@
1
- "use server";
2
-
3
- import { isAuthenticated } from "@/lib/auth";
4
- import { NextResponse } from "next/server";
5
- import dbConnect from "@/lib/mongodb";
6
- import Project from "@/models/Project";
7
- import { Project as ProjectType } from "@/types";
8
-
9
- export async function getProjects(): Promise<{
10
- ok: boolean;
11
- projects: ProjectType[];
12
- }> {
13
- const user = await isAuthenticated();
14
-
15
- if (user instanceof NextResponse || !user) {
16
- return {
17
- ok: false,
18
- projects: [],
19
- };
20
- }
21
-
22
- await dbConnect();
23
- const projects = await Project.find({
24
- user_id: user?.id,
25
- })
26
- .sort({ _createdAt: -1 })
27
- .limit(100)
28
- .lean();
29
- if (!projects) {
30
- return {
31
- ok: false,
32
- projects: [],
33
- };
34
- }
35
- return {
36
- ok: true,
37
- projects: JSON.parse(JSON.stringify(projects)) as ProjectType[],
38
- };
39
- }
40
-
41
- export async function getProject(
42
- namespace: string,
43
- repoId: string
44
- ): Promise<ProjectType | null> {
45
- const user = await isAuthenticated();
46
-
47
- if (user instanceof NextResponse || !user) {
48
- return null;
49
- }
50
-
51
- await dbConnect();
52
- const project = await Project.findOne({
53
- user_id: user.id,
54
- namespace,
55
- repoId,
56
- }).lean();
57
-
58
- if (!project) {
59
- return null;
60
- }
61
-
62
- return JSON.parse(JSON.stringify(project)) as ProjectType;
63
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/api/ask-ai/route.ts CHANGED
@@ -223,8 +223,7 @@ export async function PUT(request: NextRequest) {
223
  const userToken = request.cookies.get(MY_TOKEN_KEY())?.value;
224
 
225
  const body = await request.json();
226
- const { prompt, html, previousPrompt, provider, selectedElementHtml, model } =
227
- body;
228
 
229
  if (!prompt || !html) {
230
  return NextResponse.json(
@@ -233,15 +232,7 @@ export async function PUT(request: NextRequest) {
233
  );
234
  }
235
 
236
- const selectedModel = MODELS.find(
237
- (m) => m.value === model || m.label === model
238
- );
239
- if (!selectedModel) {
240
- return NextResponse.json(
241
- { ok: false, error: "Invalid model selected" },
242
- { status: 400 }
243
- );
244
- }
245
 
246
  let token = userToken;
247
  let billTo: string | null = null;
 
223
  const userToken = request.cookies.get(MY_TOKEN_KEY())?.value;
224
 
225
  const body = await request.json();
226
+ const { prompt, html, previousPrompt, provider, selectedElementHtml } = body;
 
227
 
228
  if (!prompt || !html) {
229
  return NextResponse.json(
 
232
  );
233
  }
234
 
235
+ const selectedModel = MODELS[0];
 
 
 
 
 
 
 
 
236
 
237
  let token = userToken;
238
  let billTo: string | null = null;
app/api/auth/route.ts CHANGED
@@ -22,13 +22,9 @@ export async function POST(req: NextRequest) {
22
 
23
  const host =
24
  req.headers.get("host") ?? req.headers.get("origin") ?? "localhost:3000";
25
-
26
- const url = host.includes("/spaces/enzostvs")
27
- ? "enzostvs-deepsite.hf.space"
28
- : host;
29
  const redirect_uri =
30
  `${host.includes("localhost") ? "http://" : "https://"}` +
31
- url +
32
  "/auth/callback";
33
  const request_auth = await fetch("https://huggingface.co/oauth/token", {
34
  method: "POST",
 
22
 
23
  const host =
24
  req.headers.get("host") ?? req.headers.get("origin") ?? "localhost:3000";
 
 
 
 
25
  const redirect_uri =
26
  `${host.includes("localhost") ? "http://" : "https://"}` +
27
+ host +
28
  "/auth/callback";
29
  const request_auth = await fetch("https://huggingface.co/oauth/token", {
30
  method: "POST",
app/api/me/projects/[namespace]/[repoId]/route.ts CHANGED
@@ -205,12 +205,10 @@ export async function POST(
205
  space_id: `${namespace}/${repoId}`,
206
  }).lean();
207
  if (project) {
208
- // redirect to the project page if it already exists
209
  return NextResponse.json(
210
  {
211
  ok: false,
212
  error: "Project already exists",
213
- redirect: `/projects/${namespace}/${repoId}`,
214
  },
215
  { status: 400 }
216
  );
 
205
  space_id: `${namespace}/${repoId}`,
206
  }).lean();
207
  if (project) {
 
208
  return NextResponse.json(
209
  {
210
  ok: false,
211
  error: "Project already exists",
 
212
  },
213
  { status: 400 }
214
  );
app/layout.tsx CHANGED
@@ -9,7 +9,6 @@ import { Toaster } from "@/components/ui/sonner";
9
  import MY_TOKEN_KEY from "@/lib/get-cookie-name";
10
  import { apiServer } from "@/lib/api";
11
  import AppContext from "@/components/contexts/app-context";
12
- import Script from "next/script";
13
 
14
  const inter = Inter({
15
  variable: "--font-inter-sans",
@@ -90,11 +89,6 @@ export default async function RootLayout({
90
  const data = await getMe();
91
  return (
92
  <html lang="en">
93
- <Script
94
- defer
95
- data-domain="deepsite.hf.co"
96
- src="https://plausible.io/js/script.js"
97
- ></Script>
98
  <body
99
  className={`${inter.variable} ${ptSans.variable} antialiased bg-black dark h-[100dvh] overflow-hidden`}
100
  >
 
9
  import MY_TOKEN_KEY from "@/lib/get-cookie-name";
10
  import { apiServer } from "@/lib/api";
11
  import AppContext from "@/components/contexts/app-context";
 
12
 
13
  const inter = Inter({
14
  variable: "--font-inter-sans",
 
89
  const data = await getMe();
90
  return (
91
  <html lang="en">
 
 
 
 
 
92
  <body
93
  className={`${inter.variable} ${ptSans.variable} antialiased bg-black dark h-[100dvh] overflow-hidden`}
94
  >
components/editor/ask-ai/index.tsx CHANGED
@@ -67,10 +67,6 @@ export function AskAI({
67
  const [controller, setController] = useState<AbortController | null>(null);
68
  const [isFollowUp, setIsFollowUp] = useState(true);
69
 
70
- const selectedModel = useMemo(() => {
71
- return MODELS.find((m: { value: string }) => m.value === model);
72
- }, [model]);
73
-
74
  const callAi = async (redesignMarkdown?: string) => {
75
  if (isAiWorking) return;
76
  if (!redesignMarkdown && !prompt.trim()) return;
@@ -177,14 +173,13 @@ export function AskAI({
177
  return;
178
  }
179
 
 
180
  toast.success("AI responded successfully");
181
  setPreviousPrompt(prompt);
182
  setPrompt("");
183
  setisAiWorking(false);
184
  setHasAsked(true);
185
- if (selectedModel?.isThinker) {
186
- setModel(MODELS[0].value);
187
- }
188
  if (audio.current) audio.current.play();
189
 
190
  // Now we have the complete HTML including </html>, so set it to be sure
@@ -450,7 +445,7 @@ export function AskAI({
450
  id="diff-patch-checkbox"
451
  checked={isFollowUp}
452
  onCheckedChange={(e) => {
453
- if (e === true && !isSameHtml && selectedModel?.isThinker) {
454
  setModel(MODELS[0].value);
455
  }
456
  setIsFollowUp(e === true);
 
67
  const [controller, setController] = useState<AbortController | null>(null);
68
  const [isFollowUp, setIsFollowUp] = useState(true);
69
 
 
 
 
 
70
  const callAi = async (redesignMarkdown?: string) => {
71
  if (isAiWorking) return;
72
  if (!redesignMarkdown && !prompt.trim()) return;
 
173
  return;
174
  }
175
 
176
+ console.log("AI response complete", contentResponse);
177
  toast.success("AI responded successfully");
178
  setPreviousPrompt(prompt);
179
  setPrompt("");
180
  setisAiWorking(false);
181
  setHasAsked(true);
182
+ setModel(MODELS[0].value);
 
 
183
  if (audio.current) audio.current.play();
184
 
185
  // Now we have the complete HTML including </html>, so set it to be sure
 
445
  id="diff-patch-checkbox"
446
  checked={isFollowUp}
447
  onCheckedChange={(e) => {
448
+ if (e === true && !isSameHtml) {
449
  setModel(MODELS[0].value);
450
  }
451
  setIsFollowUp(e === true);
components/editor/deploy-button/index.tsx CHANGED
@@ -71,7 +71,7 @@ export function DeployButton({
71
  <div>
72
  <Button variant="default" className="max-lg:hidden !px-4">
73
  <MdSave className="size-4" />
74
- Deploy your Project
75
  </Button>
76
  <Button variant="default" size="sm" className="lg:hidden">
77
  Deploy
 
71
  <div>
72
  <Button variant="default" className="max-lg:hidden !px-4">
73
  <MdSave className="size-4" />
74
+ Save your Project
75
  </Button>
76
  <Button variant="default" size="sm" className="lg:hidden">
77
  Deploy
components/editor/save-button/index.tsx CHANGED
@@ -51,24 +51,25 @@ export function SaveButton({
51
  setLoading(false);
52
  }
53
  };
 
54
  return (
55
  <>
56
  <Button
57
  variant="default"
58
- className="max-lg:hidden !px-4 relative"
59
  onClick={updateSpace}
60
  >
61
  <MdSave className="size-4" />
62
- Deploy your Project{" "}
63
  {loading && <Loading className="ml-2 size-4 animate-spin" />}
64
  </Button>
65
  <Button
66
  variant="default"
67
  size="sm"
68
- className="lg:hidden relative"
69
  onClick={updateSpace}
70
  >
71
- Deploy {loading && <Loading className="ml-2 size-4 animate-spin" />}
72
  </Button>
73
  </>
74
  );
 
51
  setLoading(false);
52
  }
53
  };
54
+
55
  return (
56
  <>
57
  <Button
58
  variant="default"
59
+ className="max-lg:hidden !px-4"
60
  onClick={updateSpace}
61
  >
62
  <MdSave className="size-4" />
63
+ Save your Project{" "}
64
  {loading && <Loading className="ml-2 size-4 animate-spin" />}
65
  </Button>
66
  <Button
67
  variant="default"
68
  size="sm"
69
+ className="lg:hidden"
70
  onClick={updateSpace}
71
  >
72
+ Save {loading && <Loading className="ml-2 size-4 animate-spin" />}
73
  </Button>
74
  </>
75
  );
components/my-projects/load-project.tsx CHANGED
@@ -16,7 +16,6 @@ import { toast } from "sonner";
16
  import { api } from "@/lib/api";
17
  import { useUser } from "@/hooks/useUser";
18
  import { LoginModal } from "../login-modal";
19
- import { useRouter } from "next/navigation";
20
 
21
  export const LoadProject = ({
22
  fullXsBtn = false,
@@ -26,7 +25,6 @@ export const LoadProject = ({
26
  onSuccess: (project: Project) => void;
27
  }) => {
28
  const { user } = useUser();
29
- const router = useRouter();
30
 
31
  const [openLoginModal, setOpenLoginModal] = useState(false);
32
  const [open, setOpen] = useState(false);
@@ -61,15 +59,13 @@ export const LoadProject = ({
61
  setIsLoading(true);
62
  try {
63
  const response = await api.post(`/me/projects/${username}/${namespace}`);
 
64
  toast.success("Project imported successfully!");
65
  setOpen(false);
66
  setUrl("");
67
  onSuccess(response.data.project);
68
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
69
  } catch (error: any) {
70
- if (error?.response?.data?.redirect) {
71
- return router.push(error.response.data.redirect);
72
- }
73
  toast.error(
74
  error?.response?.data?.error ?? "Failed to import the project."
75
  );
 
16
  import { api } from "@/lib/api";
17
  import { useUser } from "@/hooks/useUser";
18
  import { LoginModal } from "../login-modal";
 
19
 
20
  export const LoadProject = ({
21
  fullXsBtn = false,
 
25
  onSuccess: (project: Project) => void;
26
  }) => {
27
  const { user } = useUser();
 
28
 
29
  const [openLoginModal, setOpenLoginModal] = useState(false);
30
  const [open, setOpen] = useState(false);
 
59
  setIsLoading(true);
60
  try {
61
  const response = await api.post(`/me/projects/${username}/${namespace}`);
62
+ console.log("response", response);
63
  toast.success("Project imported successfully!");
64
  setOpen(false);
65
  setUrl("");
66
  onSuccess(response.data.project);
67
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
  } catch (error: any) {
 
 
 
69
  toast.error(
70
  error?.response?.data?.error ?? "Failed to import the project."
71
  );
lib/auth.ts CHANGED
@@ -1,7 +1,6 @@
1
  import { User } from "@/types";
2
  import { NextResponse } from "next/server";
3
- import { cookies, headers } from "next/headers";
4
- import MY_TOKEN_KEY from "./get-cookie-name";
5
 
6
  // UserResponse = type User & { token: string };
7
  type UserResponse = User & { token: string };
@@ -9,11 +8,7 @@ type UserResponse = User & { token: string };
9
  export const isAuthenticated = async (): // req: NextRequest
10
  Promise<UserResponse | NextResponse<unknown> | undefined> => {
11
  const authHeaders = await headers();
12
- const cookieStore = await cookies();
13
- const token = cookieStore.get(MY_TOKEN_KEY())?.value
14
- ? `Bearer ${cookieStore.get(MY_TOKEN_KEY())?.value}`
15
- : authHeaders.get("Authorization");
16
-
17
  if (!token) {
18
  return NextResponse.json(
19
  {
 
1
  import { User } from "@/types";
2
  import { NextResponse } from "next/server";
3
+ import { headers } from "next/headers";
 
4
 
5
  // UserResponse = type User & { token: string };
6
  type UserResponse = User & { token: string };
 
8
  export const isAuthenticated = async (): // req: NextRequest
9
  Promise<UserResponse | NextResponse<unknown> | undefined> => {
10
  const authHeaders = await headers();
11
+ const token = authHeaders.get("Authorization");
 
 
 
 
12
  if (!token) {
13
  return NextResponse.json(
14
  {
lib/prompts.ts CHANGED
@@ -2,7 +2,7 @@ export const SEARCH_START = "<<<<<<< SEARCH";
2
  export const DIVIDER = "=======";
3
  export const REPLACE_END = ">>>>>>> REPLACE";
4
  export const MAX_REQUESTS_PER_IP = 2;
5
- export const INITIAL_SYSTEM_PROMPT = `ONLY USE HTML, CSS AND JAVASCRIPT. If you want to use ICON make sure to import the library first. Try to create the best UI possible by using only HTML, CSS and JAVASCRIPT. MAKE IT RESPONSIVE USING TAILWINDCSS. Use as much as you can TailwindCSS for the CSS, if you can't do something with TailwindCSS, then use custom CSS (make sure to import <script src="https://cdn.tailwindcss.com"></script> in the head). Also, try to ellaborate as much as you can, to create something unique. ALWAYS GIVE THE RESPONSE INTO A SINGLE HTML FILE. AVOID CHINESE CHARACTERS IN THE CODE IF NOT ASKED BY THE USER.`;
6
  export const FOLLOW_UP_SYSTEM_PROMPT = `You are an expert web developer modifying an existing HTML file.
7
  The user wants to apply changes based on their request.
8
  You MUST output ONLY the changes required using the following SEARCH/REPLACE block format. Do NOT output the entire file.
 
2
  export const DIVIDER = "=======";
3
  export const REPLACE_END = ">>>>>>> REPLACE";
4
  export const MAX_REQUESTS_PER_IP = 2;
5
+ export const INITIAL_SYSTEM_PROMPT = `ONLY USE HTML, CSS AND JAVASCRIPT. If you want to use ICON make sure to import the library first. Try to create the best UI possible by using only HTML, CSS and JAVASCRIPT. MAKE IT RESPONSIVE USING TAILWINDCSS. Use as much as you can TailwindCSS for the CSS, if you can't do something with TailwindCSS, then use custom CSS (make sure to import <script src="https://cdn.tailwindcss.com"></script> in the head). Also, try to ellaborate as much as you can, to create something unique. ALWAYS GIVE THE RESPONSE INTO A SINGLE HTML FILE`;
6
  export const FOLLOW_UP_SYSTEM_PROMPT = `You are an expert web developer modifying an existing HTML file.
7
  The user wants to apply changes based on their request.
8
  You MUST output ONLY the changes required using the following SEARCH/REPLACE block format. Do NOT output the entire file.
lib/providers.ts CHANGED
@@ -29,11 +29,6 @@ export const PROVIDERS = {
29
  max_tokens: 128_000,
30
  id: "together",
31
  },
32
- groq: {
33
- name: "Groq",
34
- max_tokens: 16_384,
35
- id: "groq",
36
- },
37
  };
38
 
39
  export const MODELS = [
@@ -55,19 +50,7 @@ export const MODELS = [
55
  "sambanova",
56
  ],
57
  autoProvider: "novita",
58
- isThinker: true,
59
- },
60
- {
61
- value: "Qwen/Qwen3-Coder-480B-A35B-Instruct",
62
- label: "Qwen3 Coder 480B A35B Instruct",
63
- providers: ["novita", "hyperbolic"],
64
- autoProvider: "novita",
65
  isNew: true,
66
- },
67
- {
68
- value: "moonshotai/Kimi-K2-Instruct",
69
- label: "Kimi K2 Instruct",
70
- providers: ["together", "novita", "groq"],
71
- autoProvider: "groq",
72
  },
73
  ];
 
29
  max_tokens: 128_000,
30
  id: "together",
31
  },
 
 
 
 
 
32
  };
33
 
34
  export const MODELS = [
 
50
  "sambanova",
51
  ],
52
  autoProvider: "novita",
 
 
 
 
 
 
 
53
  isNew: true,
54
+ isThinker: true,
 
 
 
 
 
55
  },
56
  ];
public/providers/groq.svg DELETED