Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions fullstack/fullstack-assessment/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# env files (can opt-in for committing if needed)
.env*

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
5 changes: 5 additions & 0 deletions fullstack/fullstack-assessment/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!-- BEGIN:nextjs-agent-rules -->
# This is NOT the Next.js you know

This version has breaking changes β€” APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
<!-- END:nextjs-agent-rules -->
1 change: 1 addition & 0 deletions fullstack/fullstack-assessment/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@AGENTS.md
36 changes: 36 additions & 0 deletions fullstack/fullstack-assessment/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
23 changes: 23 additions & 0 deletions fullstack/fullstack-assessment/app/api/posts/[id]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { NextResponse } from 'next/server';
import { posts } from '../../../../data/post';

interface RouteParams {
params: Promise<{
id: string;
}>;
}

export async function GET(request: Request, { params }: RouteParams) {
// Await the params Promise
const { id } = await params;
const post = posts.find(p => p.id === parseInt(id));

if (!post) {
return NextResponse.json(
{ error: 'Post not found' },
{ status: 404 }
);
}

return NextResponse.json(post);
}
6 changes: 6 additions & 0 deletions fullstack/fullstack-assessment/app/api/posts/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { NextResponse } from 'next/server';
import { posts } from '../../../data/post';

export async function GET() {
return NextResponse.json(posts);
}
Binary file added fullstack/fullstack-assessment/app/favicon.ico
Binary file not shown.
58 changes: 58 additions & 0 deletions fullstack/fullstack-assessment/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
@import "tailwindcss";

@layer utilities {
/* Custom animations */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}

.animate-fade-in-up {
animation: fadeInUp 0.6s ease-out forwards;
}

/* Custom scrollbar */
::-webkit-scrollbar {
width: 8px;
}

::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 10px;
}

::-webkit-scrollbar-thumb {
background: linear-gradient(to bottom, #3b82f6, #4f46e5);
border-radius: 10px;
}

::-webkit-scrollbar-thumb:hover {
background: linear-gradient(to bottom, #2563eb, #4338ca);
}
}

/* Smooth scrolling */
html {
scroll-behavior: smooth;
}

/* Line clamp utility for text truncation */
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}

.line-clamp-3 {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
19 changes: 19 additions & 0 deletions fullstack/fullstack-assessment/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { Metadata } from 'next';
import './globals.css';

export const metadata: Metadata = {
title: 'My Next.js Blog',
description: 'A simple blog application',
};

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
89 changes: 89 additions & 0 deletions fullstack/fullstack-assessment/app/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import Link from 'next/link';
import { posts } from '../data/post';


export default function Home() {
return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-50">
{/* Hero Section */}
<header className="bg-white/80 backdrop-blur-sm border-b border-gray-200/50 sticky top-0 z-10">
<div className="max-w-6xl mx-auto py-8 px-4">
<div className="text-center">
<h1 className="text-3xl md:text-5xl font-bold bg-gradient-to-r from-blue-600 to-indigo-600 bg-clip-text text-transparent mb-10">
My Next.js Blog
</h1>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
Exploring the world of Next.js, one post at a time
</p>
</div>
</div>
</header>

{/* Main Content */}
<main className="max-w-6xl mx-auto py-12 px-4">
<div className="mb-8 text-center">
<h2 className="text-3xl font-bold text-gray-800">Latest Posts</h2>
<div className="w-20 h-1 bg-gradient-to-r from-blue-500 to-indigo-500 mx-auto mt-2 rounded-full"></div>
</div>

<div className="grid md:grid-cols-2 lg:grid-cols-2 gap-8">
{posts.map((post, index) => (
<article
key={post.id}
className="group bg-white rounded-2xl shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-1 overflow-hidden"
style={{ animationDelay: `${index * 100}ms` }}
>
{/* Decorative header bar */}
<div className="h-2 bg-gradient-to-r from-blue-500 to-indigo-500"></div>

<div className="p-6">
{/* Date badge */}
<div className="flex justify-between items-start mb-4">
<span className="inline-flex items-center px-3 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800">
{new Date(post.date).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
})}
</span>
<span className="text-gray-400 text-sm">#{post.id}</span>
</div>

{/* Title */}
<Link href={`/posts/${post.id}`}>
<h3 className="text-2xl font-bold text-gray-800 group-hover:text-blue-600 transition-colors duration-200 mb-3 line-clamp-2">
{post.title}
</h3>
</Link>

{/* Excerpt */}
<p className="text-gray-600 leading-relaxed mb-4 line-clamp-3">
{post.excerpt}
</p>

{/* Read more link */}
<Link
href={`/posts/${post.id}`}
className="inline-flex items-center gap-2 text-blue-600 font-semibold group-hover:gap-3 transition-all duration-200"
>
Read more
<svg className="w-4 h-4 group-hover:translate-x-1 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</Link>
</div>
</article>
))}
</div>
</main>

