Skip to content

Instantly share code, notes, and snippets.

@adrianhajdin
Created October 27, 2023 09:18
Show Gist options
  • Save adrianhajdin/4d2500bf5af601bbd9f4f596298d33ac to your computer and use it in GitHub Desktop.
Save adrianhajdin/4d2500bf5af601bbd9f4f596298d33ac to your computer and use it in GitHub Desktop.
Build and Deploy a Full Stack Social Media App | React JS, Appwrite, Tailwind CSS, React Query
export const sidebarLinks = [
{
imgURL: "/assets/icons/home.svg",
route: "/",
label: "Home",
},
{
imgURL: "/assets/icons/wallpaper.svg",
route: "/explore",
label: "Explore",
},
{
imgURL: "/assets/icons/people.svg",
route: "/all-users",
label: "People",
},
{
imgURL: "/assets/icons/bookmark.svg",
route: "/saved",
label: "Saved",
},
{
imgURL: "/assets/icons/gallery-add.svg",
route: "/create-post",
label: "Create Post",
},
];
export const bottombarLinks = [
{
imgURL: "/assets/icons/home.svg",
route: "/",
label: "Home",
},
{
imgURL: "/assets/icons/wallpaper.svg",
route: "/explore",
label: "Explore",
},
{
imgURL: "/assets/icons/bookmark.svg",
route: "/saved",
label: "Saved",
},
{
imgURL: "/assets/icons/gallery-add.svg",
route: "/create-post",
label: "Create",
},
];
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap");
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
* {
@apply box-border list-none p-0 m-0 scroll-smooth;
}
body {
@apply bg-dark-1 text-white min-h-screen font-inter;
}
}
@layer utilities {
/* TYPOGRAPHY */
.h1-bold {
@apply text-[36px] font-bold leading-[140%] tracking-tighter;
}
.h1-semibold {
@apply text-[36px] font-semibold leading-[140%] tracking-tighter;
}
.h2-bold {
@apply text-[30px] font-bold leading-[140%] tracking-tighter;
}
.h3-bold {
@apply text-[24px] font-bold leading-[140%] tracking-tighter;
}
.base-semibold {
@apply text-[16px] font-semibold leading-[140%] tracking-tighter;
}
.base-medium {
@apply text-[16px] font-medium leading-[140%];
}
.base-regular {
@apply text-[16px] font-normal leading-[140%];
}
.body-bold {
@apply text-[18px] font-bold leading-[140%];
}
.body-medium {
@apply text-[18px] font-medium leading-[140%];
}
.small-semibold {
@apply text-[14px] font-semibold leading-[140%] tracking-tighter;
}
.small-medium {
@apply text-[14px] font-medium leading-[140%];
}
.small-regular {
@apply text-[14px] font-normal leading-[140%];
}
.subtle-semibold {
@apply text-[12px] font-semibold leading-[140%];
}
.tiny-medium {
@apply text-[10px] font-medium leading-[140%];
}
/* UTILITIES */
.invert-white {
@apply invert brightness-0 transition;
}
.flex-center {
@apply flex justify-center items-center;
}
.flex-between {
@apply flex justify-between items-center;
}
.flex-start {
@apply flex justify-start items-center;
}
.custom-scrollbar::-webkit-scrollbar {
width: 3px;
height: 3px;
border-radius: 2px;
}
.custom-scrollbar::-webkit-scrollbar-track {
background: #09090a;
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background: #5c5c7b;
border-radius: 50px;
}
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
background: #7878a3;
}
.common-container {
@apply flex flex-col flex-1 items-center gap-10 overflow-scroll py-10 px-5 md:px-8 lg:p-14 custom-scrollbar;
}
/* All Users */
.user-container {
@apply max-w-5xl flex flex-col items-start w-full gap-6 md:gap-9;
}
.user-grid {
@apply w-full grid grid-cols-1 xs:grid-cols-2 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3 gap-7 max-w-5xl;
}
/* Explore */
.explore-container {
@apply flex flex-col flex-1 items-center overflow-scroll py-10 px-5 md:p-14 custom-scrollbar;
}
.explore-inner_container {
@apply max-w-5xl flex flex-col items-center w-full gap-6 md:gap-9;
}
.explore-search {
@apply h-12 bg-dark-4 border-none placeholder:text-light-4 focus-visible:ring-0 focus-visible:ring-offset-0 ring-offset-0 !important;
}
/* Home */
.home-container {
@apply flex flex-col flex-1 items-center gap-10 overflow-scroll py-10 px-5 md:px-8 lg:p-14 custom-scrollbar;
}
.home-posts {
@apply max-w-screen-sm flex flex-col items-center w-full gap-6 md:gap-9;
}
.home-creators {
@apply hidden xl:flex flex-col w-72 2xl:w-465 px-6 py-10 gap-10 overflow-scroll custom-scrollbar;
}
/* Post Details */
.post_details-container {
@apply flex flex-col flex-1 gap-10 overflow-scroll py-10 px-5 md:p-14 custom-scrollbar items-center;
}
.post_details-card {
@apply bg-dark-2 w-full max-w-5xl rounded-[30px] flex-col flex xl:flex-row border border-dark-4 xl:rounded-l-[24px];
}
.post_details-img {
@apply h-80 lg:h-[480px] xl:w-[48%] rounded-t-[30px] xl:rounded-l-[24px] xl:rounded-tr-none object-cover p-5 bg-dark-1;
}
.post_details-info {
@apply bg-dark-2 flex flex-col gap-5 lg:gap-7 flex-1 items-start p-8 rounded-[30px];
}
.post_details-delete_btn {
@apply p-0 flex gap-3 hover:bg-transparent hover:text-light-1 text-light-1 small-medium lg:base-medium;
}
/* Profile */
.profile-container {
@apply flex flex-col items-center flex-1 gap-10 overflow-scroll py-10 px-5 md:p-14 custom-scrollbar;
}
.profile-inner_container {
@apply flex items-center md:mb-8 xl:items-start gap-8 flex-col xl:flex-row relative max-w-5xl w-full;
}
.profile-tab {
@apply flex-center gap-3 py-4 w-48 bg-dark-2 transition flex-1 xl:flex-initial;
}
/* Saved */
.saved-container {
@apply flex flex-col flex-1 items-center gap-10 overflow-scroll py-10 px-5 md:p-14 custom-scrollbar;
}
/* Bottom bar */
.bottom-bar {
@apply z-50 flex-between w-full sticky bottom-0 rounded-t-[20px] bg-dark-2 px-5 py-4 md:hidden;
}
/* File uploader */
.file_uploader-img {
@apply h-80 lg:h-[480px] w-full rounded-[24px] object-cover object-top;
}
.file_uploader-label {
@apply text-light-4 text-center small-regular w-full p-4 border-t border-t-dark-4;
}
.file_uploader-box {
@apply flex-center flex-col p-7 h-80 lg:h-[612px];
}
/* Grid Post List */
.grid-container {
@apply w-full grid grid-cols-1 sm:grid-cols-2 md:grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-7 max-w-5xl;
}
.grid-post_link {
@apply flex rounded-[24px] border border-dark-4 overflow-hidden cursor-pointer w-full h-full;
}
.grid-post_user {
@apply absolute bottom-0 p-5 flex-between w-full bg-gradient-to-t from-dark-3 to-transparent rounded-b-[24px] gap-2;
}
/* Left sidebar */
.leftsidebar {
@apply hidden md:flex px-6 py-10 flex-col justify-between min-w-[270px] bg-dark-2;
}
.leftsidebar-link {
@apply rounded-lg base-medium hover:bg-primary-500 transition;
}
/* Post Card */
.post-card {
@apply bg-dark-2 rounded-3xl border border-dark-4 p-5 lg:p-7 w-full max-w-screen-sm;
}
.post-card_img {
@apply h-64 xs:h-[400px] lg:h-[450px] w-full rounded-[24px] object-cover mb-5;
}
/* Topbar */
.topbar {
@apply sticky top-0 z-50 md:hidden bg-dark-2 w-full;
}
/* User card */
.user-card {
@apply flex-center flex-col gap-4 border border-dark-4 rounded-[20px] px-5 py-8;
}
}
@layer components {
/* SHADCN COMPONENTS */
/* Form */
.shad-form_label {
@apply text-white !important;
}
.shad-form_message {
@apply text-red !important;
}
.shad-input {
@apply h-12 bg-dark-4 border-none placeholder:text-light-4 focus-visible:ring-1 focus-visible:ring-offset-1 ring-offset-light-3 !important;
}
.shad-textarea {
@apply h-36 bg-dark-3 rounded-xl border-none focus-visible:ring-1 focus-visible:ring-offset-1 ring-offset-light-3 !important;
}
/* Button */
.shad-button_primary {
@apply bg-primary-500 hover:bg-primary-500 text-light-1 flex gap-2 !important;
}
.shad-button_dark_4 {
@apply h-12 bg-dark-4 px-5 text-light-1 flex gap-2 !important;
}
.shad-button_ghost {
@apply flex gap-4 items-center justify-start hover:bg-transparent hover:text-white !important;
}
}
https://drive.google.com/file/d/13_7FofRAC3wARqPtAVPi53QNJJRd5RH_/view?usp=sharing
export enum QUERY_KEYS {
// AUTH KEYS
CREATE_USER_ACCOUNT = "createUserAccount",
// USER KEYS
GET_CURRENT_USER = "getCurrentUser",
GET_USERS = "getUsers",
GET_USER_BY_ID = "getUserById",
// POST KEYS
GET_POSTS = "getPosts",
GET_INFINITE_POSTS = "getInfinitePosts",
GET_RECENT_POSTS = "getRecentPosts",
GET_POST_BY_ID = "getPostById",
GET_USER_POSTS = "getUserPosts",
GET_FILE_PREVIEW = "getFilePreview",
// SEARCH KEYS
SEARCH_POSTS = "getSearchPosts",
}
/** @type {import('tailwindcss').Config} */
const defaultTheme = require('tailwindcss/defaultTheme')
module.exports = {
darkMode: ['class'],
content: [
'./pages/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./src/**/*.{ts,tsx}',
],
theme: {
container: {
center: true,
padding: '2rem',
screens: {
'2xl': '1400px',
},
},
extend: {
colors: {
'primary-500': '#877EFF',
'primary-600': '#5D5FEF',
'secondary-500': '#FFB620',
'off-white': '#D0DFFF',
'red': '#FF5A5A',
'dark-1': '#000000',
'dark-2': '#09090A',
'dark-3': '#101012',
'dark-4': '#1F1F22',
'light-1': '#FFFFFF',
'light-2': '#EFEFEF',
'light-3': '#7878A3',
'light-4': '#5C5C7B',
},
screens: {
'xs': '480px',
},
width: {
'420': '420px',
'465': '465px',
},
fontFamily: {
inter: ['Inter', 'sans-serif'],
},
keyframes: {
'accordion-down': {
from: { height: 0 },
to: { height: 'var(--radix-accordion-content-height)' },
},
'accordion-up': {
from: { height: 'var(--radix-accordion-content-height)' },
to: { height: 0 },
},
},
animation: {
'accordion-down': 'accordion-down 0.2s ease-out',
'accordion-up': 'accordion-up 0.2s ease-out',
},
},
},
plugins: [require('tailwindcss-animate')],
};
export type INavLink = {
imgURL: string;
route: string;
label: string;
};
export type IUpdateUser = {
userId: string;
name: string;
bio: string;
imageId: string;
imageUrl: URL | string;
file: File[];
};
export type INewPost = {
userId: string;
caption: string;
file: File[];
location?: string;
tags?: string;
};
export type IUpdatePost = {
postId: string;
caption: string;
imageId: string;
imageUrl: URL;
file: File[];
location?: string;
tags?: string;
};
export type IUser = {
id: string;
name: string;
username: string;
email: string;
imageUrl: string;
bio: string;
};
export type INewUser = {
name: string;
email: string;
username: string;
password: string;
};
import { useEffect, useState } from "react";
// https://codesandbox.io/s/react-query-debounce-ted8o?file=/src/useDebounce.js
export default function useDebounce<T>(value: T, delay: number): T {
// State and setters for debounced value
const [debouncedValue, setDebouncedValue] = useState<T>(value);
useEffect(() => {
// Update debounced value after delay
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
// Cancel the timeout if value changes (also on delay change or unmount)
// This is how we prevent debounced value from updating if value is changed ...
// .. within the delay period. Timeout gets cleared and restarted.
return () => {
clearTimeout(handler);
};
}, [value, delay]); // Only re-call effect if value or delay changes
return debouncedValue;
}
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
export const convertFileToUrl = (file: File) => URL.createObjectURL(file);
export function formatDateString(dateString: string) {
const options: Intl.DateTimeFormatOptions = {
year: "numeric",
month: "short",
day: "numeric",
};
const date = new Date(dateString);
const formattedDate = date.toLocaleDateString("en-US", options);
const time = date.toLocaleTimeString([], {
hour: "numeric",
minute: "2-digit",
});
return `${formattedDate} at ${time}`;
}
//
export const multiFormatDateString = (timestamp: string = ""): string => {
const timestampNum = Math.round(new Date(timestamp).getTime() / 1000);
const date: Date = new Date(timestampNum * 1000);
const now: Date = new Date();
const diff: number = now.getTime() - date.getTime();
const diffInSeconds: number = diff / 1000;
const diffInMinutes: number = diffInSeconds / 60;
const diffInHours: number = diffInMinutes / 60;
const diffInDays: number = diffInHours / 24;
switch (true) {
case Math.floor(diffInDays) >= 30:
return formatDateString(timestamp);
case Math.floor(diffInDays) === 1:
return `${Math.floor(diffInDays)} day ago`;
case Math.floor(diffInDays) > 1 && diffInDays < 30:
return `${Math.floor(diffInDays)} days ago`;
case Math.floor(diffInHours) >= 1:
return `${Math.floor(diffInHours)} hours ago`;
case Math.floor(diffInMinutes) >= 1:
return `${Math.floor(diffInMinutes)} minutes ago`;
default:
return "Just now";
}
};
export const checkIsLiked = (likeList: string[], userId: string) => {
return likeList.includes(userId);
};
@00shivani
Copy link

