>({});
17 |
18 | const filteredResources = useMemo(() => {
19 | return resources.filter((resource) => {
20 | const matchesSearch =
21 | resource.title.toLowerCase().includes(search.toLowerCase()) ||
22 | resource.description.toLowerCase().includes(search.toLowerCase()) ||
23 | resource.tags.some((tag: string) =>
24 | tag.toLowerCase().includes(search.toLowerCase())
25 | );
26 |
27 | const matchesCategory =
28 | !selectedCategory || resource.category === selectedCategory;
29 |
30 | return matchesSearch && matchesCategory;
31 | });
32 | }, [search, selectedCategory]);
33 |
34 | const handleLike = (id: string) => {
35 | setLikes((prev) => ({
36 | ...prev,
37 | [id]: (prev[id] || 0) + 1,
38 | }));
39 | };
40 |
41 | return (
42 |
43 | {/* Navigation */}
44 |
79 |
80 | {/* Header */}
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
93 |
94 |
95 |
96 |
97 | {/* Main Content */}
98 |
99 |
100 | {filteredResources.map((resource) => (
101 |
109 | ))}
110 |
111 |
112 | {filteredResources.length === 0 && (
113 |
114 |
115 | No resources found matching your criteria.
116 |
117 |
118 | )}
119 |
120 |
121 | );
122 | }
123 |
124 | export default App;
125 |
--------------------------------------------------------------------------------
/src/app/components/CategoryFilter.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Category } from "../types/resource";
3 |
4 | interface CategoryFilterProps {
5 | selectedCategory: Category | null;
6 | onSelect: (category: Category | null) => void;
7 | }
8 |
9 | const categories: Category[] = [
10 | "Framework",
11 | "UI Library",
12 | "Tool",
13 | "Learning",
14 | "Performance",
15 | "Testing",
16 | "State Management",
17 | "CSS",
18 | "TypeScript",
19 | ];
20 |
21 | export function CategoryFilter({
22 | selectedCategory,
23 | onSelect,
24 | }: CategoryFilterProps) {
25 | return (
26 |
27 |
38 | {categories.map((category) => (
39 |
51 | ))}
52 |
53 | );
54 | }
55 |
--------------------------------------------------------------------------------
/src/app/components/ResourceCard.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Heart, ExternalLink } from "lucide-react";
3 | import { Resource } from "../types/resource";
4 | import { Tag } from "./Tag";
5 | import { TechIcon } from "./TechIcon";
6 |
7 | interface ResourceCardProps {
8 | resource: Resource;
9 | onLike: (id: string) => void;
10 | }
11 |
12 | export function ResourceCard({ resource, onLike }: ResourceCardProps) {
13 | return (
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | {resource.title}
23 |
24 | {/*
25 | {resource.category}
26 | */}
27 |
28 |
29 |
35 |
36 |
37 |
38 |
39 |
{resource.description}
40 |
41 |
42 | {resource.tags.map((tag) => (
43 |
44 | ))}
45 |
46 |
47 |
48 |
55 |
56 | Added on {new Date(resource.dateAdded).toLocaleDateString()}
57 |
58 |
59 |
60 | );
61 | }
62 |
--------------------------------------------------------------------------------
/src/app/components/SearchBar.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Search } from "lucide-react";
3 |
4 | interface SearchBarProps {
5 | value: string;
6 | onChange: (value: string) => void;
7 | }
8 |
9 | export function SearchBar({ value, onChange }: SearchBarProps) {
10 | return (
11 |
12 |
13 | onChange(e.target.value)}
17 | placeholder="Search resources..."
18 | className="w-full pl-10 pr-4 py-2 rounded-lg bg-gray-700 border border-gray-600 text-gray-100 placeholder-gray-400 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 transition-all"
19 | />
20 |
21 | );
22 | }
23 |
--------------------------------------------------------------------------------
/src/app/components/Tag.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Tag as TagIcon } from "lucide-react";
3 | import { getTagColors } from "../utils/tagColors";
4 |
5 | interface TagProps {
6 | label: string;
7 | }
8 |
9 | export function Tag({ label }: TagProps) {
10 | const { bg, text } = getTagColors(label);
11 |
12 | return (
13 |
16 |
17 | {label}
18 |
19 | );
20 | }
21 |
--------------------------------------------------------------------------------
/src/app/components/TechIcon.tsx:
--------------------------------------------------------------------------------
1 | import { Code, Book, Gauge, Accessibility } from "lucide-react";
2 | import Image from "next/image";
3 |
4 | interface TechIconProps {
5 | name: string;
6 | className?: string;
7 | }
8 |
9 | const defaultIcons = {
10 | code:
,
11 | book: ,
12 | accessibility: ,
13 | performance: ,
14 | };
15 |
16 | export function TechIcon({ name, className = "h-6 w-6" }: TechIconProps) {
17 | // Convert name to simple-icons format (lowercase, remove spaces)
18 | const iconName = name.toLowerCase().replace(/\s+/g, "");
19 |
20 | if (defaultIcons[name as keyof typeof defaultIcons]) {
21 | return defaultIcons[name as keyof typeof defaultIcons];
22 | }
23 |
24 | return (
25 |
32 | );
33 | }
34 |
--------------------------------------------------------------------------------
/src/app/data/resources.ts:
--------------------------------------------------------------------------------
1 | import { Resource } from "../types/resource";
2 |
3 | export const resources: Resource[] = [
4 | {
5 | id: "1",
6 | title: "Tailwind CSS",
7 | description: "A utility-first CSS framework for rapid UI development",
8 | url: "https://tailwindcss.com",
9 | category: "CSS",
10 | tags: ["css", "framework", "utility-first"],
11 | likes: 1234,
12 | dateAdded: "2024-03-15",
13 | iconName: "css3",
14 | },
15 | {
16 | id: "2",
17 | title: "React Query",
18 | description: "Powerful asynchronous state management for React",
19 | url: "https://tanstack.com/query",
20 | category: "State Management",
21 | tags: ["react", "state", "async"],
22 | likes: 892,
23 | dateAdded: "2024-03-14",
24 | iconName: "react",
25 | },
26 | {
27 | id: "3",
28 | title: "Vite",
29 | description: "Next Generation Frontend Tooling",
30 | url: "https://vitejs.dev",
31 | category: "Tool",
32 | tags: ["bundler", "development", "tool"],
33 | likes: 2156,
34 | dateAdded: "2024-03-13",
35 | iconName: "vite",
36 | },
37 | {
38 | id: "chromevox-extension",
39 | title: "ChromeVox Extension",
40 | description:
41 | "Screen reader extension for Chrome browser to test accessibility",
42 | url: "http://www.chromevox.com/",
43 | category: "Tool",
44 | tags: ["accessibility", "a11y", "testing", "chrome-extension"],
45 | likes: 0,
46 | dateAdded: "2024-01-01",
47 | iconName: "chromewebstore",
48 | },
49 | {
50 | id: "wcag-guidelines",
51 | title: "Web Content Accessibility Guidelines 2.0",
52 | description: "Official W3C guidelines for making web content accessible",
53 | url: "https://www.w3.org/TR/WCAG20/",
54 | category: "Learning",
55 | tags: ["accessibility", "standards", "w3c"],
56 | likes: 0,
57 | dateAdded: "2024-01-01",
58 | iconName: "accessibility",
59 | },
60 | {
61 | id: "angular-material",
62 | title: "Angular Material",
63 | description: "Material Design components for Angular applications",
64 | url: "https://material.angular.io/components/categories",
65 | category: "UI Library",
66 | tags: ["angular", "material-design", "components"],
67 | likes: 0,
68 | dateAdded: "2024-01-01",
69 | iconName: "angular",
70 | },
71 | {
72 | id: "typescript-playground",
73 | title: "TypeScript Playground",
74 | description: "Online editor for experimenting with TypeScript code",
75 | url: "https://www.typescriptlang.org/play",
76 | category: "TypeScript",
77 | tags: ["typescript", "editor", "development"],
78 | likes: 0,
79 | dateAdded: "2024-01-01",
80 | iconName: "typescript",
81 | },
82 | {
83 | id: "redux-devtools",
84 | title: "Redux DevTools",
85 | description: "Browser extension for debugging Redux applications",
86 | url: "https://github.com/reduxjs/redux-devtools",
87 | category: "State Management",
88 | tags: ["redux", "debugging", "development"],
89 | likes: 0,
90 | dateAdded: "2024-01-01",
91 | iconName: "redux",
92 | },
93 | {
94 | id: "flexbox-guide",
95 | title: "Complete Guide to Flexbox",
96 | description: "Comprehensive guide to CSS Flexbox layout",
97 | url: "https://css-tricks.com/snippets/css/a-guide-to-flexbox/",
98 | category: "CSS",
99 | tags: ["css", "flexbox", "layout"],
100 | likes: 0,
101 | dateAdded: "2024-01-01",
102 | iconName: "css",
103 | },
104 | {
105 | id: "jest-testing",
106 | title: "Jest Testing Framework",
107 | description:
108 | "Delightful JavaScript Testing Framework with a focus on simplicity",
109 | url: "https://jestjs.io/",
110 | category: "Testing",
111 | tags: ["testing", "javascript", "framework"],
112 | likes: 0,
113 | dateAdded: "2024-01-01",
114 | iconName: "jest",
115 | },
116 | {
117 | id: "web-vitals",
118 | title: "Web Vitals",
119 | description: "Essential metrics for a healthy site by Google",
120 | url: "https://web.dev/vitals/",
121 | category: "Performance",
122 | tags: ["performance", "metrics", "google"],
123 | likes: 0,
124 | dateAdded: "2024-01-01",
125 | iconName: "code",
126 | },
127 | {
128 | id: "react-docs",
129 | title: "React Documentation",
130 | description: "Official React documentation and guides",
131 | url: "https://reactjs.org/docs/getting-started.html",
132 | category: "Framework",
133 | tags: ["react", "documentation", "javascript"],
134 | likes: 0,
135 | dateAdded: "2024-01-01",
136 | iconName: "react",
137 | },
138 | {
139 | id: "webpack-bundler",
140 | title: "Webpack",
141 | description: "Static module bundler for modern JavaScript applications",
142 | url: "https://webpack.js.org/",
143 | category: "Tool",
144 | tags: ["bundler", "javascript", "build"],
145 | likes: 0,
146 | dateAdded: "2024-01-01",
147 | iconName: "webpack",
148 | },
149 | {
150 | id: "angular-performance-checklist",
151 | title: "Angular Performance Checklist",
152 | description: "Comprehensive checklist for optimizing Angular applications",
153 | url: "https://github.com/mgechev/angular-performance-checklist",
154 | category: "Performance",
155 | tags: ["angular", "optimization", "best-practices"],
156 | likes: 0,
157 | dateAdded: "2024-01-01",
158 | iconName: "performance",
159 | },
160 | {
161 | id: "typescript-deep-dive",
162 | title: "TypeScript Deep Dive",
163 | description:
164 | "Comprehensive guide to TypeScript features and best practices",
165 | url: "https://basarat.gitbook.io/typescript/",
166 | category: "TypeScript",
167 | tags: ["typescript", "guide", "advanced"],
168 | likes: 0,
169 | dateAdded: "2024-01-01",
170 | iconName: "gitbook",
171 | },
172 | {
173 | id: "css-grid-course",
174 | title: "CSS Grid Course",
175 | description: "Complete CSS Grid course with interactive examples",
176 | url: "https://cssgrid.io/",
177 | category: "CSS",
178 | tags: ["css", "grid", "layout", "course"],
179 | likes: 0,
180 | dateAdded: "2024-01-01",
181 | iconName: "book",
182 | },
183 | {
184 | id: "ngrx-store",
185 | title: "NgRx Store",
186 | description: "Reactive State Management for Angular applications",
187 | url: "https://ngrx.io/",
188 | category: "State Management",
189 | tags: ["angular", "redux", "state-management"],
190 | likes: 0,
191 | dateAdded: "2024-01-01",
192 | iconName: "ngrx",
193 | },
194 | {
195 | id: "cypress-testing",
196 | title: "Cypress Testing Framework",
197 | description: "Modern web testing framework for end-to-end testing",
198 | url: "https://www.cypress.io/",
199 | category: "Testing",
200 | tags: ["testing", "e2e", "automation"],
201 | likes: 0,
202 | dateAdded: "2024-01-01",
203 | iconName: "cypress",
204 | },
205 | {
206 | id: "material-ui",
207 | title: "Material-UI",
208 | description: "React components library implementing Material Design",
209 | url: "https://material-ui.com/",
210 | category: "UI Library",
211 | tags: ["react", "material-design", "components"],
212 | likes: 0,
213 | dateAdded: "2024-01-01",
214 | iconName: "mui",
215 | },
216 | {
217 | id: "vue-framework",
218 | title: "Vue.js",
219 | description:
220 | "Progressive JavaScript framework for building user interfaces",
221 | url: "https://vuejs.org/",
222 | category: "Framework",
223 | tags: ["vue", "javascript", "frontend"],
224 | likes: 0,
225 | dateAdded: "2024-01-01",
226 | iconName: "vuedotjs",
227 | },
228 | {
229 | id: "web-components-mdn",
230 | title: "Web Components MDN Guide",
231 | description: "Comprehensive guide to Web Components on MDN",
232 | url: "https://developer.mozilla.org/en-US/docs/Web/Web_Components",
233 | category: "Learning",
234 | tags: ["web-components", "standards", "documentation"],
235 | likes: 0,
236 | dateAdded: "2024-01-01",
237 | iconName: "docs",
238 | },
239 | {
240 | id: "lighthouse",
241 | title: "Lighthouse",
242 | description: "Automated tool for improving web app quality",
243 | url: "https://developers.google.com/web/tools/lighthouse",
244 | category: "Performance",
245 | tags: ["performance", "audit", "google"],
246 | likes: 0,
247 | dateAdded: "2024-01-01",
248 | iconName: "lighthouse",
249 | },
250 | {
251 | id: "storybook",
252 | title: "Storybook",
253 | description: "Tool for developing UI components in isolation",
254 | url: "https://storybook.js.org/",
255 | category: "Tool",
256 | tags: ["components", "development", "documentation"],
257 | likes: 0,
258 | dateAdded: "2024-01-01",
259 | iconName: "storybook",
260 | },
261 | {
262 | id: "react-query",
263 | title: "React Query",
264 | description: "Powerful data synchronization for React applications",
265 | url: "https://react-query.tanstack.com/",
266 | category: "State Management",
267 | tags: ["react", "data-fetching", "cache"],
268 | likes: 0,
269 | dateAdded: "2024-01-01",
270 | iconName: "database",
271 | },
272 | {
273 | id: "typescript-handbook",
274 | title: "TypeScript Handbook",
275 | description: "Official TypeScript documentation and guides",
276 | url: "https://www.typescriptlang.org/docs/handbook/",
277 | category: "TypeScript",
278 | tags: ["typescript", "documentation", "microsoft"],
279 | likes: 0,
280 | dateAdded: "2024-01-01",
281 | iconName: "typescript",
282 | },
283 | {
284 | id: "css-animation-course",
285 | title: "CSS Animation Course",
286 | description: "Free course about CSS animations and transitions",
287 | url: "https://cssanimation.rocks/",
288 | category: "CSS",
289 | tags: ["css", "animation", "tutorial"],
290 | likes: 0,
291 | dateAdded: "2024-01-01",
292 | iconName: "css3",
293 | },
294 | {
295 | id: "testing-library",
296 | title: "Testing Library",
297 | description: "Simple and complete testing utilities for JavaScript",
298 | url: "https://testing-library.com/",
299 | category: "Testing",
300 | tags: ["testing", "javascript", "dom"],
301 | likes: 0,
302 | dateAdded: "2024-01-01",
303 | iconName: "testinglibrary",
304 | },
305 | {
306 | id: "web-vitals-essential",
307 | title: "Web Vitals Essential Metrics",
308 | description: "Essential metrics for healthy web applications",
309 | url: "https://web.dev/vitals/",
310 | category: "Performance",
311 | tags: ["performance", "metrics", "google"],
312 | likes: 0,
313 | dateAdded: "2024-01-01",
314 | iconName: "code",
315 | },
316 | {
317 | id: "svelte-framework",
318 | title: "Svelte",
319 | description: "Cybernetically enhanced web applications framework",
320 | url: "https://svelte.dev/",
321 | category: "Framework",
322 | tags: ["svelte", "javascript", "reactive"],
323 | likes: 0,
324 | dateAdded: "2024-01-01",
325 | iconName: "svelte",
326 | },
327 | {
328 | id: "chakra-ui",
329 | title: "Chakra UI",
330 | description: "Simple, modular and accessible component library",
331 | url: "https://chakra-ui.com/",
332 | category: "UI Library",
333 | tags: ["react", "components", "accessibility"],
334 | likes: 0,
335 | dateAdded: "2024-01-01",
336 | iconName: "chakraui",
337 | },
338 | {
339 | id: "eslint",
340 | title: "ESLint",
341 | description: "Pluggable linting utility for JavaScript and TypeScript",
342 | url: "https://eslint.org/",
343 | category: "Tool",
344 | tags: ["linting", "javascript", "quality"],
345 | likes: 0,
346 | dateAdded: "2024-01-01",
347 | iconName: "eslint",
348 | },
349 | {
350 | id: "mdn-javascript",
351 | title: "MDN JavaScript Guide",
352 | description: "Comprehensive JavaScript documentation and tutorials",
353 | url: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide",
354 | category: "Learning",
355 | tags: ["javascript", "documentation", "tutorial"],
356 | likes: 0,
357 | dateAdded: "2024-01-01",
358 | iconName: "javascript",
359 | },
360 | {
361 | id: "zustand",
362 | title: "Zustand",
363 | description: "Small, fast and scalable state management solution",
364 | url: "https://github.com/pmndrs/zustand",
365 | category: "State Management",
366 | tags: ["react", "state", "hooks"],
367 | likes: 0,
368 | dateAdded: "2024-01-01",
369 | iconName: "store",
370 | },
371 | {
372 | id: "prettier",
373 | title: "Prettier",
374 | description: "Opinionated code formatter for JavaScript and TypeScript",
375 | url: "https://prettier.io/",
376 | category: "Tool",
377 | tags: ["formatting", "code-quality", "development"],
378 | likes: 0,
379 | dateAdded: "2024-01-01",
380 | iconName: "prettier",
381 | },
382 | {
383 | id: "css-modules",
384 | title: "CSS Modules",
385 | description: "Local scope CSS for component-based development",
386 | url: "https://github.com/css-modules/css-modules",
387 | category: "CSS",
388 | tags: ["css", "modules", "components"],
389 | likes: 0,
390 | dateAdded: "2024-01-01",
391 | iconName: "cssmodules",
392 | },
393 | {
394 | id: "vitest",
395 | title: "Vitest",
396 | description: "Next generation testing framework powered by Vite",
397 | url: "https://vitest.dev/",
398 | category: "Testing",
399 | tags: ["testing", "vite", "performance"],
400 | likes: 0,
401 | dateAdded: "2024-01-01",
402 | iconName: "vite",
403 | },
404 | {
405 | id: "nextjs-framework",
406 | title: "Next.js",
407 | description:
408 | "The React Framework for Production with server-side rendering",
409 | url: "https://nextjs.org/",
410 | category: "Framework",
411 | tags: ["react", "ssr", "production"],
412 | likes: 0,
413 | dateAdded: "2024-01-01",
414 | iconName: "next",
415 | },
416 | {
417 | id: "recoil-state",
418 | title: "Recoil",
419 | description: "State management library for React applications by Facebook",
420 | url: "https://recoiljs.org/",
421 | category: "State Management",
422 | tags: ["react", "state", "facebook"],
423 | likes: 0,
424 | dateAdded: "2024-01-01",
425 | iconName: "recoil",
426 | },
427 | {
428 | id: "typescript-exercises",
429 | title: "TypeScript Exercises",
430 | description: "Interactive TypeScript exercises for learning and practice",
431 | url: "https://typescript-exercises.github.io/",
432 | category: "TypeScript",
433 | tags: ["typescript", "learning", "practice"],
434 | likes: 0,
435 | dateAdded: "2024-01-01",
436 | iconName: "typescript",
437 | },
438 | {
439 | id: "sass-guidelines",
440 | title: "Sass Guidelines",
441 | description:
442 | "Opinionated styleguide for writing sane, maintainable and scalable Sass",
443 | url: "https://sass-guidelin.es/",
444 | category: "CSS",
445 | tags: ["sass", "css", "best-practices"],
446 | likes: 0,
447 | dateAdded: "2024-01-01",
448 | iconName: "sass",
449 | },
450 | {
451 | id: "playwright",
452 | title: "Playwright",
453 | description: "Modern end-to-end testing framework by Microsoft",
454 | url: "https://playwright.dev/",
455 | category: "Testing",
456 | tags: ["testing", "e2e", "automation"],
457 | likes: 0,
458 | dateAdded: "2024-01-01",
459 | iconName: "code",
460 | },
461 | {
462 | id: "web-performance-calendar",
463 | title: "Web Performance Calendar",
464 | description: "Collection of performance articles and best practices",
465 | url: "https://calendar.perfplanet.com/",
466 | category: "Performance",
467 | tags: ["performance", "optimization", "articles"],
468 | likes: 0,
469 | dateAdded: "2024-01-01",
470 | iconName: "performance",
471 | },
472 | {
473 | id: "ant-design",
474 | title: "Ant Design",
475 | description: "Enterprise-class UI design language and React components",
476 | url: "https://ant.design/",
477 | category: "UI Library",
478 | tags: ["react", "components", "enterprise"],
479 | likes: 0,
480 | dateAdded: "2024-01-01",
481 | iconName: "ant",
482 | },
483 | {
484 | id: "nx-tools",
485 | title: "Nx Build System",
486 | description: "Smart, extensible build framework for monorepos",
487 | url: "https://nx.dev/",
488 | category: "Tool",
489 | tags: ["monorepo", "build", "scaling"],
490 | likes: 0,
491 | dateAdded: "2024-01-01",
492 | iconName: "nx",
493 | },
494 | {
495 | id: "web-dev",
496 | title: "web.dev",
497 | description: "Guidance for modern web development by Google",
498 | url: "https://web.dev/",
499 | category: "Learning",
500 | tags: ["google", "best-practices", "tutorials"],
501 | likes: 0,
502 | dateAdded: "2024-01-01",
503 | iconName: "google",
504 | },
505 | {
506 | id: "mobx-state",
507 | title: "MobX",
508 | description: "Simple, scalable state management",
509 | url: "https://mobx.js.org/",
510 | category: "State Management",
511 | tags: ["state", "reactive", "javascript"],
512 | likes: 0,
513 | dateAdded: "2024-01-01",
514 | iconName: "mobx",
515 | },
516 | {
517 | id: "postcss",
518 | title: "PostCSS",
519 | description: "Tool for transforming CSS with JavaScript plugins",
520 | url: "https://postcss.org/",
521 | category: "Tool",
522 | tags: ["css", "transformation", "plugins"],
523 | likes: 0,
524 | dateAdded: "2024-01-01",
525 | iconName: "postcss",
526 | },
527 | {
528 | id: "css-in-js",
529 | title: "Emotion",
530 | description: "CSS-in-JS library designed for high performance styling",
531 | url: "https://emotion.sh/",
532 | category: "CSS",
533 | tags: ["css-in-js", "react", "styling"],
534 | likes: 0,
535 | dateAdded: "2024-01-01",
536 | iconName: "css3",
537 | },
538 | {
539 | id: "remix-framework",
540 | title: "Remix",
541 | description: "Full stack web framework focusing on web standards",
542 | url: "https://remix.run/",
543 | category: "Framework",
544 | tags: ["react", "fullstack", "web-standards"],
545 | likes: 0,
546 | dateAdded: "2024-01-01",
547 | iconName: "remix",
548 | },
549 | {
550 | id: "astro-framework",
551 | title: "Astro",
552 | description: "Modern static site builder with island architecture",
553 | url: "https://astro.build/",
554 | category: "Framework",
555 | tags: ["static-site", "performance", "modern"],
556 | likes: 0,
557 | dateAdded: "2024-01-01",
558 | iconName: "astro",
559 | },
560 | {
561 | id: "jotai-state",
562 | title: "Jotai",
563 | description: "Primitive and flexible state management for React",
564 | url: "https://jotai.org/",
565 | category: "State Management",
566 | tags: ["react", "atomic", "state"],
567 | likes: 0,
568 | dateAdded: "2024-01-01",
569 | iconName: "atom",
570 | },
571 | {
572 | id: "typescript-patterns",
573 | title: "TypeScript Design Patterns",
574 | description: "Collection of design patterns implemented in TypeScript",
575 | url: "https://refactoring.guru/design-patterns/typescript",
576 | category: "TypeScript",
577 | tags: ["patterns", "architecture", "best-practices"],
578 | likes: 0,
579 | dateAdded: "2024-01-01",
580 | iconName: "gitbook",
581 | },
582 | {
583 | id: "styled-components",
584 | title: "Styled Components",
585 | description: "Visual primitives for the component age using CSS-in-JS",
586 | url: "https://styled-components.com/",
587 | category: "CSS",
588 | tags: ["css-in-js", "react", "styling"],
589 | likes: 0,
590 | dateAdded: "2024-01-01",
591 | iconName: "style",
592 | },
593 | {
594 | id: "testing-playground",
595 | title: "Testing Playground",
596 | description: "Interactive sandbox for Testing Library queries",
597 | url: "https://testing-playground.com/",
598 | category: "Testing",
599 | tags: ["testing", "interactive", "practice"],
600 | likes: 0,
601 | dateAdded: "2024-01-01",
602 | iconName: "code",
603 | },
604 | {
605 | id: "web-perf-today",
606 | title: "Web Performance Today",
607 | description: "Modern web performance optimization techniques",
608 | url: "https://www.webpagetest.org/learn/",
609 | category: "Performance",
610 | tags: ["optimization", "metrics", "tools"],
611 | likes: 0,
612 | dateAdded: "2024-01-01",
613 | iconName: "performance",
614 | },
615 | {
616 | id: "radix-ui",
617 | title: "Radix UI",
618 | description:
619 | "Unstyled, accessible components for building high‑quality design systems",
620 | url: "https://www.radix-ui.com/",
621 | category: "UI Library",
622 | tags: ["react", "accessibility", "headless"],
623 | likes: 0,
624 | dateAdded: "2024-01-01",
625 | iconName: "radixui",
626 | },
627 | {
628 | id: "turbopack",
629 | title: "Turbopack",
630 | description: "Incremental bundler optimized for JavaScript and TypeScript",
631 | url: "https://turbo.build/pack",
632 | category: "Tool",
633 | tags: ["bundler", "performance", "rust"],
634 | likes: 0,
635 | dateAdded: "2024-01-01",
636 | iconName: "turbo",
637 | },
638 | {
639 | id: "frontend-masters",
640 | title: "Frontend Masters",
641 | description: "Advanced JavaScript, CSS and Framework Courses",
642 | url: "https://frontendmasters.com/",
643 | category: "Learning",
644 | tags: ["courses", "professional", "development"],
645 | likes: 0,
646 | dateAdded: "2024-01-01",
647 | iconName: "learn",
648 | },
649 | {
650 | id: "xstate",
651 | title: "XState",
652 | description: "State machines and statecharts for modern web applications",
653 | url: "https://xstate.js.org/",
654 | category: "State Management",
655 | tags: ["state-machine", "typescript", "visualization"],
656 | likes: 0,
657 | dateAdded: "2024-01-01",
658 | iconName: "xstate",
659 | },
660 | {
661 | id: "css-tricks",
662 | title: "CSS-Tricks",
663 | description:
664 | "Daily articles about CSS, HTML, JavaScript, and all things related to web design and development",
665 | url: "https://css-tricks.com/",
666 | category: "Learning",
667 | tags: ["css", "tutorials", "articles"],
668 | likes: 0,
669 | dateAdded: "2024-01-01",
670 | iconName: "css3",
671 | },
672 | {
673 | id: "qwik-framework",
674 | title: "Qwik",
675 | description:
676 | "Framework that delivers instant loading web applications at any size",
677 | url: "https://qwik.builder.io/",
678 | category: "Framework",
679 | tags: ["performance", "resumable", "modern"],
680 | likes: 0,
681 | dateAdded: "2024-01-01",
682 | iconName: "qwik",
683 | },
684 | {
685 | id: "javascript-info",
686 | title: "JavaScript.info",
687 | description:
688 | "Modern JavaScript Tutorial - from fundamentals to advanced topics",
689 | url: "https://javascript.info/",
690 | category: "Learning",
691 | tags: ["javascript", "tutorial", "comprehensive"],
692 | likes: 0,
693 | dateAdded: "2024-01-01",
694 | iconName: "javascript",
695 | },
696 | {
697 | id: "egghead-courses",
698 | title: "Egghead.io",
699 | description: "Concise screencast tutorials for web development",
700 | url: "https://egghead.io/",
701 | category: "Learning",
702 | tags: ["video-tutorials", "professional", "bite-sized"],
703 | likes: 0,
704 | dateAdded: "2024-01-01",
705 | iconName: "video",
706 | },
707 | {
708 | id: "web-dev-bootcamp",
709 | title: "Full Stack Open",
710 | description:
711 | "Deep dive into modern web development by University of Helsinki",
712 | url: "https://fullstackopen.com/en/",
713 | category: "Learning",
714 | tags: ["fullstack", "react", "nodejs"],
715 | likes: 0,
716 | dateAdded: "2024-01-01",
717 | iconName: "education",
718 | },
719 | {
720 | id: "web-security-academy",
721 | title: "Web Security Academy",
722 | description: "Free online web security training from PortSwigger",
723 | url: "https://portswigger.net/web-security",
724 | category: "Learning",
725 | tags: ["security", "web", "hands-on"],
726 | likes: 0,
727 | dateAdded: "2024-01-01",
728 | iconName: "security",
729 | },
730 | {
731 | id: "react-patterns",
732 | title: "React Patterns",
733 | description:
734 | "Common design patterns and best practices for React applications",
735 | url: "https://reactpatterns.com/",
736 | category: "Learning",
737 | tags: ["react", "patterns", "best-practices"],
738 | likes: 0,
739 | dateAdded: "2024-01-01",
740 | iconName: "pattern",
741 | },
742 | {
743 | id: "javascript30",
744 | title: "JavaScript30",
745 | description: "30 Day Vanilla JS Coding Challenge by Wes Bos",
746 | url: "https://javascript30.com/",
747 | category: "Learning",
748 | tags: ["javascript", "challenge", "projects"],
749 | likes: 0,
750 | dateAdded: "2024-01-01",
751 | iconName: "challenge",
752 | },
753 | {
754 | id: "css-grid-garden",
755 | title: "Grid Garden",
756 | description: "Interactive game for learning CSS grid layout",
757 | url: "https://cssgridgarden.com/",
758 | category: "Learning",
759 | tags: ["css", "grid", "interactive"],
760 | likes: 0,
761 | dateAdded: "2024-01-01",
762 | iconName: "game",
763 | },
764 | {
765 | id: "testing-javascript",
766 | title: "Testing JavaScript",
767 | description: "Complete testing course by Kent C. Dodds",
768 | url: "https://testingjavascript.com/",
769 | category: "Learning",
770 | tags: ["testing", "javascript", "comprehensive"],
771 | likes: 0,
772 | dateAdded: "2024-01-01",
773 | iconName: "test",
774 | },
775 | {
776 | id: "web-accessibility",
777 | title: "Web Accessibility Course",
778 | description: "Complete course on web accessibility by Google",
779 | url: "https://www.udacity.com/course/web-accessibility--ud891",
780 | category: "Learning",
781 | tags: ["accessibility", "a11y", "google"],
782 | likes: 0,
783 | dateAdded: "2024-01-01",
784 | iconName: "accessibility",
785 | },
786 | {
787 | id: "algorithms-javascript",
788 | title: "JavaScript Algorithms",
789 | description: "Algorithms and data structures implemented in JavaScript",
790 | url: "https://github.com/trekhleb/javascript-algorithms",
791 | category: "Learning",
792 | tags: ["algorithms", "data-structures", "practice"],
793 | likes: 0,
794 | dateAdded: "2024-01-01",
795 | iconName: "algorithm",
796 | },
797 | {
798 | id: "clean-code-javascript",
799 | title: "Clean Code JavaScript",
800 | description: "Clean Code concepts adapted for JavaScript",
801 | url: "https://github.com/ryanmcdermott/clean-code-javascript",
802 | category: "Learning",
803 | tags: ["clean-code", "best-practices", "principles"],
804 | likes: 0,
805 | dateAdded: "2024-01-01",
806 | iconName: "code",
807 | },
808 | {
809 | id: "functional-light-js",
810 | title: "Functional-Light JavaScript",
811 | description: "Pragmatic, balanced FP in JavaScript by Kyle Simpson",
812 | url: "https://github.com/getify/Functional-Light-JS",
813 | category: "Learning",
814 | tags: ["functional-programming", "javascript", "book"],
815 | likes: 0,
816 | dateAdded: "2024-01-01",
817 | iconName: "function",
818 | },
819 | {
820 | id: "web-components-tutorial",
821 | title: "Web Components Tutorial",
822 | description: "Complete guide to building web components",
823 | url: "https://open-wc.org/guides/",
824 | category: "Learning",
825 | tags: ["web-components", "tutorial", "standards"],
826 | likes: 0,
827 | dateAdded: "2024-01-01",
828 | iconName: "components",
829 | },
830 | {
831 | id: "performance-workshop",
832 | title: "Web Performance Workshop",
833 | description: "Comprehensive workshop on web performance optimization",
834 | url: "https://frontendmasters.com/courses/web-performance/",
835 | category: "Learning",
836 | tags: ["performance", "optimization", "workshop"],
837 | likes: 0,
838 | dateAdded: "2024-01-01",
839 | iconName: "performance",
840 | },
841 | {
842 | id: "type-hero",
843 | title: "TypeHero",
844 | description:
845 | "Interactive TypeScript challenges platform with community-driven learning and collaborative environment",
846 | url: "https://typehero.dev/",
847 | category: "Learning",
848 | tags: ["typescript", "challenges", "interactive", "community"],
849 | likes: 0,
850 | dateAdded: "2024-01-01",
851 | iconName: "typescript",
852 | },
853 | {
854 | id: "motion-animation",
855 | title: "Motion",
856 | description:
857 | "Modern animation library for JavaScript and React with springs, layout animations, and timelines",
858 | url: "https://motion.dev/",
859 | category: "UI Library",
860 | tags: ["animation", "react", "javascript"],
861 | likes: 0,
862 | dateAdded: "2024-11-16",
863 | iconName: "framer",
864 | },
865 | ];
866 |
--------------------------------------------------------------------------------
/src/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codesandtags/frontend-resources/fc166daf1be554c49e7fdbeb9cb6c49d9983b28f/src/app/favicon.ico
--------------------------------------------------------------------------------
/src/app/fonts/GeistMonoVF.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codesandtags/frontend-resources/fc166daf1be554c49e7fdbeb9cb6c49d9983b28f/src/app/fonts/GeistMonoVF.woff
--------------------------------------------------------------------------------
/src/app/fonts/GeistVF.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codesandtags/frontend-resources/fc166daf1be554c49e7fdbeb9cb6c49d9983b28f/src/app/fonts/GeistVF.woff
--------------------------------------------------------------------------------
/src/app/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | :root {
6 | --background: #ffffff;
7 | --foreground: #171717;
8 | }
9 |
10 | @media (prefers-color-scheme: dark) {
11 | :root {
12 | --background: #0a0a0a;
13 | --foreground: #ededed;
14 | }
15 | }
16 |
17 | body {
18 | color: var(--foreground);
19 | background: var(--background);
20 | font-family: Arial, Helvetica, sans-serif;
21 | }
22 |
--------------------------------------------------------------------------------
/src/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import type { Metadata } from "next";
2 | import localFont from "next/font/local";
3 | import "./globals.css";
4 |
5 | const geistSans = localFont({
6 | src: "./fonts/GeistVF.woff",
7 | variable: "--font-geist-sans",
8 | weight: "100 900",
9 | });
10 | const geistMono = localFont({
11 | src: "./fonts/GeistMonoVF.woff",
12 | variable: "--font-geist-mono",
13 | weight: "100 900",
14 | });
15 |
16 | export const metadata: Metadata = {
17 | title: "Frontend Resources",
18 | description: " 🔥 A curated collection of frontend development resources",
19 | openGraph: {
20 | title: "Frontend Resources",
21 | description: "A curated collection of frontend development resources",
22 | url: "https://codesandtags.io",
23 | siteName: "Frontend Resources",
24 | images: [
25 | {
26 | url: "/og-frontend-resources.png", // Add your OG image at public/og-frontend-resources.png
27 | width: 1200,
28 | height: 630,
29 | alt: "Frontend Resources Preview",
30 | },
31 | ],
32 | locale: "en_US",
33 | type: "website",
34 | },
35 | twitter: {
36 | card: "summary_large_image",
37 | title: "Frontend Resources",
38 | description: "A curated collection of frontend development resources",
39 | images: ["/og-frontend-resources.png"],
40 | },
41 | };
42 |
43 | export default function RootLayout({
44 | children,
45 | }: Readonly<{
46 | children: React.ReactNode;
47 | }>) {
48 | return (
49 |
50 |
53 | {children}
54 |
55 |
56 | );
57 | }
58 |
--------------------------------------------------------------------------------
/src/app/lib/mongodb.ts:
--------------------------------------------------------------------------------
1 | import mongoose from "mongoose";
2 |
3 | const MONGODB_URI = process.env.MONGODB_URI || "";
4 |
5 | if (!MONGODB_URI) {
6 | throw new Error("Please define MONGODB_URI in .env file");
7 | }
8 |
9 | let cached = global.mongoose;
10 |
11 | if (!cached) {
12 | cached = global.mongoose = { conn: null, promise: null };
13 | }
14 |
15 | export async function connectDB() {
16 | try {
17 | if (cached.conn) return cached.conn;
18 |
19 | cached.promise = mongoose.connect(MONGODB_URI);
20 | cached.conn = await cached.promise;
21 | return cached.conn;
22 | } catch (error) {
23 | console.error("MongoDB connection error:", error);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/app/models/Resource.ts:
--------------------------------------------------------------------------------
1 | // models/Resource.ts
2 | import mongoose from "mongoose";
3 |
4 | const ResourceSchema = new mongoose.Schema({
5 | title: String,
6 | description: String,
7 | url: String,
8 | category: String,
9 | tags: [String],
10 | likes: Number,
11 | dateAdded: Date,
12 | iconName: String,
13 | });
14 |
15 | export const Resource =
16 | mongoose.models.Resource || mongoose.model("Resource", ResourceSchema);
17 |
--------------------------------------------------------------------------------
/src/app/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import App from "./components/App";
3 |
4 | export default function Home() {
5 | return ;
6 | }
7 |
--------------------------------------------------------------------------------
/src/app/scripts/migrate.ts:
--------------------------------------------------------------------------------
1 | import { connectDB } from "../lib/mongodb";
2 | import { Resource } from "../models/Resource";
3 | import { resources } from "../data/resources";
4 |
5 | async function migrate() {
6 | await connectDB();
7 |
8 | try {
9 | await Resource.deleteMany({}); // Clear existing data
10 | await Resource.insertMany(resources);
11 | console.log("Data migration successful");
12 | } catch (error) {
13 | console.error("Migration failed:", error);
14 | }
15 | process.exit();
16 | }
17 |
18 | migrate();
19 |
--------------------------------------------------------------------------------
/src/app/types/resource.ts:
--------------------------------------------------------------------------------
1 | export interface Resource {
2 | id: string;
3 | title: string;
4 | description: string;
5 | url: string;
6 | category: Category;
7 | tags: string[];
8 | likes: number;
9 | dateAdded: string;
10 | iconName: string;
11 | }
12 |
13 | export type Category =
14 | | "Framework"
15 | | "UI Library"
16 | | "Tool"
17 | | "Learning"
18 | | "Performance"
19 | | "Testing"
20 | | "State Management"
21 | | "CSS"
22 | | "TypeScript";
23 |
--------------------------------------------------------------------------------
/src/app/utils/tagColors.ts:
--------------------------------------------------------------------------------
1 | interface TagColorMap {
2 | [key: string]: {
3 | bg: string;
4 | text: string;
5 | };
6 | }
7 |
8 | export const getTagColors = (tag: string): { bg: string; text: string } => {
9 | const colorMap: TagColorMap = {
10 | react: { bg: 'bg-blue-600/20', text: 'text-blue-300' },
11 | vue: { bg: 'bg-emerald-600/20', text: 'text-emerald-300' },
12 | angular: { bg: 'bg-red-600/20', text: 'text-red-300' },
13 | typescript: { bg: 'bg-blue-600/20', text: 'text-blue-300' },
14 | javascript: { bg: 'bg-yellow-600/20', text: 'text-yellow-300' },
15 | css: { bg: 'bg-pink-600/20', text: 'text-pink-300' },
16 | html: { bg: 'bg-orange-600/20', text: 'text-orange-300' },
17 | framework: { bg: 'bg-purple-600/20', text: 'text-purple-300' },
18 | library: { bg: 'bg-indigo-600/20', text: 'text-indigo-300' },
19 | tool: { bg: 'bg-cyan-600/20', text: 'text-cyan-300' },
20 | testing: { bg: 'bg-green-600/20', text: 'text-green-300' },
21 | state: { bg: 'bg-violet-600/20', text: 'text-violet-300' },
22 | async: { bg: 'bg-fuchsia-600/20', text: 'text-fuchsia-300' },
23 | bundler: { bg: 'bg-amber-600/20', text: 'text-amber-300' },
24 | development: { bg: 'bg-teal-600/20', text: 'text-teal-300' },
25 | };
26 |
27 | // Default color for tags without specific mapping
28 | const defaultColor = { bg: 'bg-gray-600/20', text: 'text-gray-300' };
29 |
30 | return colorMap[tag.toLowerCase()] || defaultColor;
31 | };
--------------------------------------------------------------------------------
/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from "tailwindcss";
2 |
3 | export default {
4 | content: [
5 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
6 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
7 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
8 | ],
9 | theme: {
10 | extend: {
11 | colors: {
12 | background: "var(--background)",
13 | foreground: "var(--foreground)",
14 | },
15 | },
16 | },
17 | plugins: [],
18 | } satisfies Config;
19 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2017",
4 | "lib": ["dom", "dom.iterable", "esnext", "es2017"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "noEmit": true,
9 | "esModuleInterop": true,
10 | "module": "commonjs",
11 | "moduleResolution": "bundler",
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "jsx": "preserve",
15 | "incremental": true,
16 | "plugins": [
17 | {
18 | "name": "next"
19 | }
20 | ],
21 | "paths": {
22 | "@/*": ["./src/*"]
23 | },
24 | "outDir": "./dist",
25 | "sourceMap": true,
26 | "removeComments": true,
27 | "noImplicitAny": true,
28 | "strictNullChecks": true,
29 | "strictFunctionTypes": true,
30 | "noImplicitThis": true,
31 | "noUnusedLocals": true,
32 | "noUnusedParameters": true,
33 | "noImplicitReturns": true,
34 | "noFallthroughCasesInSwitch": true,
35 | "allowSyntheticDefaultImports": true,
36 | "emitDecoratorMetadata": true,
37 | "experimentalDecorators": true,
38 | "baseUrl": "."
39 | },
40 | "include": [
41 | "next-env.d.ts",
42 | "**/*.ts",
43 | "**/*.tsx",
44 | ".next/types/**/*.ts",
45 | "src/**/*"
46 | ],
47 | "exclude": ["node_modules"]
48 | }
49 |
--------------------------------------------------------------------------------