{/* Footer */}
<footer className="bg-white/80 backdrop-blur-sm border-t border-gray-200/50 mt-16">
<div className="max-w-6xl mx-auto py-8 px-4 text-center">
<p className="text-gray-600">Built with ❀️ using Next.js 15 & Tailwind CSS</p>
<p className="text-sm text-gray-500 mt-2">Β© 2025 My Next.js Blog. All rights reserved.</p>
</div>
</footer>
</div>
);
}
98 changes: 98 additions & 0 deletions fullstack/fullstack-assessment/app/posts/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { notFound } from 'next/navigation';
import Link from 'next/link';
import { posts } from '../../../data/post';

interface PostPageProps {
params: Promise<{
id: string;
}>;
}

export async function generateStaticParams() {
return posts.map((post) => ({
id: post.id.toString(),
}));
}

export default async function PostPage({ params }: PostPageProps) {
// IMPORTANT: await the params Promise
const { id } = await params;
const post = posts.find(p => p.id === parseInt(id));

if (!post) {
notFound();
}

return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-50">
{/* Header with Back Button - Enhanced */}
<header className="bg-white/80 backdrop-blur-sm border-b border-gray-200/50 sticky top-0 z-10">
<div className="max-w-4xl mx-auto py-4 px-4">
<Link
href="/"
className="group inline-flex items-center gap-2 text-gray-600 hover:text-blue-600 transition-all duration-200"
>
<svg
className="w-5 h-5 group-hover:-translate-x-1 transition-transform duration-200"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
Back to Home
</Link>
</div>
</header>

{/* Main Content - Enhanced */}
<main className="max-w-4xl mx-auto py-12 px-4">
<article className="bg-white rounded-2xl shadow-xl overflow-hidden transition-all duration-300 hover:shadow-2xl">
{/* Hero Section */}
<div className="bg-gradient-to-r from-blue-600 to-indigo-600 px-8 py-12">
<div className="text-center">
<span className="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-white/20 text-white backdrop-blur-sm">
{new Date(post.date).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
})}
</span>
<h1 className="text-4xl md:text-5xl font-bold text-white mt-4 mb-4">
{post.title}
</h1>
<div className="w-20 h-1 bg-white/30 mx-auto rounded-full"></div>
</div>
</div>

{/* Content */}
<div className="px-8 py-12">
<div className="prose prose-lg max-w-none">
{post.content.split('\n\n').map((paragraph, index) => (
<p key={index} className="text-gray-700 leading-relaxed mb-6 text-lg">
{paragraph}
</p>
))}
</div>

{/* Decorative divider */}
<div className="mt-12 pt-8 border-t border-gray-200 text-center">
<p className="text-gray-500 text-sm">
Thank you for reading! πŸ“–
</p>
</div>
</div>
</article>


</main>

{/* Footer */}
<footer className="bg-white/80 backdrop-blur-sm border-t border-gray-200/50 mt-16">
<div className="max-w-4xl mx-auto py-6 px-4 text-center">
<p className="text-gray-500 text-sm">Built with ❀️ using Next.js & Tailwind CSS</p>
</div>
</footer>
</div>
);
}
Loading