Hi, Im when i try to sign up a new user, im getting an error that says password_error

but the password i entered is at least 8 characters. any suggestions?

Thanks in advance

it says it shouldnt be one of the commonly used passwords, so maybe try something unique?

@mizzath2003
Copy link

image_2023-12-11_121105752

Does anyone know what's the reason for this error. This is the error i am getting when saving a post. when i go save a post from appwrite manually then it shows in the web and the delete save also works. but when i try to save a post from the site i am getting this error. Has anyone come across this error or have any solution

@mizzath2003
Copy link

image

I think i am having an issue in this part. But i am having trouble to find out what exactly it is does anyone know

@Taqi27
Copy link

Taqi27 commented Dec 11, 2023

Hi, Im when i try to sign up a new user, im getting an error that says password_error

but the password i entered is at least 8 characters. any suggestions?

Thanks in advance

nvm i figured it out. 😆

Hi there Can you tell me what was the problem as I am stuck on same problem it would be very helpful..

@mizzath2003
Copy link

image

I think i am having an issue in this part. But i am having trouble to find out what exactly it is does anyone know

image

problem solved as there was a typo i had used "user" instead of "users"

@lilman109
Copy link

@00shivani
Thanks, I figured it out.

@Taqi27
For me, i was passing in the arguments out of order for the createUserAccount's account.create function in api.ts.

