thank you sir you're great motivation hy guys i'm kinda confused for my final year project what should i make please give me the idea note i'm backend intern at the company in node js, but id do have basic react knowledge which allow me to become full stack now the thing is it's difficult for me to built anything but i;m confused what should i make saas build project unique one
A true tutorial - The fact that you spent almost an entire chapter explaining why the auth-call back is important/how it works is extremely impressive and helpful.
Damn 11 hours Josh! Thanks for working so hard to bring this content to the community and not putting it behind payed JS tutorials and signups. Super clean keep up the good work.
🤯🤯 God this is awesome! Auth + PDFs + Stripe + OpenAI Streaming! Josh you're a legend! This will get me a real job by the end of this year 😆 Thank you so much!!
Hopefully you get a good job! However, technologies focusing on the having a REST api and SPA approach rather than tRPC is most likely what you will be doing in a job and that’s what will resonate more with your interviewers, some might not even have heard of tRPC and might pick a candidate that can show they understand the standard web practices betterZ Nevertheless, best of luck with your job search!
Josh you are insane man. Those videos are going to be insanely helpful for people like me who have the basics down but don't know exactly how to proceed efficiently with certain things. Much much love bro.
I really like these videos that are unqiue and advanced at the same time, there are always Netflix, Twitter, Amazon clones out there BUT this one rocks. Thanks Josh, really appreciate it man.❤❤
Number #1 advise nobody ever gives you: To avoid too many conflicts (usually happens due to new versions of a package). Make sure your package.json file matches Josh's file on github. If you run into issues, align the two and write pnpm up. It will update all your packages to the matching versions of Joshs
Hey, sooo, I was doing this. However, I noticed that everytime, I try downgrading the @tailwindcss/typography": ^0.5.12" to the same one with Josh. It just does not downgarde and was still like that.
1:46:38 [React Query issue] As React Query 5 has just been released and the current version of tRPC (v10) still depends on React Query 4, the installation cmd of tRPC would be: pnpm add @trpc/server @trpc/client @trpc/react-query @trpc/next @tanstack/react-query@^4.18.0 zod . And this would be updated in tRPC v11.
2:06:22 React Query 5 has a breaking change that all callbacks have been removed from useQuery. So the use of onSuccess callback here is no longer feasible.
This is my implementation, I use an useEffect for that useEffect(() => { // error code unauthorized : if (error?.data?.code === "UNAUTHORIZED" ) { router.push("/sign-in"); } // success else if (!isLoading) { router.push((data !== undefined && data.success && origin) ? `/${origin}` : "/dashboard"); } }, [data, isLoading]); @@amardeep6088
Great video Josh! For those building this, an improvement to this is to validate pdf pages on drag enter or click upload and show the error state in the upload input. Or you could show a message on each upload on the free tier stating that even if they upload a pdf with more than 5 pages only the first five pages will be accepted The second option is more user friendly and would probably work better.
this video is an absolute gem! 😍 It's incredible to see a complete SaaS platform being built from scratch using such an impressive stack of technologies.
Whaaaaaat,am I dreaming or what 🤯. Josh thank you so much this will help many of us that has Sass ideas but not very good at building pages like this Kickstart it . Thank you so much ❤
Excellent work! A gentle suggestion would be add the following components as part 2. Feature flags/experimentation using posthog etc., event tracking using umami , and headless CMS for marketing. This would be deadly combo. Most of the tutorials do not cover these components with SaaS. These are very important for product optimization. Thank you
Thank you for such a lovely project Josh, it truly is beautiful. Word of advice for anyone doing this now: a lot of things have changed and it make it really difficult to follow along especially as you're learning, TCRP has updated their docs , the library isn't free and some issue with Pinecone. Maybe do something more up to date.
Great video, In the part of getting the user information at the beginning of creating the dashboard, I realised that you have to use 'await' in front of 'getKindeServerSession' and 'getUser' function, and accordingly make the page an async function.
hey, my code still doesn't work and your the only one who commented about a potential fix, but when I put await in front of both the functions instead of getting an error under email, I just get one under the "user" (in user.email)
@@WarTornTales make the function enclosing the "await" keyword an async function by adding it like this: const page = async () => { const { getUser } = getKindeServerSession(); const user = await getUser(); if(!user || !user.id) redirect('/auth-callback?origin=dashboard'); return ( {user?.email} ) }
@@WarTornTales Also, you may be getting a typescript error because user can be null from KindeUser, so you must add the question mark in front of user like so "user?.email"
Absolutely insane to offer this kind of content for free! You are a true 🐐for doing this Josh! Pushing small business forward is a huge step to tackle the corporate conglomerate landscape we see today. Best of luck to everyone who will start their own side hustles from content like this, let's come up with great ideas 💡
For 2:05:35 this might help u const query = trpc.authCallback.useQuery(undefined, { retry: true, retryDelay: 500, }); // Check for errors in the query result if (query.error) { const errData = query.error.data; if (errData?.code === 'UNAUTHORIZED') { router.push('/sign-in'); } else { // Handle other types of errors console.error("An error occurred:", query.error); } } // Continue with other logic based on the query result if (query.data?.success) { router.push(origin ? `/${origin}` : '/dashboard'); }
Its an amazing project. I was confused about the t3 stack but it is the best stack for me now. Trpc and prisma makes backend so much easier. Thanks Josh for such quality content !
Your content is amazing! This helped me a lot to build my first SaaS. You inspired me to code with vigor, based on this video. Although I didn't create an AI SaaS, I used the foundation of the project as a starting point.
This blew me away. First, it's a fully deployable application, the tech stack used is modern, the teaching was clean and clear, it's very in-depth content; very thorough. Then it's free at the same time. Josh, thank you very much. I have a question though, seems react-query has deprecated onsuccess from their UseQuery and ultimately trpc follows. Would there be an updated tutorial to improve on this as I got stuck at that point? Still reading up on my way around though. Nevertheless, thank you, Josh!
This doesn't bode well for the use of TRPC in production applications. Either way, the solution is to use the useEffect hook from React. import { useRouter, useSearchParams } from "next/navigation"; import React, { useEffect } from "react"; import { trpc } from "../_trpc/client"; function Page() { const router = useRouter(); const searchParams = useSearchParams(); const origin = searchParams.get("origin"); const { data, isLoading } = trpc.authCallback.useQuery(undefined); useEffect(() => { if (!isLoading && data) { // User synced router.push(origin ? `/${origin}` : "/dashboard"); } }, [data, isLoading, origin, router]); } export default Page;
I was not getting an error for using namespace though I am using the free version of pinecone, I am getting an error for pineconeIndex in core.ts and importing PineconeClient in pinecone.ts. Is there any fix for this? There is no data reflected on my pinecone database. I am stuck here for days
At 4:58:30 you might face an upload error, as it might uploading error where you won't be able to see the file uploaded when you try to open it and it will say that the file upload fail. If you face this problem go back to core that ts and modify the existing onUploadComplete to this: .onUploadComplete(async ({ metadata, file }) => { const createdFile = await db.file.create({ data: { key: file.key, name: file.name, userId: metadata.userId, url: file.url, uploadStatus: "PROCESSING", }, }); remember we have changed the url from the aws address to file.url because the aws URL doesn't work and it shows 403 forbidden at the point when I'm working on it. So make this change for URL and you will be able to solve the error. Thanks
did u get it run , I need some queries , I am facing issue that even the pdf file gets uploaded , and is visible but even the page is 1 or 2 page , the chat side still shows pdf too long ,
I don't know whether it's with me or with everyone but, Josh you have made using various technologies extremely difficult here. The order of defining things, using libraries and partial explanation of topics is really creating a barrier for me every time I try to complete it. It's just what I felt. I would really like other opinions too, but only from those who have at least spent 2 hrs completing the coding from this project. Please don't comment if you are just watching it.
Hey Josh thank you for making this video... Quick question brother... The current free tier of pinecone does not support namespace so it makes it difficult to group vectors to a single file. Do you know of any other tool similar to pine cone that provides namespaces on its free tier?
Hello. It is the 9 of November 2023. I am doing this course. I am at 1:31:29 and the code works only if I will create async Page.tsx component and if I will call the getUser function using await. I don't know why. But may be this comment will help somebody
@@hawksgaming1107 getUser is a async method, bcz everytime getUser method is called, kinde make connection with database and fetch the user details, this process needs time, so that's why await is used, hope it helps 💪
Hello developers, for anyone having the issue rendering the pdf file, which it does not show up on screen and the network request return a 403 error, this is how you could resolve it, go to core.ts file and under the onUploadComplete change the url from the modified one to file.url, somehow the url that Josh provided is not working, so go with the file.url instead and remember to delete all the files before retrying because the url of the files is already invalid. Hope this help!!
@@teenageworrior1634 The issue might be with your browser. I get the same issue using Chrome because of the default behavior of the browser when dealing with PDF files; it triggers the download manager instead of displaying it, but even when I change the settings, it does not work. I do not know why, but there is one solution to this issue to my knowledge: using a different browser like Microsoft Edge.
The file.url instead of the Josh url solved the rendering of the file. You saved my mental state. I still have the "Too many pages in PDF" even with small pdfs but probably is another error.
Amazing job Josh! You've been a major help in my learning experience. Imo saving the file after every className would be amazing to show exactly how everything works.
Hello Josh, first of all, I loved the project, so I appreciate your great work. I've been following it, but I'm having an issue with the Pinecone integration. It seems that since you made the video, the way it works has changed a lot. Now, it has a different type of pod, a pod-starter. In your case, you can select the pod-s1, but whenever I try to implement it, I always get an error saying that I exceed the maximum transfer quota. I couldn't find a way to solve it since the documentation doesn't specify how to do this using Lang, as in your video. Besides, I don't understand much about AI things. I wanted to know if you knew of any solution.
I spent a lot of time, but I found a solution for pinecone 1.1.1 and pod type starter. in pinecone.ts: import { Pinecone } from '@pinecone-database/pinecone'; export const pinecone = new Pinecone({ apiKey: process.env.PINECONE_API_KEY!, environment: 'gcp-starter', }); in api>uploadthing>core.ts: ... const pineconeIndex = pinecone.Index('quill'); const embeddings = new OpenAIEmbeddings({ openAIApiKey: process.env.OPENAI_API_KEY, }); await PineconeStore.fromDocuments(pageLevelDocs, embeddings, { pineconeIndex, }); ... that works for me...
@@mitol5549 I really need help. How you fix the type error in pineconeIdex? Type 'Index' is missing the following properties from type 'VectorOperationsApi': _deleteRaw, _delete, delete1Raw, delete1, and 16 more.ts(2740) pinecone.d.ts(8, 5): The expected type comes from property 'pineconeIndex' which is declared here on type 'PineconeLibArgs'
@@mitol5549 I am still getting a typescript error on pineconeIndex. "Type 'Index' is missing the following properties from type 'VectorOperationsApi': _deleteRaw, _delete, delete1Raw, delete1, and 16 more.ts(2740)" EDIT: Nevermind, the code you shared does work. I just had to update langchain to get it to work. I am using: "langchain": "^0.0.172" "@pinecone-database/pinecone": "^1.1.2", I am still able to use the free starter from pinecone.
Hey josh, in 2:04:38, you used onSuccess in the useQuery function but as of now it’s deprecated and cannot be used anymore. Can you suggest a workaround to this? Thanks
I've gotta say, I was excited until the first 2 hours of the video felt like copy pasting classnames. You really have to find a way to avoid that in tutorials. If I could re-design this experience, I'd start with the backend functionality first because its the most exciting part and the main reason why people will pick this up
Hello Josh, Thank you for making this tutorial. Can you also make a tutorial where customers can set custom domains in SaaS (multi-tenant system) in Next.js
thank you so much ;from you effort that tend you to bring us this awesome project as much of knowledge you let us know also understand how nextjs work as a full stack SAAS Plateforme thank you again💻💻💻💻💻💥💥💥💥💥💥💥💥💥🧑💻🧑💻
i get this error related to cors ?????? Access to fetch at 'uploading-prod.s3.us-west-2.amazonaws.com/ebe45169-7581-4016-80ef-a897056151cc-vdhpga.pdf' from origin 'localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Only 30 mins in, but I want to thank you Josh - this is amazing! Love that you actually explain everything you do, unlike 99% of other tutorials on youtube. Please stay that way, much obliged :)
"Excellent video! I'm eager to learn and build an inventory management system using Next.js. Could you please consider creating a tutorial on this topic? Your tutorials are always top-notch, and I believe it would be incredibly beneficial for learners like me. Looking forward to more great content!"
Not surprised. I actually think despite all the hype in the comments that this was a poor tutorial. 40 mins in and it's mostly magic (css hardcoding everywhere). I just keep hearing "I promise, this is the last time", but it's not been the case so far. No depth in explaining what's happening and the alternatives, or even a link to go learn more. Tailwind looks like magic here too. I guess that's a prerequisite and I wish it was mentioned at the start. So far it feels like a "follow after me" guide, rather than a tutorial, which is more of a "teaching" session. Right now, I'm following blindly and that doesn't sit well with me.
Hey Josh, Amazing Lecture bruh. You taught such good concept about Authentication Systems, Next.js. I'm sure you have no idea how good you taught in this lecture. Thank you very very much.
I really appreciate your style. The way you explain things is very clear, which is a significant advantage when learning something new like this. Thank you for this excellent tutorial!
Mate, You seem good lad. I gonna watch and build my own. You are good with it mate! After building my own, I gonna call it MINE! You are doing good mate!!!!! Cheers 🍻
Just discovered your channel, and I must say, you create some of the best content out there! Keep going at it, I will definitely recommend your videos and I will for sure keep watching!
Great job Josh. Love how you add explanations and side comments instead of just writing the code. You are great at teaching man! We will now expect one of these full projects every week 🤣🤣🤣🤣🤣
hey josh you can use ALT + Z to wrap the content and fit accordingly to your vscode width, like you mentioned the className was too big and you were scrolling. thanks for the video! Greate stuff!
"Great video! Looking forward to more tutorials on Next.js projects, especially ones related to inventory management. Your content is always top-notch!"
thanks for this huge effort. A shortcut for you and my fellow foreigners that are using multiple keyboards, Windows key + space quickly changes the keyboard locale :)
I've began working on a lot of Next side-projects for my work, and although I follow a lot of the best practices that I've seen and read up on thus far, this video will cement a lot of things, I'm sure of it. I plan on watching this and re-creating it this weekend, thank you Josh! You and Web Dev Cody are saints 🙏
Thanks a lot! Instead of duplicating PdfRenderer and its state for a fullscreen mode, I would suggest using browser's natvie FullscreenAPI either directly or via libraries like react-fullscreen. This method shares the state between full screen and normal mode and renders selected components without any dialogs/modal windows. Cheers :)
Thanks for this I was about to start a project I wanted to use TRPC but I was waiting for your video since I don't understand the docs the perfect time Thanks so much
In the src/app/auth-callback/page.tsx, this code will never reach the onError function because the retry will never end. You have to set the retry param to a number. Eg: 5. After 5 retries, the onError function will get called. Also, the route path of line 22 is not correct. It should be something like /api/auth/login. For some reason, I had to replace line 22 with that (window.location.href = '/api/auth/login?') to get the login flow work. Thanks a lot of this video. You are an excellent teacher
Thank you for that. It works perfectly now. For those who are struggling, just copy the below code onError: (err) => { if (err.data?.code === 'UNAUTHORIZED') { window.location.href = '/api/auth/login?'; } }, retry: 5,