Written by: Marlon Colca
Posted on 06 Sep 2025 - a month ago
nextjs typescript clones
Create a Next.js App Router project and enable Tailwind with a dark, media‑friendly baseline.
Goal: Create a Next.js App Router project and enable Tailwind with a dark, media‑friendly baseline.
npx create-next-app@latest next-netflix-clone \
--typescript --eslint --src-dir --app --import-alias @/*
cd next-netflix-clone
@import "tailwindcss";
in globals.css
.src/app/layout.tsx
imports ./globals.css
.src/app/page.tsx
is the Home.public/
has videos/
, posters/
, subs/
.@import "tailwindcss";
pulls in the modern reset and utilities with zero config. Keeps CSS tiny and consistent.color-scheme: dark
also hints native form controls/scrollbars to use dark variants.public/
lets the browser request /videos/...
directly without bundling large files into JS.@/*
: Avoids brittle ../../..
paths as the project grows; matches typical Next repo conventions.moduleResolution: "bundler"
: TypeScript resolves ESM the same way the Next bundler does (fewer path/extension gotchas and better DX in editors).resolveJsonModule
: Lets us import movies from "@/data/movies.json"
to drive the UI without extra build steps.globals.css
🎨@import "tailwindcss";
/* Dark cinematic baseline */
:root {
color-scheme: dark;
}
body {
background: #000;
color: #fff;
}
/* Optional: thin scrollbars for rows */
* {
scrollbar-width: thin;
scrollbar-color: #444 transparent;
}
*::-webkit-scrollbar {
height: 8px;
}
*::-webkit-scrollbar-thumb {
background: #444;
border-radius: 999px;
}
// src/app/layout.tsx
import type { Metadata } from "next";
import "./globals.css";
export const metadata: Metadata = {
title: "Netflix Clone Demo",
description: "Catalog with local and external videos",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className="antialiased">{children}</body>
</html>
);
}
src/app/layout.tsx
: App‑wide HTML shell and metadata. Importing ./globals.css
here ensures styles apply to all routes.src/app/page.tsx
: The /
route (Home). Anything exported here renders inside the <body>
from the layout above.src/app/globals.css
: Tailwind core + project‑wide base styles (dark baseline, scrollbars). No per‑component scoping here on purpose.public/…
: Files are served as‑is at /…
. Example: public/posters/sintel.jpg
becomes /posters/sintel.jpg
in <img src>
/<Image src>
.next.config.ts
: Defaults are fine for this course; we keep it minimal until we need image domains or headers.mkdir -p public/videos public/posters public/subs
{
"compilerOptions": {
"resolveJsonModule": true,
"moduleResolution": "bundler",
"paths": { "@/*": ["./src/*"] }
}
}
npm run dev
(or pnpm dev
).npm run build
.globals.css
is imported in layout.tsx
.public/
and paths start with /
.tsconfig.json
has "paths": { "@/*": ["./src/*"] }
and your editor picked it up."resolveJsonModule": true
in tsconfig.json
.scrollbar-width
/scrollbar-color
set above.npm run dev
and open http://localhost:3000/
.public/posters/
and reference it from src/app/page.tsx
using /posters/<file>.jpg
to validate public/
wiring.@import "tailwindcss";
line to see utilities disappear—good sanity check that Tailwind is active.Define a simple, typed catalog and helpers to query it efficiently from the UI.
07 Sep 2025 - a month ago