export const createUserAccount = async (user: INewUser) => {
  try {
    const newAccount = account.create(
      ID.unique(),
      user.email,
      user.password,
      user.name,
    );
...
}

such a careless mistake on my part

@ghazalaqamar
Copy link

hhj
hello
im having this error 404 database not found. i have already created database in appwrite. can someone help me with this.

@mizzath2003
Copy link

mizzath2003 commented Dec 13, 2023

hhj hello im having this error 404 database not found. i have already created database in appwrite. can someone help me with this.

is the database key correct?

@TassuAgarwal
Copy link

TassuAgarwal commented Dec 13, 2023

Screenshot 2023-12-13 230346

Please help

@dnyanugarule
Copy link

where i get images means where the zip folder located

@HerbertNtim
Copy link

getting this issue image anybody getting the same ? or anybody has bg-dark-1 code ?

Hi checkout @41:56 , he resolves this

U need to update your tailwindcss config with the github gist

@HerbertNtim
Copy link

Screenshot 2023-12-13 230346

Please help

may be it is from your imports and how you declare variables using your imports.
example: using the authcontext
import { useUserContext } from "@/context/AuthContext"
// using the context api
const { user } = useUserContext()

see i destructure it if not you have issue with using the properties. I hope this helps?

@HerbertNtim
Copy link

where i get images means where the zip folder located

Here is the link
https://drive.google.com/file/d/13_7FofRAC3wARqPtAVPi53QNJJRd5RH_/view?usp=sharing

@yanlimabarbosa
Copy link

image

AppwriteException: User (role: guests) missing scope (account)

what should i do?? please helpp

@Animesh-X
Copy link

Animesh-X commented Dec 19, 2023

Screenshot 2023-12-19 at 5 19 34 PM This is error i am getting when I try to create a post. I have followed along the code. I think the error is in Onsubmit or useCreatePost This is the useCreatePost function `export const useCreatePost = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: (post: INewPost) => createPost(post), onSuccess: () => { queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.GET_RECENT_POSTS], }); }, }); };`

Screenshot 2023-12-19 at 5 22 22 PM

Screenshot 2023-12-19 at 5 22 40 PM

@Shashikiran200212
Copy link

is anyone facing trouble in deployment ?

@akash-suklabaidya
Copy link

akash-suklabaidya commented Dec 19, 2023

image

AppwriteException: User (role: guests) missing scope (account)

what should i do?? please helpp

hey, did you fix the error? If yes, please help me

@Shashikiran200212
Copy link

Shashikiran200212 commented Dec 19, 2023 via email

@risky30
Copy link

risky30 commented Dec 19, 2023

image

AppwriteException: User (role: guests) missing scope (account)

what should i do?? please helpp

Same Error. Did anyone fix it so far ?

@yanlimabarbosa
Copy link

@risky30
@akashsb18

AppwriteException: User (role: guests) missing scope (account)
what should i do?? please helpp

hey, did you fix the error? If yes, please help me

I fixed it, the error wasnt on the code itself but on appwrite configuration, all should have permissions to any to create, read, update and delete, but the "saves" wasnt configurated, I hope u could understand

@will-frankland
Copy link

will-frankland commented Dec 19, 2023

Has anyone come across this error:

Query data cannot be undefined. Please make sure to return a value other than undefined from your query function. Affected query key: ["getPostById","post.$id"]

I've rewatched the video multiple times and cannot get the edit function to work. It populates an empty post.

When I get to the point of console.logging the imageUrl it is undefined.

@risky30
Copy link

risky30 commented Dec 20, 2023

@risky30 @akashsb18

AppwriteException: User (role: guests) missing scope (account)
what should i do?? please helpp

hey, did you fix the error? If yes, please help me

I fixed it, the error wasnt on the code itself but on appwrite configuration, all should have permissions to any to create, read, update and delete, but the "saves" wasnt configurated, I hope u could understand

My Saves is configurated like Users and Posts but still got the same error........

@ghazalaqamar
Copy link

@risky30 @akashsb18

AppwriteException: User (role: guests) missing scope (account)
what should i do?? please helpp

hey, did you fix the error? If yes, please help me

I fixed it, the error wasnt on the code itself but on appwrite configuration, all should have permissions to any to create, read, update and delete, but the "saves" wasnt configurated, I hope u could understand

My Saves is configurated like Users and Posts but still got the same error........

hey. try checking if the spelling of 'posts' 'users' 'saves' are same in both .env.local and config.ts. Also check if you have copied the correct ids to .env.local from appwrite.

image
image

@akash-suklabaidya
Copy link

@risky30 @akashsb18

AppwriteException: User (role: guests) missing scope (account)
what should i do?? please helpp

hey, did you fix the error? If yes, please help me

I fixed it, the error wasnt on the code itself but on appwrite configuration, all should have permissions to any to create, read, update and delete, but the "saves" wasnt configurated, I hope u could understand

My Saves is configurated like Users and Posts but still got the same error........

hey. try checking if the spelling of 'posts' 'users' 'saves' are same in both .env.local and config.ts. Also check if you have copied the correct ids to .env.local from appwrite.

image image

I've tried every possible solution but still could't fix it .

@risky30
Copy link

risky30 commented Dec 21, 2023

Has anyone come across this error:

Query data cannot be undefined. Please make sure to return a value other than undefined from your query function. Affected query key: ["getPostById","post.$id"]

I've rewatched the video multiple times and cannot get the edit function to work. It populates an empty post.

When I get to the point of console.logging the imageUrl it is undefined.

send pictures of the errors

@Rahul-Roy-Hub
Copy link

Screenshot (351)

Get error in getAccount, getCurrentUser, checkAuthUser

@NandithaKumar
Copy link

$ npx shadcn-ui@latest init
FetchError: request to https://ui.shadcn.com/registry/styles/index.json failed, reason: unable to get local issuer certificate
at ClientRequest. (file:///C:/Users/nk95/AppData/Local/npm-cache/_npx/125ee17d583c4e03/node_modules/node-fetch/src/index.js:108:11)
at ClientRequest.emit (node:events:517:28)
at TLSSocket.socketErrorListener (node:_http_client:501:9)
at TLSSocket.emit (node:events:517:28)
at emitErrorNT (node:internal/streams/destroy:151:8)
at emitErrorCloseNT (node:internal/streams/destroy:116:3)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
type: 'system',
errno: 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY',
code: 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY',
erroredSysCall: undefined
}
Failed to fetch styles from registry.

Hi there, any solution to solve this issue...tried with different network didn't work

@facuCast123
Copy link

Did anyone else have this error happen when doing the Topbar component? My AuthContext.tsx and Types folder are the same as in his repo. I don't know where the problem is.

PropertyError1

@fingineer
Copy link

fingineer commented Dec 23, 2023

Screenshot 2023-12-23 appwrite error
can anybody please respond to this error. cheers

@risky30
Copy link

risky30 commented Dec 23, 2023

Did anyone else have this error happen when doing the Topbar component? My AuthContext.tsx and Types folder are the same as in his repo. I don't know where the problem is.

PropertyError1

let's see your whole topbar and AuthContext

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment