
ที่เก็บนี้มีรหัสที่สอดคล้องกับการสอนเชิงลึกที่มีอยู่ในช่อง YouTube ของเรา JavaScript Mastery
หากคุณชอบการเรียนรู้ด้วยภาพนี่เป็นแหล่งข้อมูลที่สมบูรณ์แบบสำหรับคุณ ทำตามการสอนของเราเพื่อเรียนรู้วิธีการสร้างโครงการเช่นขั้นตอนเหล่านี้ในลักษณะที่เป็นมิตรกับผู้เริ่มต้น!

โคลนนิ่งเลี้ยงลูกด้วยสแต็กเต็มรูปแบบที่พัฒนาขึ้นโดยใช้ Next.js, GraphQL, Auth Auth, TypeScript และ TailwindCSS ถัดไปมีคุณสมบัติทั้งหมดที่จำเป็นทั้งหมดของการเลี้ยงลูกจากการแบ่งปันและการจัดแสดงโครงการ
หากคุณกำลังเริ่มต้นและต้องการความช่วยเหลือหรือเผชิญกับข้อบกพร่องใด ๆ ให้เข้าร่วมชุมชน Discord ของเรากับสมาชิกมากกว่า 27K+ เป็นสถานที่ที่ผู้คนช่วยเหลือซึ่งกันและกัน

โฮมเพจการออกแบบที่ทันสมัย : คุณสมบัติการออกแบบที่สะอาดและทันสมัยคล้ายกับ Dribbble พร้อมอินเทอร์เฟซที่ดึงดูดสายตาซึ่งแสดงตัวอย่างโครงการและการนำทาง
การเรียกดูและการปนเปื้อน : เรียกดูโครงการที่แตกต่างกันกรองตามหมวดหมู่และสัมผัสกับการแบ่งแยกที่ราบรื่นสำหรับการสำรวจข้อมูลที่ราบรื่น
ระบบการรับรองความถูกต้องและการอนุมัติ : ระบบการตรวจสอบสิทธิ์และการอนุมัติที่ใช้งานได้อย่างสมบูรณ์ช่วยให้ผู้ใช้สามารถเข้าสู่ระบบอย่างปลอดภัยโดยใช้ JWT และ Google Authentication
สร้างหน้าโพสต์ : จัดเตรียมพื้นที่เฉพาะสำหรับผู้ใช้เพื่อแบ่งปันโครงการของพวกเขากับชุมชน มันมีฟิลด์สำหรับรายละเอียดโครงการรูปภาพและข้อมูลอื่น ๆ ที่เกี่ยวข้อง
รายละเอียดโครงการและโครงการที่เกี่ยวข้อง : มุมมองโดยละเอียดพร้อมฟังก์ชั่นโครงการที่เกี่ยวข้องทำให้ผู้ใช้สามารถสำรวจโครงการเพิ่มเติมภายในหมวดหมู่หรือธีมเดียวกัน
แก้ไขและอัปโหลดรูปภาพอีกครั้ง : ผู้ใช้มีความสามารถในการแก้ไขโครงการที่สร้างขึ้นก่อนหน้านี้รวมถึงความสามารถในการอัปโหลดภาพจากอุปกรณ์ของพวกเขาไปยังคลาวด์เพื่ออัปเดต
ลบโครงการ : ฟังก์ชั่นการลบทำให้การลบโครงการง่ายขึ้นด้วยกระบวนการคลิกเดียวทำให้ประสบการณ์ผู้ใช้มีความคล่องตัว
หน้าโปรไฟล์ผู้ใช้สไตล์พอร์ตโฟลิโอ : หน้าโปรไฟล์ผู้ใช้ใช้เค้าโครงสไตล์พอร์ตโฟลิโอแสดงโครงการของผู้ใช้พร้อมกับโปรไฟล์โครงการของผู้ใช้รายอื่นเพื่อการสำรวจอย่างง่ายดาย
เส้นทาง API แบ็กเอนด์ : เส้นทาง API แบ็กเอนด์สำหรับการจัดการการจัดการโทเค็น JWT เพื่อการตรวจสอบความปลอดภัยที่ปลอดภัยและการอัปโหลดรูปภาพรองรับการรวมเข้ากับส่วนหน้าอย่างราบรื่น
และอีกมากมายรวมถึงสถาปัตยกรรมรหัสและความสามารถในการนำกลับมาใช้ใหม่
ทำตามขั้นตอนเหล่านี้เพื่อตั้งค่าโครงการในเครื่องบนเครื่องของคุณ
ข้อกำหนดเบื้องต้น
ตรวจสอบให้แน่ใจว่าคุณติดตั้งต่อไปนี้บนเครื่องของคุณ:
การโคลนนิ่งที่เก็บ
git clone https://github.com/adrianhajdin/project_nextjs13_flexibble.git
cd project_nextjs13_flexibbleการติดตั้ง
ติดตั้งการพึ่งพาโครงการโดยใช้ NPM:
npm installตั้งค่าตัวแปรสภาพแวดล้อม
สร้างไฟล์ใหม่ชื่อ .env ในรูทของโครงการของคุณและเพิ่มเนื้อหาต่อไปนี้:
GOOGLE_CLIENT_ID =
GOOGLE_CLIENT_SECRET =
NEXTAUTH_URL =
NEXTAUTH_SECRET =
CLOUDINARY_NAME =
CLOUDINARY_KEY =
CLOUDINARY_SECRET =
GRAFBASE_API_URL =
GRAFBASE_API_KEY =แทนที่ค่าตัวยึดตำแหน่งด้วยข้อมูลประจำตัวจริงของคุณ คุณสามารถรับข้อมูลรับรองเหล่านี้ได้โดยการลงทะเบียนบนเว็บไซต์ที่เกี่ยวข้องจาก Google Cloud, Cloudinary และ Grafbase
สำหรับความลับของการรับรองความถูกต้องถัดไปคุณสามารถสร้างความลับแบบสุ่มโดยใช้ crytool
ดำเนินโครงการ
npm run devเปิด http: // localhost: 3000 ในเบราว์เซอร์ของคุณเพื่อดูโครงการ
common.types.ts import { User , Session } from 'next-auth'
export type FormState = {
title : string ;
description : string ;
image : string ;
liveSiteUrl : string ;
githubUrl : string ;
category : string ;
} ;
export interface ProjectInterface {
title : string ;
description : string ;
image : string ;
liveSiteUrl : string ;
githubUrl : string ;
category : string ;
id : string ;
createdBy : {
name : string ;
email : string ;
avatarUrl : string ;
id : string ;
} ;
}
export interface UserProfile {
id : string ;
name : string ;
email : string ;
description : string | null ;
avatarUrl : string ;
githubUrl : string | null ;
linkedinUrl : string | null ;
projects : {
edges : { node : ProjectInterface } [ ] ;
pageInfo : {
hasPreviousPage : boolean ;
hasNextPage : boolean ;
startCursor : string ;
endCursor : string ;
} ;
} ;
}
export interface SessionInterface extends Session {
user : User & {
id : string ;
name : string ;
email : string ;
avatarUrl : string ;
} ;
}
export interface ProjectForm {
title : string ;
description : string ;
image : string ;
liveSiteUrl : string ;
githubUrl : string ;
category : string ;
}constants.ts export const NavLinks = [
{ href : '/' , key : 'Inspiration' , text : 'Inspiration' } ,
{ href : '/' , key : 'Find Projects' , text : 'Find Projects' } ,
{ href : '/' , key : 'Learn Development' , text : 'Learn Development' } ,
{ href : '/' , key : 'Career Advancement' , text : 'Career Advancement' } ,
{ href : '/' , key : 'Hire Developers' , text : 'Hire Developers' }
] ;
export const categoryFilters = [
"Frontend" ,
"Backend" ,
"Full-Stack" ,
"Mobile" ,
"UI/UX" ,
"Game Dev" ,
"DevOps" ,
"Data Science" ,
"Machine Learning" ,
"Cybersecurity" ,
"Blockchain" ,
"E-commerce" ,
"Chatbots"
]
export const footerLinks = [
{
title : 'For developers' ,
links : [
'Go Pro!' ,
'Explore development work' ,
'Development blog' ,
'Code podcast' ,
'Open-source projects' ,
'Refer a Friend' ,
'Code of conduct' ,
] ,
} ,
{
title : 'Hire developers' ,
links : [
'Post a job opening' ,
'Post a freelance project' ,
'Search for developers' ,
] ,
} ,
{
title : 'Brands' ,
links : [
'Advertise with us' ,
] ,
} ,
{
title : 'Company' ,
links : [
'About' ,
'Careers' ,
'Support' ,
'Media kit' ,
'Testimonials' ,
'API' ,
'Terms of service' ,
'Privacy policy' ,
'Cookie policy' ,
] ,
} ,
{
title : 'Directories' ,
links : [
'Development jobs' ,
'Developers for hire' ,
'Freelance developers for hire' ,
'Tags' ,
'Places' ,
] ,
} ,
{
title : 'Development assets' ,
links : [
'Code Marketplace' ,
'GitHub Marketplace' ,
'NPM Registry' ,
'Packagephobia' ,
] ,
} ,
{
title : 'Development Resources' ,
links : [
'Freelancing' ,
'Development Hiring' ,
'Development Portfolio' ,
'Development Education' ,
'Creative Process' ,
'Development Industry Trends' ,
] ,
} ,
] ;globals.css @import url ( "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" );
@tailwind base;
@tailwind components;
@tailwind utilities;
* {
margin : 0 ;
padding : 0 ;
box-sizing : border-box;
}
body {
font-family : Inter;
}
. flexCenter {
@apply flex justify-center items-center;
}
. flexBetween {
@apply flex justify-between items-center;
}
. flexStart {
@apply flex items-center justify-start;
}
. text-small {
@apply text-sm font-medium;
}
. paddings {
@apply lg:px-20 py-6 px-5;
}
:: -webkit-scrollbar {
width : 5 px ;
height : 4 px ;
}
:: -webkit-scrollbar-thumb {
background : # 888 ;
border-radius : 12 px ;
}
. modal-head-text {
@apply md:text-5xl text-3xl font-extrabold text-left max-w-5xl w-full;
}
. no-result-text {
@apply w-full text-center my-10 px-2;
}
/* Project Details */
. user-actions_section {
@apply fixed max-md:hidden flex gap-4 flex-col right-10 top-20;
}
. user-info {
@apply flex flex-wrap whitespace-nowrap text-sm font-normal gap-2 w-full;
}
/* Home */
. projects-grid {
@apply grid xl:grid-cols-4 md:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-10 mt-10 w-full;
}
/* Project Actions */
. edit-action_btn {
@apply p-3 text-gray-100 bg-light-white-400 rounded-lg text-sm font-medium;
}
. delete-action_btn {
@apply p-3 text-gray-100 hover:bg-red-600 rounded-lg text-sm font-medium;
}
/* Related Project Card */
. related_project-card {
@apply flex-col rounded-2xl min-w-[ 210 px ] min-h-[ 197 px ];
}
. related_project-card_title {
@apply justify-end items-end w-full h-1/3 bg-gradient-to-b from-transparent to-black/50 rounded-b-2xl gap-2 absolute bottom-0 right-0 font-semibold text-lg text-white p-4;
}
. related_projects-grid {
@apply grid xl:grid-cols-4 md:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-8 mt-5;
}
/* Custom Menu */
. custom_menu-btn {
@apply gap-4 w-full rounded-md bg-light-white-100 p-4 text-base outline-none capitalize;
}
. custom_menu-items {
@apply flex-col absolute left-0 mt-2 xs:min-w-[ 300 px ] w-fit max-h-64 origin-top-right rounded-xl bg-white border border-nav-border shadow-menu overflow-y-auto;
}
. custom_menu-item {
@apply text-left w-full px-5 py-2 text-sm hover:bg-light-white-100 self-start whitespace-nowrap capitalize;
}
/* Footer */
. footer {
@apply flex-col paddings w-full gap-20 bg-light-white;
}
. footer_copyright {
@apply max-sm:flex-col w-full text-sm font-normal;
}
. footer_column {
@apply flex-1 flex flex-col gap-3 text-sm min-w-max;
}
/* Form Field */
. form_field-input {
@apply w-full outline-0 bg-light-white-100 rounded-xl p-4;
}
/* Modal */
. modal {
@apply fixed z-10 left-0 right-0 top-0 bottom-0 mx-auto bg-black/80;
}
. modal_wrapper {
@apply flex justify-start items-center flex-col absolute h-[ 95 % ] w-full bottom-0 bg-white rounded-t-3xl lg:px-40 px-8 pt-14 pb-72 overflow-auto;
}
/* Navbar */
. navbar {
@apply py-5 px-8 border-b border-nav-border gap-4;
}
/* Profile Menu */
. profile_menu-items {
@apply flex-col absolute right-1/2 translate-x-1/2 mt-3 p-7 sm:min-w-[ 300 px ] min-w-max rounded-xl bg-white border border-nav-border shadow-menu;
}
/* Profile Card */
. profile_card-title {
@apply justify-end items-end w-full h-1/3 bg-gradient-to-b from-transparent to-black/50 rounded-b-2xl gap-2 absolute bottom-0 right-0 font-semibold text-lg text-white p-4;
}
/* Project Form */
. form {
@apply flex-col w-full lg:pt-24 pt-12 gap-10 text-lg max-w-5xl mx-auto;
}
. form_image-container {
@apply w-full lg:min-h-[ 400 px ] min-h-[ 200 px ] relative;
}
. form_image-label {
@apply z-10 text-center w-full h-full p-20 text-gray-100 border-2 border-gray-50 border-dashed;
}
. form_image-input {
@apply absolute z-30 w-full opacity-0 h-full cursor-pointer;
}
/* Profile Projects */
. profile_projects {
@apply grid xl:grid-cols-4 md:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-8 mt-5;
}graphqlQueriesAndMutations.ts export const createProjectMutation = `
mutation CreateProject($input: ProjectCreateInput!) {
projectCreate(input: $input) {
project {
id
title
description
createdBy {
email
name
}
}
}
}
` ;
export const updateProjectMutation = `
mutation UpdateProject($id: ID!, $input: ProjectUpdateInput!) {
projectUpdate(by: { id: $id }, input: $input) {
project {
id
title
description
createdBy {
email
name
}
}
}
}
` ;
export const deleteProjectMutation = `
mutation DeleteProject($id: ID!) {
projectDelete(by: { id: $id }) {
deletedId
}
}
` ;
export const createUserMutation = `
mutation CreateUser($input: UserCreateInput!) {
userCreate(input: $input) {
user {
name
email
avatarUrl
description
githubUrl
linkedinUrl
id
}
}
}
` ;
export const projectsQuery = `
query getProjects($category: String, $endCursor: String) {
projectSearch(first: 8, after: $endCursor, filter: {category: {eq: $category}}) {
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
edges {
node {
title
githubUrl
description
liveSiteUrl
id
image
category
createdBy {
id
email
name
avatarUrl
}
}
}
}
}
` ;
export const getProjectByIdQuery = `
query GetProjectById($id: ID!) {
project(by: { id: $id }) {
id
title
description
image
liveSiteUrl
githubUrl
category
createdBy {
id
name
email
avatarUrl
}
}
}
` ;
export const getUserQuery = `
query GetUser($email: String!) {
user(by: { email: $email }) {
id
name
email
avatarUrl
description
githubUrl
linkedinUrl
}
}
` ;
export const getProjectsOfUserQuery = `
query getUserProjects($id: ID!, $last: Int = 4) {
user(by: { id: $id }) {
id
name
email
description
avatarUrl
githubUrl
linkedinUrl
projects(last: $last) {
edges {
node {
id
title
image
}
}
}
}
}
` ;ProfileMenu.tsx "use client"
import Link from "next/link" ;
import Image from "next/image" ;
import { signOut } from "next-auth/react" ;
import { Fragment , useState } from "react" ;
import { Menu , Transition } from "@headlessui/react" ;
import { SessionInterface } from "@/common.types" ;
const ProfileMenu = ( { session } : { session : SessionInterface } ) => {
const [ openModal , setOpenModal ] = useState ( false ) ;
return (
< div className = "flexCenter z-10 flex-col relative" >
< Menu as = "div" >
< Menu . Button className = "flexCenter" onMouseEnter = { ( ) => setOpenModal ( true ) } >
{ session ?. user ?. image && (
< Image
src = { session . user . image }
width = { 40 }
height = { 40 }
className = "rounded-full"
alt = "user profile image"
/ >
) }
< / Menu . Button >
< Transition
show = { openModal }
as = { Fragment }
enter = "transition ease-out duration-200"
enterFrom = "transform opacity-0 scale-95"
enterTo = "transform opacity-100 scale-100"
leave = "transition ease-in duration-75"
leaveFrom = "transform opacity-100 scale-100"
leaveTo = "transform opacity-0 scale-95"
>
< Menu . Items
static
className = "flexStart profile_menu-items"
onMouseLeave = { ( ) => setOpenModal ( false ) }
>
< div className = "flex flex-col items-center gap-y-4" >
{ session ? . user ?. image && (
< Image
src = { session ? . user ? . image }
className = "rounded-full"
width = { 80 }
height = { 80 }
alt = "profile Image"
/ >
) }
< p className = "font-semibold" > { session ? . user ?. name } < / p>
< / div >
< div className = "flex flex-col gap-3 pt-10 items-start w-full" >
< Menu . Item >
< Link href = { `/profile/${ session ? . user ? . id } `} className="text-sm">Work Preferences</Link>
</Menu.Item>
<Menu.Item>
<Link href={` / profile / $ { session ?. user ?. id } `} className="text-sm">Settings</Link>
</Menu.Item>
<Menu.Item>
<Link href={` / profile / $ { session ?. user ?. id } ` } className = "text-sm" > Profile < / Link>
< / Menu.Item>
< / div >
< div className = "w-full flexStart border-t border-nav-border mt-5 pt-5" >
< Menu . Item >
< button type = "button" className = "text-sm" onClick = { ( ) => signOut ( ) } >
Sign out
< / button>
< / Menu.Item>
< / div >
< / Menu . Items >
< / Transition >
< / Menu >
< / div >
)
}
export default ProfileMenuProfilePage.tsx import { ProjectInterface , UserProfile } from '@/common.types'
import Image from 'next/image'
import Link from 'next/link'
import Button from "./Button" ;
import ProjectCard from './ProjectCard' ;
type Props = {
user : UserProfile ;
}
const ProfilePage = ( { user } : Props ) => (
< section className = 'flexCenter flex-col max-w-10xl w-full mx-auto paddings' >
< section className = "flexBetween max-lg:flex-col gap-10 w-full" >
< div className = 'flex items-start flex-col w-full' >
< Image src = { user ? . avatarUrl } width = { 100 } height = { 100 } className = "rounded-full" alt = "user image" / >
< p className = "text-4xl font-bold mt-10" > { user ? . name } < / p>
< p className = "md:text-5xl text-3xl font-extrabold md:mt-10 mt-5 max-w-lg" > I’m Software Engineer at JSM < / p>
< div className = "flex mt-8 gap-5 w-full flex-wrap" >
< Button
title = "Follow"
leftIcon = "/plus-round.svg"
bgColor = "bg-light-white-400 !w-max"
textColor = "text-black-100"
/ >
< Link href = { `mailto: ${ user ?. email } ` } >
< Button title = "Hire Me" leftIcon = "/email.svg" / >
< / Link >
< / div >
< / div >
{ user ? . projects ? . edges ? . length > 0 ? (
< Image
src = { user ? . projects ? . edges [ 0 ] ? . node ?. image }
alt = "project image"
width = { 739 }
height = { 554 }
className = 'rounded-xl object-contain'
/ >
) : (
< Image
src = "/profile-post.png"
width = { 739 }
height = { 554 }
alt = "project image"
className = 'rounded-xl'
/ >
) }
< / section >
< section className = "flexStart flex-col lg:mt-28 mt-16 w-full" >
< p className = "w-full text-left text-lg font-semibold" > Recent Work < / p>
< div className = "profile_projects" >
{ user ? . projects ?. edges ?. map (
( { node } : { node : ProjectInterface } ) => (
< ProjectCard
key = { `${ node ? . id } ` }
id = { node ? . id }
image = { node ?. image }
title = { node ?. title }
name = { user . name }
avatarUrl = { user . avatarUrl }
userId = { user . id }
/ >
)
) }
< / div >
< / section >
< / section >
)
export default ProfilePageprojectPage.tsx import Image from "next/image"
import Link from "next/link"
import { getCurrentUser } from "@/lib/session"
import { getProjectDetails } from "@/lib/actions"
import Modal from "@/components/Modal"
// import ProjectActions from "@/components/ProjectActions"
import RelatedProjects from "@/components/RelatedProjects"
import { ProjectInterface } from "@/common.types"
import ProjectActions from "@/components/ProjectActions"
const Project = async ( { params : { id } } : { params : { id : string } } ) => {
const session = await getCurrentUser ( )
const result = await getProjectDetails ( id ) as { project ?: ProjectInterface }
if ( ! result ?. project ) return (
< p className = "no-result-text" > Failed to fetch project info < / p>
)
const projectDetails = result ?. project
const renderLink = ( ) => `/profile/ ${ projectDetails ?. createdBy ?. id } `
return (
< Modal >
< section className = "flexBetween gap-y-8 max-w-4xl max-xs:flex-col w-full" >
< div className = "flex-1 flex items-start gap-5 w-full max-xs:flex-col" >
< Link href = { renderLink ( ) } >
< Image
src = { projectDetails ? . createdBy ? . avatarUrl }
width = { 50 }
height = { 50 }
alt = "profile"
className = "rounded-full"
/ >
< / Link >
< div className = "flex-1 flexStart flex-col gap-1" >
< p className = "self-start text-lg font-semibold" >
{ projectDetails ? . title }
< / p>
< div className = "user-info" >
< Link href = { renderLink ( ) } >
{ projectDetails ?. createdBy ?. name }
< / Link>
< Image src = "/dot.svg" width = { 4 } height = { 4 } alt = "dot" / >
< Link href = { `/?category=${ projectDetails . category } ` } className = "text-primary-purple font-semibold" >
{ projectDetails ?. category }
< / Link >
< / div >
< / div >
< / div >
{ session ? . user ?. email === projectDetails ?. createdBy ?. email && (
< div className = "flex justify-end items-center gap-2" >
< ProjectActions projectId = { projectDetails ? . id } / >
< / div >
) }
< / section >
< section className = "mt-14" >
< Image
src = { `${ projectDetails ? . image } ` }
className = "object-cover rounded-2xl"
width = { 1064 }
height = { 798 }
alt = "poster"
/ >
< / section >
< section className = "flexCenter flex-col mt-20" >
< p className = "max-w-5xl text-xl font-normal" >
{ projectDetails ? . description }
< / p>
< div className = "flex flex-wrap mt-5 gap-5" >
< Link href = { projectDetails ? . githubUrl } target = "_blank" rel = "noreferrer" className = "flexCenter gap-2 tex-sm font-medium text-primary-purple" >
? < span className = "underline" > Github < / span>
< / Link>
< Image src = "/dot.svg" width = { 4 } height = { 4 } alt = "dot" / >
< Link href = { projectDetails ? . liveSiteUrl } target = "_blank" rel = "noreferrer" className = "flexCenter gap-2 tex-sm font-medium text-primary-purple" >
< span className = "underline" > Live Site < / span>
< / Link>
< / div >
< / section >
< section className = "flexCenter w-full gap-8 mt-28" >
< span className = "w-full h-0.5 bg-light-white-200" / >
< Link href = { renderLink ( ) } className = "min-w-[82px] h-[82px]" >
< Image
src = { projectDetails ? . createdBy ? . avatarUrl }
className = "rounded-full"
width = { 82 }
height = { 82 }
alt = "profile image"
/ >
< / Link >
< span className = "w-full h-0.5 bg-light-white-200" / >
< / section >
< RelatedProjects userId = { projectDetails ? . createdBy ? . id } projectId = { projectDetails ?. id } / >
< / Modal >
)
}
export default Projecttailwind.config.ts tailwind . config . ts
/** @type {import('tailwindcss').Config} */
module . exports = {
content : [
'./pages/**/*.{js,ts,jsx,tsx,mdx}' ,
'./components/**/*.{js,ts,jsx,tsx,mdx}' ,
'./app/**/*.{js,ts,jsx,tsx,mdx}' ,
] ,
theme : {
extend : {
colors : {
'nav-border' : '#EBEAEA' ,
'light-white' : '#FAFAFB' ,
'light-white-100' : '#F1F4F5' ,
'light-white-200' : '#d7d7d7' ,
'light-white-300' : '#F3F3F4' ,
'light-white-400' : '#E2E5F1' ,
'light-white-500' : '#E4E4E4' ,
gray : '#4D4A4A' ,
'gray-100' : '#3d3d4e' ,
'black-100' : '#252525' ,
'primary-purple' : '#9747FF' ,
'gray-50' : '#D9D9D9' ,
} ,
boxShadow : {
menu : '0px 159px 95px rgba(13,12,34,0.01), 0px 71px 71px rgba(13,12,34,0.02), 0px 18px 39px rgba(13,12,34,0.02), 0px 0px 0px rgba(13,12,34,0.02)' ,
} ,
screens : {
'xs' : '400px' ,
} ,
maxWidth : {
'10xl' : '1680px'
}
} ,
} ,
plugins : [ ] ,
} ; สินทรัพย์ที่ใช้ในโครงการที่นี่
พัฒนาทักษะของคุณด้วยหลักสูตร next.js 14 pro
สนุกกับการสร้างโครงการนี้หรือไม่? ดำน้ำลึกลงไปในหลักสูตรมืออาชีพของเราสำหรับการผจญภัยการเรียนรู้ที่สมบูรณ์ยิ่งขึ้น พวกเขาเต็มไปด้วยคำอธิบายโดยละเอียดคุณสมบัติที่ยอดเยี่ยมและการออกกำลังกายเพื่อเพิ่มทักษะของคุณ ไปเลย!

เร่งการเดินทางอย่างมืออาชีพของคุณด้วยโปรแกรมการฝึกอบรมผู้เชี่ยวชาญ
และถ้าคุณหิวมากกว่าหลักสูตรและต้องการเข้าใจว่าเราเรียนรู้และจัดการกับความท้าทายด้านเทคโนโลยีได้อย่างไร เราครอบคลุมแนวปฏิบัติที่ดีที่สุดทักษะการใช้เว็บที่แตกต่างกันและเสนอการให้คำปรึกษาเพื่อเพิ่มความมั่นใจของคุณ มาเรียนรู้และเติบโตไปด้วยกัน!