{"id":88709,"date":"2024-12-18T00:31:45","date_gmt":"2024-12-17T21:01:45","guid":{"rendered":"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/"},"modified":"2024-12-18T00:31:45","modified_gmt":"2024-12-17T21:01:45","slug":"crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b","status":"publish","type":"post","link":"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/","title":{"rendered":"Crypto News Aggregator \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 Typescript\u060c Next.js\u060c NewsDataHub \u0648 API\u0647\u0627\u06cc CoinGecko"},"content":{"rendered":"<p>Summarize this content to 400 words in Persian Lang<br \/>\n              \u062f\u0631 \u0627\u06cc\u0646 \u0645\u0642\u0627\u0644\u0647\u060c \u0645\u06cc\u200c\u062e\u0648\u0627\u0647\u06cc\u0645 \u06cc\u06a9 \u0628\u0631\u0646\u0627\u0645\u0647 \u0633\u0627\u062f\u0647 \u0627\u0645\u0627 \u0645\u0641\u06cc\u062f \u0628\u0631\u0627\u06cc \u062c\u0645\u0639\u200c\u0622\u0648\u0631\u06cc \u0627\u062e\u0628\u0627\u0631 \u0627\u0631\u0632\u0647\u0627\u06cc \u062f\u06cc\u062c\u06cc\u062a\u0627\u0644 \u0628\u0633\u0627\u0632\u06cc\u0645 \u06a9\u0647 \u0627\u0632 NewsDataHub \u0648 API\u0647\u0627\u06cc CoinGecko \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc\u200c\u06a9\u0646\u062f. \u0647\u062f\u0641 \u0627\u06cc\u0646 \u0645\u0642\u0627\u0644\u0647 \u06cc\u06a9 \u062a\u0648\u0633\u0639\u0647\u200c\u062f\u0647\u0646\u062f\u0647 \u0633\u0637\u062d \u0645\u0628\u062a\u062f\u06cc \u0627\u0633\u062a &#8211; \u0627\u06af\u0631 \u0641\u06a9\u0631 \u0645\u06cc\u200c\u06a9\u0646\u06cc\u062f \u0647\u0631 \u0628\u062e\u0634 \u0627\u0631\u0632\u0634\u06cc \u0628\u0647 \u062a\u062c\u0631\u0628\u0647 \u06cc\u0627\u062f\u06af\u06cc\u0631\u06cc \u0634\u0645\u0627 \u0646\u0645\u06cc\u200c\u0627\u0641\u0632\u0627\u06cc\u062f\u060c \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u06cc\u062f \u0627\u0632 \u0622\u0646 \u0635\u0631\u0641\u0646\u0638\u0631 \u06a9\u0646\u06cc\u062f.<\/p>\n<p>\u0647\u0645\u0686\u0646\u06cc\u0646 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u0628\u0628\u06cc\u0646\u06cc\u062f \u06a9\u0647 \u06a9\u062f \u0646\u0647\u0627\u06cc\u06cc \u067e\u0631\u0648\u0698\u0647 \u0686\u06af\u0648\u0646\u0647 \u0627\u0633\u062a: https:\/\/github.com\/newsdatahub\/crypto-news-aggregator<\/p>\n<p>\u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u0628\u0628\u06cc\u0646\u06cc\u062f \u06a9\u0647 \u0646\u0633\u062e\u0647 \u062a\u0648\u0644\u06cc\u062f\u06cc \u0627\u06cc\u0646 \u0628\u0631\u0646\u0627\u0645\u0647 \u062f\u0642\u06cc\u0642\u0627\u064b \u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u0686\u06af\u0648\u0646\u0647 \u0627\u0633\u062a: https:\/\/newsdatahub.com\/crypto<\/p>\n<p>\u0628\u06cc\u0627\u06cc\u06cc\u062f \u0628\u0627 \u0627\u06cc\u062c\u0627\u062f \u06cc\u06a9 \u067e\u0631\u0648\u0698\u0647 Next.js \u062c\u062f\u06cc\u062f \u0628\u0627 \u067e\u0634\u062a\u06cc\u0628\u0627\u0646\u06cc Typescript \u0634\u0631\u0648\u0639 \u06a9\u0646\u06cc\u0645.<\/p>\n<p>npx create-next-app@latest crypto-news-aggregator &#8211;typescript<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u0648\u0642\u062a\u06cc \u0627\u0632 \u0634\u0645\u0627 \u062e\u0648\u0627\u0633\u062a\u0647 \u0634\u062f\u060c \u0627\u0646\u062a\u062e\u0627\u0628 \u06a9\u0646\u06cc\u062f:<\/p>\n<p>\u0628\u0631\u0627\u06cc ESLint \u0628\u0644\u0647<br \/>\n\u0646\u0647 \u0628\u0631\u0627\u06cc Tailwind CSS (\u0645\u0627 \u0627\u0632 \u0645\u0627\u0698\u0648\u0644\u200c\u0647\u0627\u06cc CSS \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u062e\u0648\u0627\u0647\u06cc\u0645 \u06a9\u0631\u062f)<br \/>\n\u0646\u0647 \u0628\u0631\u0627\u06cc src\/ \u062f\u0627\u06cc\u0631\u06a9\u062a\u0648\u0631\u06cc<br \/>\n\u0628\u0631\u0627\u06cc App Router \u0628\u0644\u0647<br \/>\n\u0646\u0647 \u0628\u0631\u0627\u06cc \u062a\u0648\u0631\u0628\u0648\u067e\u06a9<br \/>\n\u0646\u0647 \u0628\u0631\u0627\u06cc \u0633\u0641\u0627\u0631\u0634\u06cc \u06a9\u0631\u062f\u0646 \u0646\u0627\u0645 \u0645\u0633\u062a\u0639\u0627\u0631 \u0648\u0627\u0631\u062f\u0627\u062a (\u0645\u0627 \u0627\u06cc\u0646 \u0631\u0627 \u0628\u0647 \u0635\u0648\u0631\u062a \u062f\u0633\u062a\u06cc \u062a\u0646\u0638\u06cc\u0645 \u0645\u06cc \u06a9\u0646\u06cc\u0645)<\/p>\n<p>cd \u062f\u0631 \u067e\u0648\u0634\u0647 \u067e\u0631\u0648\u0698\u0647:<\/p>\n<p>cd crypto-news-aggregator<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>  \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0633\u0627\u062e\u062a\u0627\u0631 \u067e\u0631\u0648\u0698\u0647<\/p>\n<p>\u067e\u0633 \u0627\u0632 \u0645\u0642\u062f\u0627\u0631\u062f\u0647\u06cc \u0627\u0648\u0644\u06cc\u0647\u060c \u0628\u06cc\u0627\u06cc\u06cc\u062f \u0633\u0627\u062e\u062a\u0627\u0631 \u067e\u0631\u0648\u0698\u0647 \u062e\u0648\u062f \u0631\u0627 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u0645. \u0645\u0646 \u0647\u062f\u0641 \u0647\u0631 \u062f\u0627\u06cc\u0631\u06a9\u062a\u0648\u0631\u06cc \u0648 \u0641\u0627\u06cc\u0644 \u0631\u0627 \u062a\u0648\u0636\u06cc\u062d \u062e\u0648\u0627\u0647\u0645 \u062f\u0627\u062f.<\/p>\n<p>mkdir -p app\/components\/{news-feed,price-ticker} __tests__ types<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u062f\u0631 \u067e\u0627\u06cc\u0627\u0646 \u0627\u06cc\u0646 \u0622\u0645\u0648\u0632\u0634 \u0628\u0627\u06cc\u062f \u0628\u0647 \u0633\u0627\u062e\u062a\u0627\u0631 \u0632\u06cc\u0631 \u0628\u0631\u0633\u06cc\u062f.<\/p>\n<p>crypto-news-aggregator\/<br \/>\n\u251c\u2500\u2500 __tests__\/                    # Test files<br \/>\n\u2502   \u251c\u2500\u2500 Home.test.tsx<br \/>\n\u2502   \u251c\u2500\u2500 NewsCard.test.tsx<br \/>\n\u2502   \u2514\u2500\u2500 PriceTicker.test.tsx<br \/>\n\u251c\u2500\u2500 app\/                          # Next.js app directory<br \/>\n\u2502   \u251c\u2500\u2500 components\/               # React components<br \/>\n\u2502   \u2502   \u251c\u2500\u2500 news-feed\/            # News-related components<br \/>\n\u2502   \u2502   \u2502   \u251c\u2500\u2500 NewsCard.tsx<br \/>\n\u2502   \u2502   \u2502   \u2514\u2500\u2500 index.ts<br \/>\n\u2502   \u2502   \u2514\u2500\u2500 price-ticker\/         # Price ticker components<br \/>\n\u2502   \u2502       \u251c\u2500\u2500 PriceTicker.tsx<br \/>\n\u2502   \u2502       \u2514\u2500\u2500 index.ts<br \/>\n\u2502   \u251c\u2500\u2500 layout.tsx               # Root layout component<br \/>\n\u2502   \u251c\u2500\u2500 page.module.css          # Styles for main page<br \/>\n\u2502   \u2514\u2500\u2500 page.tsx                 # Main page component<br \/>\n\u251c\u2500\u2500 public\/                      # Static assets<br \/>\n\u251c\u2500\u2500 types\/                       # TypeScript type definitions<br \/>\n\u2502   \u251c\u2500\u2500 cache.ts<br \/>\n\u2502   \u251c\u2500\u2500 crypto.ts<br \/>\n\u2502   \u251c\u2500\u2500 env.d.ts<br \/>\n\u2502   \u251c\u2500\u2500 index.ts<br \/>\n\u2502     \u2514\u2500\u2500 news.ts<br \/>\n\u251c\u2500\u2500 .env.example                # Example environment variables<br \/>\n\u251c\u2500\u2500 .env.local                  # Environment variables (gitignored)<br \/>\n\u251c\u2500\u2500 .eslintrc.json              # ESLint configuration<br \/>\n\u251c\u2500\u2500 .gitignore                  # Git ignore rules<br \/>\n\u251c\u2500\u2500 eslint.config.mjs           # ESLint module configuration<br \/>\n\u251c\u2500\u2500 jest.config.mjs             # Jest configuration<br \/>\n\u251c\u2500\u2500 jest.setup.js               # Jest setup file<br \/>\n\u251c\u2500\u2500 next-env.d.ts               # Next.js TypeScript declarations<br \/>\n\u251c\u2500\u2500 next.config.js              # Next.js configuration<br \/>\n\u251c\u2500\u2500 package-lock.json           # Locked dependency versions<br \/>\n\u251c\u2500\u2500 package.json                # Project dependencies<br \/>\n\u251c\u2500\u2500 README.md<br \/>\n\u251c\u2500\u2500 tsconfig.json               # TypeScript configuration<br \/>\n\u2514\u2500\u2500 types.d.ts                  # Global TypeScript declarations<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u0627\u0645\u0627 \u0642\u0628\u0644 \u0627\u0632 \u0627\u06cc\u0646\u06a9\u0647 \u0628\u0647 \u0622\u0646\u062c\u0627 \u0628\u0631\u0633\u06cc\u0645\u060c \u0628\u0627\u06cc\u062f \u062f\u0627\u06cc\u0631\u06a9\u062a\u0648\u0631\u06cc \u067e\u0631\u0648\u0698\u0647 \u0631\u0627 \u06a9\u0645\u06cc \u062a\u0645\u06cc\u0632 \u06a9\u0646\u06cc\u0645 \u0648 \u0633\u067e\u0633 \u0686\u0646\u062f \u0641\u0627\u06cc\u0644 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u0645.<\/p>\n<p>  \u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc\u06cc \u06a9\u0647 \u0645\u06cc \u062a\u0648\u0627\u0646 \u0628\u0627 \u062e\u06cc\u0627\u0644 \u0631\u0627\u062d\u062a \u067e\u0627\u06a9 \u06a9\u0631\u062f<\/p>\n<p>app\/globals.css (\u0627\u06af\u0631 \u0627\u0632 \u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc module.css \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u062f)<br \/>\n\u0647\u0645\u0647 .svg \u0641\u0627\u06cc\u0644 \u0647\u0627 (\u062f\u0631 \/public \u062f\u0627\u06cc\u0631\u06a9\u062a\u0648\u0631\u06cc)<br \/>\nREADME.md (\u062d\u0630\u0641 \u06cc\u0627 \u0628\u0647\u200c\u0631\u0648\u0632\u0631\u0633\u0627\u0646\u06cc\u060c \u0632\u06cc\u0631\u0627 \u0627\u06cc\u0646 \u0628\u0631\u0646\u0627\u0645\u0647 \u067e\u06cc\u0634\u200c\u0641\u0631\u0636 \u0627\u0632 create-next-app \u0627\u0633\u062a)<\/p>\n<p>\u0627\u06af\u0631 favicon.ico \u0634\u0645\u0627 \u062f\u0631 \u062f\u0627\u06cc\u0631\u06a9\u062a\u0648\u0631\u06cc \u0628\u0631\u0646\u0627\u0645\u0647 \u0627\u0633\u062a\u060c \u0622\u0646 \u0631\u0627 \u0628\u0647 \u067e\u0648\u0634\u0647 \u0639\u0645\u0648\u0645\u06cc \u0645\u0646\u062a\u0642\u0644 \u06a9\u0646\u06cc\u062f. \u062f\u0631 \u062d\u0627\u0644\u06cc \u06a9\u0647 \u0641\u0627\u0648\u06cc\u06a9\u0648\u0646 \u0645\u06cc \u062a\u0648\u0627\u0646\u062f \u062f\u0631 \u0647\u0631 \u062f\u0648 \u0645\u06a9\u0627\u0646 \u06a9\u0627\u0631 \u06a9\u0646\u062f\u060c \u0622\u0646 \u0631\u0627 \u0628\u0647 \u0622\u0646 \u0645\u0646\u062a\u0642\u0644 \u06a9\u0646\u06cc\u062f public\/ \u0627\u0632 \u0633\u0627\u062e\u062a\u0627\u0631 \u0645\u062a\u0639\u0627\u0631\u0641 \u067e\u06cc\u0631\u0648\u06cc \u0645\u06cc \u06a9\u0646\u062f \u0648 \u0645\u06a9\u0627\u0646 \u062f\u0627\u0631\u0627\u06cc\u06cc \u0631\u0627 \u0648\u0627\u0636\u062d \u062a\u0631 \u0645\u06cc \u06a9\u0646\u062f.<\/p>\n<p>  \u062a\u0633\u062a \u06a9\u0631\u062f\u0646<\/p>\n<p>\u0645\u0627 \u0628\u0627\u06cc\u062f \u0686\u0646\u062f\u06cc\u0646 \u0628\u0633\u062a\u0647 \u0622\u0632\u0645\u0627\u06cc\u0634\u06cc \u0631\u0627 \u0646\u0635\u0628 \u06a9\u0646\u06cc\u0645<\/p>\n<p>npm install &#8211;save-dev @testing-library\/react @testing-library\/jest-dom jest jest-environment-jsdom<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u0628\u06cc\u0627\u06cc\u06cc\u062f \u0628\u0641\u0647\u0645\u06cc\u0645 \u06a9\u0647 \u0647\u0631 \u0628\u0633\u062a\u0647 \u0686\u0647 \u06a9\u0627\u0631\u06cc \u0627\u0646\u062c\u0627\u0645 \u0645\u06cc \u062f\u0647\u062f:<\/p>\n<p>@testing-library\/react: \u0627\u0628\u0632\u0627\u0631\u0647\u0627\u06cc\u06cc \u0631\u0627 \u0628\u0631\u0627\u06cc \u0622\u0632\u0645\u0627\u06cc\u0634 \u0627\u062c\u0632\u0627\u06cc React \u0627\u0631\u0627\u0626\u0647 \u0645\u06cc \u062f\u0647\u062f<\/p>\n<p>@testing-library\/jest-dom: \u0647\u0645\u0633\u0627\u0646 Jest \u0633\u0641\u0627\u0631\u0634\u06cc \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc \u06a9\u0646\u062f<\/p>\n<p>jest: \u0686\u0627\u0631\u0686\u0648\u0628 \u0627\u0635\u0644\u06cc \u062a\u0633\u062a<\/p>\n<p>jest-environment-jsdom: \u06cc\u06a9 \u0645\u062d\u06cc\u0637 \u0645\u0631\u0648\u0631\u06af\u0631 \u0631\u0627 \u0628\u0631\u0627\u06cc \u062a\u0633\u062a \u0647\u0627\u06cc \u0645\u0627 \u0634\u0628\u06cc\u0647 \u0633\u0627\u0632\u06cc \u0645\u06cc \u06a9\u0646\u062f<\/p>\n<p>\u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f types.d.ts \u0628\u0631\u0627\u06cc \u062a\u0633\u062a \u062a\u0639\u0627\u0631\u06cc\u0641 \u0646\u0648\u0639<\/p>\n<p>import &#8216;@testing-library\/jest-dom&#8217;;<br \/>\ndeclare global {<br \/>\n  namespace jest {<br \/>\n    interface Matchers&lt;R&gt; {<br \/>\n      toBeInTheDocument(): R;<br \/>\n    }<br \/>\n  }<br \/>\n  interface Window {<br \/>\n    fetch: jest.Mock;<br \/>\n  }<br \/>\n}<br \/>\nexport {};<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u062d\u0627\u0644 \u0628\u06cc\u0627\u06cc\u06cc\u062f \u062a\u0639\u0627\u0631\u06cc\u0641 \u0646\u0648\u0639 TypeScript \u0631\u0627 \u0646\u0635\u0628 \u06a9\u0646\u06cc\u0645 \u062a\u0627 \u0648\u06cc\u0631\u0627\u06cc\u0634\u06af\u0631 \u06a9\u062f \u0645\u0627 \u0628\u062a\u0648\u0627\u0646\u062f Node.js\u060c React \u0648 Jest API\u0647\u0627 \u0631\u0627 \u062f\u0631\u06a9 \u06a9\u0646\u062f\u060c \u0648 \u0627\u0645\u06a9\u0627\u0646 \u062a\u06a9\u0645\u06cc\u0644 \u062e\u0648\u062f\u06a9\u0627\u0631 \u0648 \u06af\u0631\u0641\u062a\u0646 \u062e\u0637\u0627\u0647\u0627\u06cc \u0646\u0648\u0639 \u062f\u0631 \u0637\u0648\u0644 \u062a\u0648\u0633\u0639\u0647 \u0631\u0627 \u0641\u0631\u0627\u0647\u0645 \u06a9\u0646\u062f.<\/p>\n<p>npm install &#8211;save-dev @types\/node @types\/react @types\/jest<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u067e\u0633 \u0627\u0632 \u0646\u0635\u0628 \u0628\u0633\u062a\u0647 \u0647\u0627\u060c \u0628\u0627\u06cc\u062f \u062c\u0633\u062a \u0631\u0627 \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u06a9\u0646\u06cc\u0645. \u0627\u06cc\u062c\u0627\u062f \u06cc\u06a9 jest.config.mjs \u0641\u0627\u06cc\u0644 \u062f\u0631 \u0631\u06cc\u0634\u0647 \u067e\u0631\u0648\u0698\u0647 \u062e\u0648\u062f<\/p>\n<p>jest.config.mjs:<\/p>\n<p>import nextJest from &#8216;next\/jest.js&#8217;;<\/p>\n<p>const createJestConfig = nextJest({<br \/>\n  dir: &#8216;.\/&#8217;,<br \/>\n});<\/p>\n<p>export default createJestConfig({<br \/>\n  testEnvironment: &#8216;jest-environment-jsdom&#8217;,<br \/>\n  setupFilesAfterEnv: [&#8216;\/jest.setup.js&#8217;]\n});<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u0627\u06cc\u062c\u0627\u062f \u06cc\u06a9 jest.setup.js \u0641\u0627\u06cc\u0644 \u0628\u0631\u0627\u06cc \u0648\u0627\u0631\u062f \u06a9\u0631\u062f\u0646 \u062a\u0637\u0628\u06cc\u0642 \u062f\u0647\u0646\u062f\u0647 \u0647\u0627\u06cc DOM.<\/p>\n<p>jest.setup.js:<\/p>\n<p>import &#8216;@testing-library\/jest-dom&#8217;;<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u062f\u0631 \u0646\u0647\u0627\u06cc\u062a\u060c \u0627\u06cc\u0646 \u062e\u0637\u0648\u0637 \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f \u062a\u0627 \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a \u0622\u0632\u0645\u0627\u06cc\u0634\u06cc \u0634\u0645\u0627 \u0627\u062c\u0631\u0627 \u0634\u0648\u062f package.json \u0632\u06cc\u0631 scripts:<\/p>\n<p>&#8220;test&#8221;: &#8220;jest&#8221;,<br \/>\n&#8220;test:watch&#8221;: &#8220;jest &#8211;watch&#8221;<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u0628\u0646\u0627\u0628\u0631\u0627\u06cc\u0646 \u0628\u0647 \u0627\u06cc\u0646 \u0635\u0648\u0631\u062a \u062e\u0648\u0627\u0647\u062f \u0628\u0648\u062f:<\/p>\n<p>  &#8220;scripts&#8221;: {<br \/>\n    &#8220;dev&#8221;: &#8220;next dev&#8221;,<br \/>\n    &#8220;build&#8221;: &#8220;next build&#8221;,<br \/>\n    &#8220;start&#8221;: &#8220;next start&#8221;,<br \/>\n    &#8220;lint&#8221;: &#8220;next lint&#8221;,<br \/>\n    &#8220;test&#8221;: &#8220;jest&#8221;,<br \/>\n    &#8220;test:watch&#8221;: &#8220;jest &#8211;watch&#8221;<br \/>\n  },<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u0627\u06a9\u0646\u0648\u0646 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u062a\u0633\u062a \u0647\u0627 \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f npm test \u06cc\u0627 npm run test:watch \u0628\u0631\u0627\u06cc \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0634\u0627 \u0627\u0645\u0627 \u0645\u0627 \u0647\u0646\u0648\u0632 \u0647\u06cc\u0686 \u062a\u0633\u062a\u06cc \u0646\u062f\u0627\u0631\u06cc\u0645\u060c \u0628\u0647 \u0632\u0648\u062f\u06cc \u06cc\u06a9 \u062a\u0633\u062a \u0627\u0636\u0627\u0641\u0647 \u062e\u0648\u0627\u0647\u06cc\u0645 \u06a9\u0631\u062f.<\/p>\n<p>  \u062f\u0631\u06cc\u0627\u0641\u062a \u0646\u0634\u0627\u0646\u0647 API NewsDataHub \u0634\u0645\u0627<\/p>\n<p>\u0628\u06cc\u0627\u06cc\u06cc\u062f \u0631\u0648\u0646\u062f \u062f\u0631\u06cc\u0627\u0641\u062a \u062a\u0648\u06a9\u0646 API \u0634\u0645\u0627 \u0631\u0627 \u0637\u06cc \u06a9\u0646\u06cc\u0645.<\/p>\n<p>\u0628\u0647 NewsDataHub.com \u0645\u0631\u0627\u062c\u0639\u0647 \u06a9\u0646\u06cc\u062f<\/p>\n<p>\u0627\u06cc\u062c\u0627\u062f \u062d\u0633\u0627\u0628 \u06a9\u0627\u0631\u0628\u0631\u06cc (\u0628\u062f\u0648\u0646 \u0646\u06cc\u0627\u0632 \u0628\u0647 \u06a9\u0627\u0631\u062a \u0627\u0639\u062a\u0628\u0627\u0631\u06cc)<\/p>\n<p>\u0622\u062f\u0631\u0633 \u0627\u06cc\u0645\u06cc\u0644 \u062e\u0648\u062f \u0631\u0627 \u062f\u0631 \u0641\u0631\u0645 \u062b\u0628\u062a \u0646\u0627\u0645 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<br \/>\n\u0628\u0627\u06cc\u062f \u0627\u06cc\u0645\u06cc\u0644 \u062e\u0648\u062f \u0631\u0627 \u0628\u0631\u0627\u06cc \u06a9\u062f \u062a\u0627\u06cc\u06cc\u062f \u0628\u0631\u0631\u0633\u06cc \u06a9\u0646\u06cc\u062f<br \/>\n\u0647\u0646\u06af\u0627\u0645\u06cc \u06a9\u0647 \u062d\u0633\u0627\u0628 \u062e\u0648\u062f \u0631\u0627 \u062a\u0623\u06cc\u06cc\u062f \u06a9\u0631\u062f\u06cc\u062f\u060c \u0628\u0647 \u062f\u0627\u0634\u0628\u0648\u0631\u062f \u062e\u0648\u062f \u0645\u0646\u062a\u0642\u0644 \u062e\u0648\u0627\u0647\u06cc\u062f \u0634\u062f\u060c \u062c\u0627\u06cc\u06cc \u06a9\u0647 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u06a9\u0644\u06cc\u062f API \u062e\u0648\u062f \u0631\u0627 \u067e\u06cc\u062f\u0627 \u06a9\u0646\u06cc\u062f<\/p>\n<p>  \u0627\u0641\u0632\u0648\u062f\u0646 \u06a9\u0644\u06cc\u062f API \u0628\u0647 \u067e\u0631\u0648\u0698\u0647 \u0634\u0645\u0627<\/p>\n<p>\u0627\u06cc\u062c\u0627\u062f \u06cc\u06a9 .env.example \u062f\u0631 \u0631\u06cc\u0634\u0647 \u067e\u0631\u0648\u0698\u0647 \u062e\u0648\u062f \u0641\u0627\u06cc\u0644 \u06a9\u0646\u06cc\u062f \u062a\u0627 \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u06cc\u06a9 \u0627\u0644\u06af\u0648 \u0628\u0631\u0627\u06cc \u0645\u062a\u063a\u06cc\u0631\u0647\u0627\u06cc \u0645\u062d\u06cc\u0637 \u0645\u0648\u0631\u062f \u0646\u06cc\u0627\u0632 \u0639\u0645\u0644 \u06a9\u0646\u062f<\/p>\n<p>NEXT_PUBLIC_API_URL=https:\/\/api.newsdatahub.com\/v1\/news<br \/>\nNEXT_PUBLIC_API_TOKEN=your_token_here<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u0633\u067e\u0633 \u0628\u0631\u0627\u06cc \u06a9\u067e\u06cc \u0645\u0648\u0627\u0631\u062f \u0632\u06cc\u0631 \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f .env.example \u0642\u0627\u0644\u0628 \u0628\u0647 .env.local \u06a9\u0647 \u062f\u0631 \u0622\u0646 \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u0648\u0627\u0642\u0639\u06cc \u0634\u0645\u0627 \u062e\u0648\u0627\u0647\u062f \u0628\u0648\u062f<\/p>\n<p>cp .env.example .env.local<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>  \u062c\u0627\u06cc\u06af\u0632\u06cc\u0646 \u06a9\u0646\u06cc\u062f your_token_here \u062f\u0631 .env.local \u0628\u0627 \u062a\u0648\u06a9\u0646 NewsDataHub API \u062e\u0648\u062f \u0627\u0632 \u062f\u0627\u0634\u0628\u0648\u0631\u062f \u062e\u0648\u062f.<\/p>\n<p>.env.example  \u0628\u0647 git \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u06cc\u06a9 \u0627\u0644\u06af\u0648 \u0645\u062a\u0639\u0647\u062f \u0627\u0633\u062a\u060c while .env.local \u062d\u0627\u0648\u06cc \u0627\u0633\u0631\u0627\u0631 \u0648\u0627\u0642\u0639\u06cc \u0627\u0633\u062a \u0648 \u0646\u0627\u062f\u06cc\u062f\u0647 \u06af\u0631\u0641\u062a\u0647 \u0645\u06cc \u0634\u0648\u062f.<\/p>\n<p>\u0647\u0646\u06af\u0627\u0645 \u0627\u0631\u062c\u0627\u0639 \u0628\u0647 \u06a9\u0644\u06cc\u062f API \u0627\u0632 \u06a9\u0644\u0645\u0627\u062a &#8220;token&#8221; \u0648 &#8220;key&#8221; \u0628\u0647 \u062c\u0627\u06cc \u06cc\u06a9\u062f\u06cc\u06af\u0631 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645. \u0647\u0646\u06af\u0627\u0645\u06cc \u06a9\u0647 \u062a\u0648\u06a9\u0646 API \u062e\u0648\u062f \u0631\u0627 \u062f\u0627\u0631\u06cc\u062f\u060c \u0622\u0646 \u0631\u0627 \u0628\u0647 \u067e\u0631\u0648\u0698\u0647 \u062e\u0648\u062f \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f .env.local \u0641\u0627\u06cc\u0644:<\/p>\n<p>NEXT_PUBLIC_API_URL=https:\/\/api.newsdatahub.com\/v1<br \/>\nNEXT_PUBLIC_API_TOKEN=your_newsdatahub_token<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>  \u062a\u0646\u0638\u06cc\u0645\u0627\u062a \u0648 \u0646\u0645\u0627\u06cc \u06a9\u0644\u06cc \u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc<\/p>\n<p>\u0628\u06cc\u0627\u06cc\u06cc\u062f \u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u0636\u0631\u0648\u0631\u06cc \u0631\u0627 \u062a\u0646\u0638\u06cc\u0645 \u06a9\u0646\u06cc\u0645. \u0645\u0646 \u0647\u062f\u0641 \u0648 \u0645\u062d\u062a\u0648\u0627\u06cc \u0647\u0631 \u06cc\u06a9 \u0631\u0627 \u062a\u0648\u0636\u06cc\u062d \u0645\u06cc \u062f\u0647\u0645:<\/p>\n<p>  \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc .gitignore<\/p>\n<p>\u0627\u06cc\u0646 .gitignore \u0641\u0627\u06cc\u0644 \u0628\u0647 \u0637\u0648\u0631 \u062e\u0648\u062f\u06a9\u0627\u0631 \u062f\u0631 \u0637\u0648\u0644 \u0627\u0648\u0644\u06cc\u0647 \u0633\u0627\u0632\u06cc \u067e\u0631\u0648\u0698\u0647 \u0627\u06cc\u062c\u0627\u062f \u0634\u062f. \u0628\u0647 Git \u0645\u06cc \u06af\u0648\u06cc\u062f \u06a9\u062f\u0627\u0645 \u0641\u0627\u06cc\u0644 \u0647\u0627 \u0648 \u067e\u0648\u0634\u0647 \u0647\u0627 \u0631\u0627 \u0627\u0632 \u06a9\u0646\u062a\u0631\u0644 \u0646\u0633\u062e\u0647 \u062d\u0630\u0641 \u06a9\u0646\u062f.<\/p>\n<p>\u0628\u06cc\u0627\u06cc\u06cc\u062f \u0627\u0632 \u062e\u0648\u062f\u0645\u0627\u0646 \u0645\u0637\u0645\u0626\u0646 \u0634\u0648\u06cc\u0645 .env.local \u0641\u0627\u06cc\u0644 \u0628\u0627 \u0627\u0641\u0632\u0648\u062f\u0646 \u0645\u0648\u0627\u0631\u062f \u0632\u06cc\u0631 \u0628\u0647 \u0622\u0646 \u0646\u0627\u062f\u06cc\u062f\u0647 \u06af\u0631\u0641\u062a\u0647 \u0645\u06cc \u0634\u0648\u062f .gitignore.<\/p>\n<p># Environment files<br \/>\n.env*.local<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>  \u062a\u0646\u0638\u06cc\u0645 \u062a\u0639\u0627\u0631\u06cc\u0641 \u0646\u0648\u0639 \u0645\u062d\u06cc\u0637<\/p>\n<p>\u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f types\/env.d.ts \u0628\u0631\u0627\u06cc \u0627\u0631\u0627\u0626\u0647 \u062a\u0639\u0627\u0631\u06cc\u0641 \u0646\u0648\u0639 TypeScript \u0628\u0631\u0627\u06cc \u0645\u062a\u063a\u06cc\u0631\u0647\u0627\u06cc \u0645\u062d\u06cc\u0637\u06cc:<\/p>\n<p>declare global {<br \/>\n  namespace NodeJS {<br \/>\n    interface ProcessEnv {<br \/>\n      NEXT_PUBLIC_API_URL: string;<br \/>\n      NEXT_PUBLIC_API_TOKEN: string;<br \/>\n    }<br \/>\n  }<br \/>\n}<\/p>\n<p>export {};<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u0627\u06cc\u0646 \u0641\u0627\u06cc\u0644 \u0628\u0647 TypeScript \u062f\u0631 \u0645\u0648\u0631\u062f \u0645\u062a\u063a\u06cc\u0631\u0647\u0627\u06cc \u0645\u062d\u06cc\u0637\u06cc \u0645\u0627 \u0645\u06cc \u06af\u0648\u06cc\u062f \u0648 \u0627\u0645\u06a9\u0627\u0646 \u0628\u0631\u0631\u0633\u06cc \u0635\u062d\u06cc\u062d \u0646\u0648\u0639 \u0631\u0627 \u062f\u0631 \u0647\u0646\u06af\u0627\u0645 \u062f\u0633\u062a\u0631\u0633\u06cc \u0641\u0631\u0627\u0647\u0645 \u0645\u06cc \u06a9\u0646\u062f process.env \u0645\u0642\u0627\u062f\u06cc\u0631 \u0648 \u0627\u0631\u0627\u0626\u0647 \u067e\u06cc\u0634\u0646\u0647\u0627\u062f\u0627\u062a \u062a\u06a9\u0645\u06cc\u0644 \u062e\u0648\u062f\u06a9\u0627\u0631. \u0628\u062f\u0648\u0646 \u0622\u0646\u060c TypeScript \u0627\u06cc\u0646 \u0645\u062a\u063a\u06cc\u0631\u0647\u0627 \u0631\u0627 \u0627\u0632 \u0646\u0648\u0639 \u062e\u0648\u062f \u062f\u0631 \u0646\u0638\u0631 \u0645\u06cc \u06af\u06cc\u0631\u062f any .<\/p>\n<p>  \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc ESLint<\/p>\n<p>\u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f .eslintrc.json \u0628\u0631\u0627\u06cc \u0641\u0639\u0627\u0644 \u06a9\u0631\u062f\u0646 \u0642\u0648\u0627\u0646\u06cc\u0646 \u067e\u06cc\u0634\u200c\u0641\u0631\u0636 Next.js \u0628\u0631\u0627\u06cc \u0639\u0645\u0644\u06a9\u0631\u062f \u0648 \u0628\u0647\u062a\u0631\u06cc\u0646 \u0634\u06cc\u0648\u0647\u200c\u0647\u0627.<\/p>\n<p>{<br \/>\n  &#8220;extends&#8221;: [<br \/>\n    &#8220;next\/core-web-vitals&#8221;<br \/>\n  ]\n}<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>  \u062d\u0627\u0644\u0627 \u0628\u06cc\u0627\u06cc\u06cc\u062f \u06a9\u062f \u067e\u0631\u0648\u0698\u0647 \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u0645<\/p>\n<p>\u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f types\/cache.ts.\u0633\u0627\u062e\u062a\u0627\u0631 \u0633\u06cc\u0633\u062a\u0645 \u062d\u0627\u0641\u0638\u0647 \u067e\u0646\u0647\u0627\u0646 \u0633\u0645\u062a \u0633\u0631\u0648\u06cc\u0633 \u06af\u06cc\u0631\u0646\u062f\u0647 \u0645\u0627 \u0631\u0627 \u062a\u0639\u0631\u06cc\u0641 \u0645\u06cc \u06a9\u0646\u062f \u0648 \u0646\u062d\u0648\u0647 \u0630\u062e\u06cc\u0631\u0647 \u0645\u0647\u0631\u0647\u0627\u06cc \u0632\u0645\u0627\u0646\u06cc \u0648 \u062f\u0627\u062f\u0647 \u0647\u0627\u06cc \u062e\u0628\u0631\u06cc \u0631\u0627 \u0645\u0634\u062e\u0635 \u0645\u06cc \u06a9\u0646\u062f.<\/p>\n<p>import { NewsItem } from &#8220;.&#8221;;<\/p>\n<p>export interface CacheData {<br \/>\n    timestamp: number;<br \/>\n    data: NewsItem[];<br \/>\n}<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f types\/crypto.ts.\u0633\u0627\u062e\u062a\u0627\u0631 \u062f\u0627\u062f\u0647 \u0642\u06cc\u0645\u062a \u0627\u0631\u0632\u0647\u0627\u06cc \u062f\u06cc\u062c\u06cc\u062a\u0627\u0644 \u0631\u0627 \u0627\u0632 \u0637\u0631\u06cc\u0642 CoinCap API\u060c \u0627\u0632 \u062c\u0645\u0644\u0647 \u0642\u06cc\u0645\u062a\u060c \u0627\u0631\u0632\u0634 \u0628\u0627\u0632\u0627\u0631 \u0648 \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a 24 \u0633\u0627\u0639\u062a\u0647 \u062a\u0639\u0631\u06cc\u0641 \u0645\u06cc\u200c\u06a9\u0646\u062f.<\/p>\n<p>export type CoinData = {<br \/>\n  [key: string]: {<br \/>\n    usd: number;<br \/>\n    usd_market_cap: number;<br \/>\n    usd_24h_vol: number;<br \/>\n    usd_24h_change: number;<br \/>\n    last_updated_at: number;<br \/>\n  }<br \/>\n}<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f  news.ts\u062d\u0627\u0648\u06cc \u0631\u0627\u0628\u0637\u200c\u0647\u0627\u06cc\u06cc \u0628\u0631\u0627\u06cc \u0645\u0648\u0627\u0631\u062f \u062e\u0628\u0631\u06cc \u0627\u0632 NewsDataHub API \u0648 \u0644\u0648\u0627\u0632\u0645 \u062c\u0627\u0646\u0628\u06cc \u0628\u0631\u0627\u06cc \u0645\u0624\u0644\u0641\u0647 NewsCard \u0645\u0627.<\/p>\n<p>export interface NewsItem {<br \/>\n    id: string;<br \/>\n    title: string;<br \/>\n    article_link: string;<br \/>\n    description: string;<br \/>\n    pub_date: string;<br \/>\n  }<\/p>\n<p>export interface NewsCardProps {<br \/>\n    index: number;<br \/>\n    item: NewsItem;<br \/>\n}<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f types\/index.ts.\u0646\u0642\u0637\u0647 \u0635\u0627\u062f\u0631\u0627\u062a \u0645\u0631\u06a9\u0632\u06cc \u0628\u0631\u0627\u06cc \u0647\u0645\u0647 \u062a\u0639\u0627\u0631\u06cc\u0641 \u0646\u0648\u0639\u060c \u0627\u0645\u06a9\u0627\u0646 \u0648\u0627\u0631\u062f\u0627\u062a \u067e\u0627\u06a9 \u0631\u0627 \u0641\u0631\u0627\u0647\u0645 \u0645\u06cc \u06a9\u0646\u062f.<\/p>\n<p>export * from &#8216;.\/cache&#8217;;<br \/>\nexport * from &#8216;.\/news&#8217;;<br \/>\nexport * from &#8216;.\/crypto&#8217;;<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>  \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0627\u0645\u067e\u0648\u0646\u0646\u062a NewsCard \u0648 PriceTicker<\/p>\n<p>\u062f\u0631 \u0645\u0631\u062d\u0644\u0647 \u0628\u0639\u062f\u060c \u0645\u0627 \u0627\u062c\u0632\u0627\u06cc \u062e\u0648\u062f \u0648 \u0633\u0628\u06a9 \u0622\u0646\u0647\u0627 \u0631\u0627 \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u0645\u06cc \u06a9\u0646\u06cc\u0645. \u0647\u0631 \u062c\u0632\u0621 \u0628\u0627\u06cc\u062f \u062f\u0631 \u062f\u0627\u06cc\u0631\u06a9\u062a\u0648\u0631\u06cc \u0645\u0631\u0628\u0648\u0637\u0647 \u062e\u0648\u062f \u0628\u0627\u0634\u062f.<\/p>\n<p>  \u062c\u0632\u0621 NewsCard<\/p>\n<p>app\/components\/news-feed\/NewsCard.tsx<\/p>\n<p>import styles from &#8216;.\/styles.module.css&#8217;;<br \/>\nimport { NewsCardProps } from &#8216;@\/types&#8217;;<\/p>\n<p>export const NewsCard: React.FC&lt;NewsCardProps&gt; = ({index, item}) =&gt; {<br \/>\n    return (<br \/>\n        &lt;div key={index} className={styles.newsCard}&gt;<br \/>\n        &lt;h2 className={styles.newsTitle}&gt;{item.title}h2&gt;<br \/>\n        &lt;p&gt;{item.description.slice(0, 200)+&#8221;&#8230;&#8221;} Read more<br \/>\n        &lt;br\/&gt;<br \/>\n        &lt;br\/&gt;<br \/>\n            &lt;a href={item.article_link} target=&#8221;_blank&#8221;  rel=&#8221;noopener noreferrer&#8221; className={styles.newsLink}&gt;<br \/>\n            {item.article_link}<br \/>\n            a&gt;<br \/>\n        p&gt;<\/p>\n<p>        &lt;div className={styles.newsDate}&gt;<br \/>\n          {new Date(item.pub_date).toLocaleDateString()}<br \/>\n        div&gt;<br \/>\n      div&gt;<br \/>\n    )<br \/>\n}<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>app\/components\/news-feed\/styles.module.css<\/p>\n<p>.newsCard {<br \/>\n  padding: 15px;<br \/>\n  border: 1px solid #ddd;<br \/>\n  border-radius: 4px;<br \/>\n  margin-bottom: 15px;<br \/>\n}<\/p>\n<p>.newsTitle {<br \/>\n  margin: 0 0 10px 0;<br \/>\n  font-size: 1.2em;<br \/>\n  color: #2e009a;<br \/>\n  font-family: math;<br \/>\n}<\/p>\n<p>.newsDate {<br \/>\n  color: #666;<br \/>\n  font-size: 0.9em;<br \/>\n  margin-top: 10px;<br \/>\n}<\/p>\n<p>.newsLink {<br \/>\n  color:darkcyan;<br \/>\n}<\/p>\n<p>.newsLink:hover {<br \/>\n  color: rgb(3, 79, 79);<br \/>\n  cursor: pointer;<br \/>\n  text-decoration: underline;<br \/>\n}<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>app\/components\/news-feed\/index.tsx<\/p>\n<p>export { NewsCard } from &#8216;.\/NewsCard&#8217;;<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>  \u06a9\u0627\u0645\u067e\u0648\u0646\u0646\u062a PriceTicker<\/p>\n<p>app\/components\/price-ticker\/PriceTicker.tsx<\/p>\n<p>import { useState, useEffect } from &#8216;react&#8217;;<br \/>\nimport styles from &#8216;.\/styles.module.css&#8217;;<br \/>\nimport { CoinData } from &#8216;@\/types&#8217;;<\/p>\n<p>export const  PriceTicker = () =&gt; {<br \/>\n  const [prices, setPrices] = useState&lt;CoinData&gt;({});<br \/>\n  const [error, setError] = useState&lt;string | null&gt;(null);<br \/>\n  const [loading, setLoading] = useState(true);<\/p>\n<p>  const fetchPrices = async () =&gt; {<br \/>\n    try {<br \/>\n      const response = await fetch(&#8216;https:\/\/api.coingecko.com\/api\/v3\/simple\/price?ids=bitcoin,ethereum,dogecoin&amp;vs_currencies=usd&amp;include_24hr_change=true&#8217;);<br \/>\n      if (!response.ok) throw new Error(&#8216;Failed to fetch prices&#8217;);<\/p>\n<p>      const data = await response.json();<\/p>\n<p>      setPrices(data);<br \/>\n      setError(null);<br \/>\n    } catch (err) {<br \/>\n      setError(&#8216;Failed to load prices&#8217;);<br \/>\n      console.error(&#8216;Price fetch error:&#8217;, err);<br \/>\n    } finally {<br \/>\n      setLoading(false);<br \/>\n    }<br \/>\n  };<\/p>\n<p>  useEffect(() =&gt; {<br \/>\n    fetchPrices();<br \/>\n    const interval = setInterval(fetchPrices, 60000); \/\/ Update every minute<br \/>\n    return () =&gt; clearInterval(interval);<br \/>\n  }, []);<\/p>\n<p>  if (loading) return &lt;div className={styles.ticker}&gt;Loading prices&#8230;div&gt;;<br \/>\n  if (error) return &lt;div className={styles.ticker}&gt;Price data unavailablediv&gt;;<\/p>\n<p>  return (<br \/>\n    &lt;div className={styles.ticker}&gt;<br \/>\n      {Object.entries(prices).map(([coinId, data]) =&gt; {<br \/>\n        const price = data.usd.toLocaleString(&#8216;en-US&#8217;, {<br \/>\n          style: &#8216;currency&#8217;,<br \/>\n          currency: &#8216;USD&#8217;,<br \/>\n          minimumFractionDigits: 2,<br \/>\n          maximumFractionDigits: 2<br \/>\n        });<\/p>\n<p>        const change = data.usd_24h_change || 0;<br \/>\n        const changeClass = change &gt;= 0 ? styles.positive : styles.negative;<\/p>\n<p>        return (<br \/>\n            &lt;div key={coinId} className={styles.cryptoPrice}&gt;<br \/>\n              &lt;span className={styles.symbol}&gt;{coinId.toUpperCase()}span&gt;<br \/>\n              &lt;span className={styles.price}&gt;{price}span&gt;<br \/>\n              &lt;span className={`${styles.change} ${changeClass}`}&gt;<br \/>\n       {change &gt;= 0 ? &#8216;\u2191&#8217; : &#8216;\u2193&#8217;}<br \/>\n                {Math.abs(change).toFixed(2)}%<br \/>\n     span&gt;<br \/>\n            div&gt;<br \/>\n        );<br \/>\n      })}<br \/>\n    div&gt;<br \/>\n);<br \/>\n}<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>app\/components\/price-ticker\/styles.module.css<\/p>\n<p>.ticker {<br \/>\n  background: #1a1a1a;<br \/>\n  color: white;<br \/>\n  padding: 10px;<br \/>\n  border-radius: 8px;<br \/>\n  margin-bottom: 20px;<br \/>\n  overflow-x: auto;<br \/>\n  display: flex;<br \/>\n  gap: 20px;<br \/>\n  align-items: center;<br \/>\n}<\/p>\n<p>.cryptoPrice {<br \/>\n  display: flex;<br \/>\n  align-items: center;<br \/>\n  gap: 8px;<br \/>\n  padding: 4px 8px;<br \/>\n  background: rgba(255, 255, 255, 0.1);<br \/>\n  border-radius: 4px;<br \/>\n  white-space: nowrap;<br \/>\n}<\/p>\n<p>.symbol {<br \/>\n  font-weight: bold;<br \/>\n  color: #ffd700;<br \/>\n}<\/p>\n<p>.price {<br \/>\n  font-family: monospace;<br \/>\n}<\/p>\n<p>.change {<br \/>\n  font-size: 0.9em;<br \/>\n  padding: 2px 6px;<br \/>\n  border-radius: 4px;<br \/>\n}<\/p>\n<p>.positive {<br \/>\n  color: #00ff00;<br \/>\n}<\/p>\n<p>.negative {<br \/>\n  color: #ff4444;<br \/>\n}<\/p>\n<p>@keyframes slide {<br \/>\n  0% {<br \/>\n    transform: translateX(100%);<br \/>\n  }<br \/>\n  100% {<br \/>\n    transform: translateX(-100%);<br \/>\n  }<br \/>\n}<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>app\/components\/news-feed\/index.tsx<\/p>\n<p>export { PriceTicker } from &#8216;.\/PriceTicker&#8217;;<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>  \u0633\u0627\u062e\u062a \u0645\u0624\u0644\u0641\u0647 \u0635\u0641\u062d\u0647 \u0627\u0635\u0644\u06cc<\/p>\n<p>\u062f\u0631 Next.js App Router\u060c \u0635\u0641\u062d\u0647 \u0627\u0635\u0644\u06cc \u0628\u0631\u0646\u0627\u0645\u0647 \u0645\u0627 \u062f\u0631 \u0622\u0646 \u0642\u0631\u0627\u0631 \u062f\u0627\u0631\u062f app\/page.tsx. \u062f\u0631 \u062d\u0627\u0644\u06cc \u06a9\u0647 \u0641\u0627\u06cc\u0644 \u0642\u0631\u0627\u0631 \u0627\u0633\u062a \u0646\u0627\u0645\u06af\u0630\u0627\u0631\u06cc \u0634\u0648\u062f page.tsx \u0628\u0647 \u062f\u0646\u0628\u0627\u0644 \u0642\u0631\u0627\u0631\u062f\u0627\u062f\u0647\u0627\u06cc Next.js\u060c \u06a9\u0627\u0645\u067e\u0648\u0646\u0646\u062a \u062e\u0648\u062f \u0631\u0627 \u0646\u0627\u0645\u06af\u0630\u0627\u0631\u06cc \u0645\u06cc \u06a9\u0646\u06cc\u0645 Home \u062a\u0627 \u0628\u0647 \u0648\u0636\u0648\u062d \u0647\u062f\u0641 \u0622\u0646 \u0631\u0627 \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0635\u0641\u062d\u0647 \u0627\u0635\u0644\u06cc \u0628\u0631\u0646\u0627\u0645\u0647 \u0645\u0627 \u0646\u0634\u0627\u0646 \u062f\u0647\u062f.<\/p>\n<p>\u067e\u06cc\u0634 \u0628\u0631\u0648\u06cc\u062f \u0648 \u0628\u0647 \u0631\u0648\u0632 \u06a9\u0646\u06cc\u062f  app\/components\/page.tsx \u0628\u0627 \u06a9\u062f \u0632\u06cc\u0631<\/p>\n<p>&#8216;use client&#8217;;<\/p>\n<p>import { useState, useEffect } from &#8216;react&#8217;;<br \/>\nimport { PriceTicker } from &#8216;@\/app\/components\/price-ticker&#8217;;<br \/>\nimport { NewsCard } from &#8216;@\/app\/components\/news-feed&#8217;;<br \/>\nimport { CacheData, NewsItem } from &#8216;@\/types&#8217;;<br \/>\nimport styles from &#8216;.\/page.module.css&#8217;;<\/p>\n<p>\/\/ Environment variables for API configuration<br \/>\nconst API_URL = process.env.NEXT_PUBLIC_API_URL;<br \/>\nconst API_TOKEN = process.env.NEXT_PUBLIC_API_TOKEN;<\/p>\n<p>\/\/ Cache duration set to one hour<br \/>\nconst CACHE_DURATION = 1000 * 60 * 60;<br \/>\nconst TOPICS = [&#8216;cryptocurrency&#8217;];<\/p>\n<p>\/\/ In-memory cache for storing news data<br \/>\nconst cache: Record&lt;string, CacheData&gt; = {};<\/p>\n<p>export default function Home() {<br \/>\n  \/\/ State management using React hooks<br \/>\n  const [news, setNews] = useState&lt;NewsItem[]&gt;([]);<br \/>\n  const [loading, setLoading] = useState(false);<br \/>\n  const [error, setError] = useState&lt;string | null&gt;(null);<br \/>\n  const [lastUpdated, setLastUpdated] = useState&lt;Date | null&gt;(null);<\/p>\n<p>  \/\/ Fetches news data with built-in caching<br \/>\n  const fetchNews = async (topics: string[]) =&gt; {<br \/>\n    const cacheKey = topics.sort().join(&#8216;,&#8217;);<br \/>\n    const cachedData = cache[cacheKey];<\/p>\n<p>    if (cachedData &amp;&amp; Date.now() &#8211; cachedData.timestamp &lt; CACHE_DURATION) {<br \/>\n      setNews(cachedData.data);<br \/>\n      setLastUpdated(new Date(cachedData.timestamp));<br \/>\n      return;<br \/>\n    }<\/p>\n<p>    setLoading(true);<br \/>\n    setError(null);<\/p>\n<p>    try {<br \/>\n      const response = await fetch(`${API_URL}?language=en&amp;topic=cryptocurrency`, {<br \/>\n        headers: {<br \/>\n          &#8216;x-api-key&#8217;: API_TOKEN,<br \/>\n          &#8216;Content-Type&#8217;: &#8216;application\/json&#8217;<br \/>\n        },<br \/>\n      });<\/p>\n<p>      if (!response.ok) throw new Error(&#8216;Failed to fetch news&#8217;);<\/p>\n<p>      const articles = await response.json();<br \/>\n      const data: NewsItem[] = articles.data;<\/p>\n<p>      cache[cacheKey] = {<br \/>\n        timestamp: Date.now(),<br \/>\n        data<br \/>\n      };<\/p>\n<p>      setNews(data);<br \/>\n      setLastUpdated(new Date());<br \/>\n    } catch (err) {<br \/>\n      setError(err instanceof Error ? err.message : &#8216;An error occurred&#8217;);<br \/>\n    } finally {<br \/>\n      setLoading(false);<br \/>\n    }<br \/>\n  };<\/p>\n<p>  \/\/ Fetch data when component mounts<br \/>\n  useEffect(() =&gt; {<br \/>\n    fetchNews(TOPICS);<br \/>\n  }, []);<\/p>\n<p>  \/\/ Handler for manual refresh<br \/>\n  const handleRefresh = () =&gt; {<br \/>\n    const cacheKey = TOPICS.sort().join(&#8216;,&#8217;);<br \/>\n    delete cache[cacheKey];<br \/>\n    fetchNews(TOPICS);<br \/>\n  };<\/p>\n<p>  return (<br \/>\n    &lt;div className={styles.container}&gt;<br \/>\n      &lt;PriceTicker \/&gt;<\/p>\n<p>      {lastUpdated &amp;&amp; (<br \/>\n        &lt;div className={styles.lastUpdated}&gt;<br \/>\n          Last updated: {lastUpdated.toLocaleTimeString()}<br \/>\n          &lt;button onClick={handleRefresh} className={styles.refreshButton}&gt;<br \/>\n            Refresh<br \/>\n          button&gt;<br \/>\n        div&gt;<br \/>\n      )}<\/p>\n<p>      {error &amp;&amp; &lt;div className={styles.error}&gt;{error}div&gt;}<\/p>\n<p>      {loading ? (<br \/>\n        &lt;div className={styles.loading}&gt;Loading&#8230;div&gt;<br \/>\n      ) : (<br \/>\n        news.map((item: NewsItem, index: number) =&gt; (<br \/>\n          &lt;NewsCard key={item.id || index} item={item} index={index} \/&gt;<br \/>\n        ))<br \/>\n      )}<br \/>\n    div&gt;<br \/>\n  );<br \/>\n}<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc page.module.css  \u0628\u0627 \u0633\u0628\u06a9 \u0647\u0627\u06cc \u0632\u06cc\u0631<\/p>\n<p>.container {<br \/>\n  max-width: 800px;<br \/>\n  margin: 0 auto;<br \/>\n  padding: 20px;<br \/>\n}<\/p>\n<p>.topics {<br \/>\n  margin-bottom: 20px;<br \/>\n}<\/p>\n<p>.topic {<br \/>\n  margin-right: 10px;<br \/>\n  padding: 5px 10px;<br \/>\n  border: 1px solid #ddd;<br \/>\n  border-radius: 4px;<br \/>\n  background: none;<br \/>\n  cursor: pointer;<br \/>\n}<\/p>\n<p>.topicSelected {<br \/>\n  background: #007bff;<br \/>\n  color: white;<br \/>\n  border-color: #007bff;<br \/>\n}<\/p>\n<p>.error {<br \/>\n  color: #dc3545;<br \/>\n  padding: 10px;<br \/>\n  border: 1px solid #dc3545;<br \/>\n  border-radius: 4px;<br \/>\n  margin-bottom: 15px;<br \/>\n}<\/p>\n<p>.loading {<br \/>\n  text-align: center;<br \/>\n  padding: 20px;<br \/>\n}<\/p>\n<p>.lastUpdated {<br \/>\n  color: #666;<br \/>\n  font-size: 0.9em;<br \/>\n  margin-bottom: 15px;<br \/>\n}<\/p>\n<p>.refreshButton {<br \/>\n  background: #007bff;<br \/>\n  color: white;<br \/>\n  border: none;<br \/>\n  padding: 5px 10px;<br \/>\n  border-radius: 4px;<br \/>\n  cursor: pointer;<br \/>\n  margin-left: 10px;<br \/>\n}<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc app\/layout.tsx \u0628\u0627 \u0645\u0648\u0627\u0631\u062f \u0632\u06cc\u0631:<\/p>\n<p>export default function RootLayout({<br \/>\n  children,<br \/>\n}: {<br \/>\n  children: React.ReactNode<br \/>\n}) {<br \/>\n  return (<br \/>\n    &lt;html lang=&#8221;en&#8221;&gt;<br \/>\n      &lt;head&gt;<br \/>\n        &lt;title&gt;Crypto News Aggregator Applicationtitle&gt;<br \/>\n        &lt;meta name=&#8221;description&#8221; content=&#8221;Crypto News Aggregator Application&#8221; \/&gt;<br \/>\n      head&gt;<br \/>\n      &lt;body&gt;<br \/>\n        {children}<br \/>\n      body&gt;<br \/>\n    html&gt;<br \/>\n  )<br \/>\n}<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>  \u0627\u062c\u0631\u0627\u06cc \u067e\u0631\u0648\u0698\u0647 \u0634\u0645\u0627<\/p>\n<p>\u0627\u062f\u0627\u0645\u0647 \u062f\u0647\u06cc\u062f \u0648 \u067e\u0631\u0648\u0698\u0647 \u062e\u0648\u062f \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f<\/p>\n<p>npm run dev<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u0628\u0631\u0646\u0627\u0645\u0647 \u062f\u0631 \u062d\u0627\u0644 \u0627\u062c\u0631\u0627 \u062e\u0648\u062f \u0631\u0627 \u062f\u0631 https:\/\/localhost:3000 \u067e\u06cc\u062f\u0627 \u06a9\u0646\u06cc\u062f<\/p>\n<p>\u0628\u0627\u0628\u062a \u0627\u062a\u0645\u0627\u0645 \u067e\u0631\u0648\u0698\u0647 \u062a\u0628\u0631\u06cc\u06a9 \u0645\u06cc \u06af\u0648\u06cc\u0645! \ud83c\udfc6 \ud83d\udc4f<\/p>\n<p>  \u062a\u0633\u062a \u06a9\u0627\u0645\u067e\u0648\u0646\u0646\u062a \u0635\u0641\u062d\u0647<\/p>\n<p>\u0645\u0627 \u0645\u06cc\u200c\u062e\u0648\u0627\u0647\u06cc\u0645 \u0622\u0632\u0645\u0627\u06cc\u0634\u06cc \u0628\u0631\u0627\u06cc \u0645\u0624\u0644\u0641\u0647 Home \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u0645 \u06a9\u0647 \u062a\u0623\u06cc\u06cc\u062f \u0645\u06cc\u200c\u06a9\u0646\u062f \u06a9\u0647 \u0645\u062d\u062a\u0648\u0627\u06cc \u0627\u062e\u0628\u0627\u0631 \u067e\u0633 \u0627\u0632 \u0648\u0627\u06a9\u0634\u06cc \u062f\u0627\u062f\u0647\u200c\u0647\u0627 \u0628\u0647 \u062f\u0631\u0633\u062a\u06cc \u0627\u0631\u0627\u0626\u0647 \u0645\u06cc\u200c\u0634\u0648\u062f. \u0627\u062f\u0627\u0645\u0647 \u062f\u0647\u06cc\u062f \u0648 \u0627\u06cc\u0646 \u0641\u0627\u06cc\u0644 \u0622\u0632\u0645\u0627\u06cc\u0634\u06cc \u0631\u0627 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f.<\/p>\n<p>__tests__\/Home.test.tsx<\/p>\n<p>import { render, screen, waitFor } from &#8216;@testing-library\/react&#8217;;<br \/>\nimport Home from &#8216;@\/app\/page&#8217;;<\/p>\n<p>describe(&#8216;Home&#8217;, () =&gt; {<br \/>\n  beforeEach(() =&gt; {<br \/>\n    \/\/ Set up test environment variables<br \/>\n    process.env.NEXT_PUBLIC_API_URL = &#8216;http:\/\/test-api.com&#8217;;<br \/>\n    process.env.NEXT_PUBLIC_API_TOKEN = &#8216;test-token&#8217;;<\/p>\n<p>    \/\/ Mock fetch for both API endpoints<br \/>\n    global.fetch = jest.fn((url) =&gt; {<br \/>\n      \/\/ Mock responses for different API calls<br \/>\n      if (url.includes(&#8216;api.coingecko.com&#8217;)) {<br \/>\n        return Promise.resolve({<br \/>\n          ok: true,<br \/>\n          json: () =&gt; Promise.resolve({<br \/>\n            bitcoin: { usd: 65000, usd_24h_change: 2.5 }<br \/>\n          }),<br \/>\n          status: 200,<br \/>\n        } as Response);<br \/>\n      }<br \/>\n      return Promise.resolve({<br \/>\n        ok: true,<br \/>\n        json: () =&gt; Promise.resolve({<br \/>\n          data: [{<br \/>\n            id: &#8216;1&#8217;,<br \/>\n            title: &#8216;News Title&#8217;,<br \/>\n            description: &#8216;News Description&#8217;,<br \/>\n            url: &#8216;https:\/\/test.com&#8217;,<br \/>\n            published_at: &#8216;2024-03-25&#8217;<br \/>\n          }]\n        }),<br \/>\n        status: 200,<br \/>\n      } as Response);<br \/>\n    }) as jest.Mock;<br \/>\n  });<\/p>\n<p>  test(&#8216;renders news feed&#8217;, async () =&gt; {<br \/>\n    render(&lt;Home \/&gt;);<br \/>\n    await waitFor(<br \/>\n      () =&gt; expect(screen.getByText(&#8220;News Title&#8221;)).toBeInTheDocument(),<br \/>\n      { timeout: 3000 }<br \/>\n    );<br \/>\n  });<br \/>\n});<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u062a\u0633\u062a \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f<\/p>\n<p>npm run test<\/p>\n<p>    \u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/p>\n<p>    \u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/p>\n<p>\u0627\u06cc\u0646 \u0622\u0632\u0645\u0627\u06cc\u0634 \u062a\u0623\u06cc\u06cc\u062f \u0645\u06cc\u200c\u06a9\u0646\u062f \u06a9\u0647 \u0645\u0624\u0644\u0641\u0647 Home \u0645\u0627 \u0628\u0627 \u0645\u0648\u0641\u0642\u06cc\u062a \u0645\u062d\u062a\u0648\u0627\u06cc \u0627\u062e\u0628\u0627\u0631 \u0631\u0627 \u067e\u0633 \u0627\u0632 \u0648\u0627\u06a9\u0634\u06cc \u062f\u0627\u062f\u0647\u200c\u0647\u0627 \u0627\u0631\u0627\u0626\u0647 \u0645\u06cc\u200c\u06a9\u0646\u062f. <\/p>\n<p>\u062a\u0633\u062a \u0647\u0627\u06cc \u0627\u0636\u0627\u0641\u06cc \u0628\u0631\u0627\u06cc \u0627\u062c\u0632\u0627\u06cc PriceTicker \u0648 NewsCard \u0631\u0627 \u0645\u06cc \u062a\u0648\u0627\u0646 \u062f\u0631 \u0645\u062e\u0632\u0646 GitHub \u067e\u0631\u0648\u0698\u0647 \u06cc\u0627\u0641\u062a. \u0627\u06cc\u0646 \u062a\u0633\u062a\u200c\u0647\u0627 \u0639\u0645\u0644\u06a9\u0631\u062f \u0648 \u0631\u0641\u062a\u0627\u0631 \u0631\u0646\u062f\u0631\u06cc\u0646\u06af \u0631\u0627 \u067e\u0648\u0634\u0634 \u0645\u06cc\u200c\u062f\u0647\u0646\u062f. \u0645\u0646 \u0634\u0645\u0627 \u0631\u0627 \u062a\u0634\u0648\u06cc\u0642 \u0645\u06cc \u06a9\u0646\u0645 \u06a9\u0647 \u062a\u0633\u062a \u0647\u0627\u06cc \u0628\u06cc\u0634\u062a\u0631\u06cc \u0628\u0631\u0627\u06cc \u0627\u06cc\u0646 \u067e\u0631\u0648\u0698\u0647 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f.<\/p>\n<p>  \u0628\u0647\u0628\u0648\u062f \u0628\u06cc\u0634\u062a\u0631 \u0627\u06cc\u0646 \u067e\u0631\u0648\u0698\u0647 \u0631\u0627 \u062f\u0631 \u0646\u0638\u0631 \u0628\u06af\u06cc\u0631\u06cc\u062f.<\/p>\n<p>\u0686\u0646\u062f \u0627\u06cc\u062f\u0647:<\/p>\n<p>\u0627\u062c\u0631\u0627\u06cc \u062d\u0627\u0644\u062a \u0647\u0627\u06cc \u0628\u0627\u0631\u06af\u0630\u0627\u0631\u06cc \u0645\u0646\u0627\u0633\u0628<br \/>\n\u0635\u0641\u062d\u0647 \u0628\u0646\u062f\u06cc \u0628\u0631\u0627\u06cc \u0627\u062e\u0628\u0627\u0631 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f<br \/>\n\u0630\u062e\u06cc\u0631\u0647 \u0633\u0627\u0632\u06cc \u067e\u06cc\u0686\u06cc\u062f\u0647 \u062a\u0631\u06cc \u0631\u0627 \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0646\u06cc\u062f<br \/>\n\u0645\u062c\u0645\u0648\u0639\u0647 \u0622\u0632\u0645\u0627\u06cc\u0634\u06cc \u0631\u0627 \u062a\u0642\u0648\u06cc\u062a \u06a9\u0646\u06cc\u062f<br \/>\n\u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u067e\u0627\u0631\u0627\u0645\u062a\u0631 \u067e\u0631\u0633 \u0648 \u062c\u0648 \u0645\u0648\u0636\u0648\u0639 \u0631\u0627 \u0628\u0631\u0627\u06cc \u0648\u0627\u06a9\u0634\u06cc \u0627\u0646\u0648\u0627\u0639 \u0645\u062e\u062a\u0644\u0641 \u0627\u062e\u0628\u0627\u0631 \u062a\u063a\u06cc\u06cc\u0631 \u062f\u0647\u06cc\u062f<\/p>\n<p>  \u0627\u0632 \u0627\u06cc\u0646\u06a9\u0647 \u062f\u0646\u0628\u0627\u0644 \u0645\u06cc \u06a9\u0646\u06cc\u062f \u0645\u062a\u0634\u06a9\u0631\u0645 \ud83d\ude04<\/p>\n<p>\u0627\u0639\u062a\u0628\u0627\u0631 \u062a\u0635\u0648\u06cc\u0631 \u062c\u0644\u062f: \u0639\u06a9\u0633 \u062a\u0648\u0633\u0637 \u067e\u0631\u0648\u0698\u0647 \u0633\u0647\u0627\u0645 RDNE: https:\/\/www.pexels.com\/photo\/selective-focus-photo-of-silver-and-gold-bitcoins-8369648\/<\/p>\n<div data-article-id=\"2161683\" id=\"article-body\">\n<p>\u062f\u0631 \u0627\u06cc\u0646 \u0645\u0642\u0627\u0644\u0647\u060c \u0645\u06cc\u200c\u062e\u0648\u0627\u0647\u06cc\u0645 \u06cc\u06a9 \u0628\u0631\u0646\u0627\u0645\u0647 \u0633\u0627\u062f\u0647 \u0627\u0645\u0627 \u0645\u0641\u06cc\u062f \u0628\u0631\u0627\u06cc \u062c\u0645\u0639\u200c\u0622\u0648\u0631\u06cc \u0627\u062e\u0628\u0627\u0631 \u0627\u0631\u0632\u0647\u0627\u06cc \u062f\u06cc\u062c\u06cc\u062a\u0627\u0644 \u0628\u0633\u0627\u0632\u06cc\u0645 \u06a9\u0647 \u0627\u0632 NewsDataHub \u0648 API\u0647\u0627\u06cc CoinGecko \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc\u200c\u06a9\u0646\u062f. \u0647\u062f\u0641 \u0627\u06cc\u0646 \u0645\u0642\u0627\u0644\u0647 \u06cc\u06a9 \u062a\u0648\u0633\u0639\u0647\u200c\u062f\u0647\u0646\u062f\u0647 \u0633\u0637\u062d \u0645\u0628\u062a\u062f\u06cc \u0627\u0633\u062a &#8211; \u0627\u06af\u0631 \u0641\u06a9\u0631 \u0645\u06cc\u200c\u06a9\u0646\u06cc\u062f \u0647\u0631 \u0628\u062e\u0634 \u0627\u0631\u0632\u0634\u06cc \u0628\u0647 \u062a\u062c\u0631\u0628\u0647 \u06cc\u0627\u062f\u06af\u06cc\u0631\u06cc \u0634\u0645\u0627 \u0646\u0645\u06cc\u200c\u0627\u0641\u0632\u0627\u06cc\u062f\u060c \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u06cc\u062f \u0627\u0632 \u0622\u0646 \u0635\u0631\u0641\u0646\u0638\u0631 \u06a9\u0646\u06cc\u062f.<\/p>\n<p>\u0647\u0645\u0686\u0646\u06cc\u0646 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u0628\u0628\u06cc\u0646\u06cc\u062f \u06a9\u0647 \u06a9\u062f \u0646\u0647\u0627\u06cc\u06cc \u067e\u0631\u0648\u0698\u0647 \u0686\u06af\u0648\u0646\u0647 \u0627\u0633\u062a: https:\/\/github.com\/newsdatahub\/crypto-news-aggregator<\/p>\n<p>\u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u0628\u0628\u06cc\u0646\u06cc\u062f \u06a9\u0647 \u0646\u0633\u062e\u0647 \u062a\u0648\u0644\u06cc\u062f\u06cc \u0627\u06cc\u0646 \u0628\u0631\u0646\u0627\u0645\u0647 \u062f\u0642\u06cc\u0642\u0627\u064b \u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u0686\u06af\u0648\u0646\u0647 \u0627\u0633\u062a: https:\/\/newsdatahub.com\/crypto<\/p>\n<p>\u0628\u06cc\u0627\u06cc\u06cc\u062f \u0628\u0627 \u0627\u06cc\u062c\u0627\u062f \u06cc\u06a9 \u067e\u0631\u0648\u0698\u0647 Next.js \u062c\u062f\u06cc\u062f \u0628\u0627 \u067e\u0634\u062a\u06cc\u0628\u0627\u0646\u06cc Typescript \u0634\u0631\u0648\u0639 \u06a9\u0646\u06cc\u0645.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"nx\">npx<\/span> <span class=\"nx\">create<\/span><span class=\"o\">-<\/span><span class=\"nx\">next<\/span><span class=\"o\">-<\/span><span class=\"nx\">app<\/span><span class=\"p\">@<\/span><span class=\"nd\">latest<\/span> <span class=\"nx\">crypto<\/span><span class=\"o\">-<\/span><span class=\"nx\">news<\/span><span class=\"o\">-<\/span><span class=\"nx\">aggregator<\/span> <span class=\"o\">--<\/span><span class=\"nx\">typescript<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0648\u0642\u062a\u06cc \u0627\u0632 \u0634\u0645\u0627 \u062e\u0648\u0627\u0633\u062a\u0647 \u0634\u062f\u060c \u0627\u0646\u062a\u062e\u0627\u0628 \u06a9\u0646\u06cc\u062f:<\/p>\n<ul>\n<li>\u0628\u0631\u0627\u06cc ESLint \u0628\u0644\u0647<\/li>\n<li>\u0646\u0647 \u0628\u0631\u0627\u06cc Tailwind CSS (\u0645\u0627 \u0627\u0632 \u0645\u0627\u0698\u0648\u0644\u200c\u0647\u0627\u06cc CSS \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u062e\u0648\u0627\u0647\u06cc\u0645 \u06a9\u0631\u062f)<\/li>\n<li>\u0646\u0647 \u0628\u0631\u0627\u06cc <code>src\/<\/code> \u062f\u0627\u06cc\u0631\u06a9\u062a\u0648\u0631\u06cc<\/li>\n<li>\u0628\u0631\u0627\u06cc App Router \u0628\u0644\u0647<\/li>\n<li>\u0646\u0647 \u0628\u0631\u0627\u06cc \u062a\u0648\u0631\u0628\u0648\u067e\u06a9<\/li>\n<li>\u0646\u0647 \u0628\u0631\u0627\u06cc \u0633\u0641\u0627\u0631\u0634\u06cc \u06a9\u0631\u062f\u0646 \u0646\u0627\u0645 \u0645\u0633\u062a\u0639\u0627\u0631 \u0648\u0627\u0631\u062f\u0627\u062a (\u0645\u0627 \u0627\u06cc\u0646 \u0631\u0627 \u0628\u0647 \u0635\u0648\u0631\u062a \u062f\u0633\u062a\u06cc \u062a\u0646\u0638\u06cc\u0645 \u0645\u06cc \u06a9\u0646\u06cc\u0645)<\/li>\n<\/ul>\n<p>cd \u062f\u0631 \u067e\u0648\u0634\u0647 \u067e\u0631\u0648\u0698\u0647:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"nx\">cd<\/span> <span class=\"nx\">crypto<\/span><span class=\"o\">-<\/span><span class=\"nx\">news<\/span><span class=\"o\">-<\/span><span class=\"nx\">aggregator<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_84 counter-hierarchy ez-toc-counter-rtl ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">\u0641\u0647\u0631\u0633\u062a \u0645\u0637\u0627\u0644\u0628<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%D8%B1%D8%A7%D9%87_%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C_%D8%B3%D8%A7%D8%AE%D8%AA%D8%A7%D8%B1_%D9%BE%D8%B1%D9%88%DA%98%D9%87\" >\u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0633\u0627\u062e\u062a\u0627\u0631 \u067e\u0631\u0648\u0698\u0647<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%D9%81%D8%A7%DB%8C%D9%84_%D9%87%D8%A7%DB%8C%DB%8C_%DA%A9%D9%87_%D9%85%DB%8C_%D8%AA%D9%88%D8%A7%D9%86_%D8%A8%D8%A7_%D8%AE%DB%8C%D8%A7%D9%84_%D8%B1%D8%A7%D8%AD%D8%AA_%D9%BE%D8%A7%DA%A9_%DA%A9%D8%B1%D8%AF\" >\u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc\u06cc \u06a9\u0647 \u0645\u06cc \u062a\u0648\u0627\u0646 \u0628\u0627 \u062e\u06cc\u0627\u0644 \u0631\u0627\u062d\u062a \u067e\u0627\u06a9 \u06a9\u0631\u062f<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%D8%AA%D8%B3%D8%AA_%DA%A9%D8%B1%D8%AF%D9%86\" >\u062a\u0633\u062a \u06a9\u0631\u062f\u0646<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%D8%AF%D8%B1%DB%8C%D8%A7%D9%81%D8%AA_%D9%86%D8%B4%D8%A7%D9%86%D9%87_API_NewsDataHub_%D8%B4%D9%85%D8%A7\" >\u062f\u0631\u06cc\u0627\u0641\u062a \u0646\u0634\u0627\u0646\u0647 API NewsDataHub \u0634\u0645\u0627<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%D8%A7%D9%81%D8%B2%D9%88%D8%AF%D9%86_%DA%A9%D9%84%DB%8C%D8%AF_API_%D8%A8%D9%87_%D9%BE%D8%B1%D9%88%DA%98%D9%87_%D8%B4%D9%85%D8%A7\" >\u0627\u0641\u0632\u0648\u062f\u0646 \u06a9\u0644\u06cc\u062f API \u0628\u0647 \u067e\u0631\u0648\u0698\u0647 \u0634\u0645\u0627<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%D8%AC%D8%A7%DB%8C%DA%AF%D8%B2%DB%8C%D9%86_%DA%A9%D9%86%DB%8C%D8%AF_your_token_here_%D8%AF%D8%B1_envlocal_%D8%A8%D8%A7_%D8%AA%D9%88%DA%A9%D9%86_NewsDataHub_API_%D8%AE%D9%88%D8%AF_%D8%A7%D8%B2_%D8%AF%D8%A7%D8%B4%D8%A8%D9%88%D8%B1%D8%AF_%D8%AE%D9%88%D8%AF\" >\u062c\u0627\u06cc\u06af\u0632\u06cc\u0646 \u06a9\u0646\u06cc\u062f your_token_here \u062f\u0631 .env.local \u0628\u0627 \u062a\u0648\u06a9\u0646 NewsDataHub API \u062e\u0648\u062f \u0627\u0632 \u062f\u0627\u0634\u0628\u0648\u0631\u062f \u062e\u0648\u062f.<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%D8%AA%D9%86%D8%B8%DB%8C%D9%85%D8%A7%D8%AA_%D9%88_%D9%86%D9%85%D8%A7%DB%8C_%DA%A9%D9%84%DB%8C_%D9%81%D8%A7%DB%8C%D9%84_%D9%87%D8%A7%DB%8C_%D9%BE%DB%8C%DA%A9%D8%B1%D8%A8%D9%86%D8%AF%DB%8C\" >\u062a\u0646\u0638\u06cc\u0645\u0627\u062a \u0648 \u0646\u0645\u0627\u06cc \u06a9\u0644\u06cc \u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%D8%A8%D9%87_%D8%B1%D9%88%D8%B2_%D8%B1%D8%B3%D8%A7%D9%86%DB%8C_gitignore\" >\u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc .gitignore<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%D8%AA%D9%86%D8%B8%DB%8C%D9%85_%D8%AA%D8%B9%D8%A7%D8%B1%DB%8C%D9%81_%D9%86%D9%88%D8%B9_%D9%85%D8%AD%DB%8C%D8%B7\" >\u062a\u0646\u0638\u06cc\u0645 \u062a\u0639\u0627\u0631\u06cc\u0641 \u0646\u0648\u0639 \u0645\u062d\u06cc\u0637<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%D8%B1%D8%A7%D9%87_%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C_ESLint\" >\u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc ESLint<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%D8%AD%D8%A7%D9%84%D8%A7_%D8%A8%DB%8C%D8%A7%DB%8C%DB%8C%D8%AF_%DA%A9%D8%AF_%D9%BE%D8%B1%D9%88%DA%98%D9%87_%D8%B1%D8%A7_%D8%A7%D8%B6%D8%A7%D9%81%D9%87_%DA%A9%D9%86%DB%8C%D9%85\" >\u062d\u0627\u0644\u0627 \u0628\u06cc\u0627\u06cc\u06cc\u062f \u06a9\u062f \u067e\u0631\u0648\u0698\u0647 \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u0645<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%D9%BE%DB%8C%D8%A7%D8%AF%D9%87_%D8%B3%D8%A7%D8%B2%DB%8C_%DA%A9%D8%A7%D9%85%D9%BE%D9%88%D9%86%D9%86%D8%AA_NewsCard_%D9%88_PriceTicker\" >\u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0627\u0645\u067e\u0648\u0646\u0646\u062a NewsCard \u0648 PriceTicker<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%D8%AC%D8%B2%D8%A1_NewsCard\" >\u062c\u0632\u0621 NewsCard<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%DA%A9%D8%A7%D9%85%D9%BE%D9%88%D9%86%D9%86%D8%AA_PriceTicker\" >\u06a9\u0627\u0645\u067e\u0648\u0646\u0646\u062a PriceTicker<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%D8%B3%D8%A7%D8%AE%D8%AA_%D9%85%D8%A4%D9%84%D9%81%D9%87_%D8%B5%D9%81%D8%AD%D9%87_%D8%A7%D8%B5%D9%84%DB%8C\" >\u0633\u0627\u062e\u062a \u0645\u0624\u0644\u0641\u0647 \u0635\u0641\u062d\u0647 \u0627\u0635\u0644\u06cc<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%D8%A7%D8%AC%D8%B1%D8%A7%DB%8C_%D9%BE%D8%B1%D9%88%DA%98%D9%87_%D8%B4%D9%85%D8%A7\" >\u0627\u062c\u0631\u0627\u06cc \u067e\u0631\u0648\u0698\u0647 \u0634\u0645\u0627<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%D8%AA%D8%B3%D8%AA_%DA%A9%D8%A7%D9%85%D9%BE%D9%88%D9%86%D9%86%D8%AA_%D8%B5%D9%81%D8%AD%D9%87\" >\u062a\u0633\u062a \u06a9\u0627\u0645\u067e\u0648\u0646\u0646\u062a \u0635\u0641\u062d\u0647<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%D8%A8%D9%87%D8%A8%D9%88%D8%AF_%D8%A8%DB%8C%D8%B4%D8%AA%D8%B1_%D8%A7%DB%8C%D9%86_%D9%BE%D8%B1%D9%88%DA%98%D9%87_%D8%B1%D8%A7_%D8%AF%D8%B1_%D9%86%D8%B8%D8%B1_%D8%A8%DA%AF%DB%8C%D8%B1%DB%8C%D8%AF\" >\u0628\u0647\u0628\u0648\u062f \u0628\u06cc\u0634\u062a\u0631 \u0627\u06cc\u0646 \u067e\u0631\u0648\u0698\u0647 \u0631\u0627 \u062f\u0631 \u0646\u0638\u0631 \u0628\u06af\u06cc\u0631\u06cc\u062f.<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-19\" href=\"https:\/\/nabfollower.com\/blog\/crypto-news-aggregator-using-typescript-nextjs-newsdatahub-and-coingecko-apis-197b\/#%D8%A7%D8%B2_%D8%A7%DB%8C%D9%86%DA%A9%D9%87_%D8%AF%D9%86%D8%A8%D8%A7%D9%84_%D9%85%DB%8C_%DA%A9%D9%86%DB%8C%D8%AF_%D9%85%D8%AA%D8%B4%DA%A9%D8%B1%D9%85_%F0%9F%98%84\" >\u0627\u0632 \u0627\u06cc\u0646\u06a9\u0647 \u062f\u0646\u0628\u0627\u0644 \u0645\u06cc \u06a9\u0646\u06cc\u062f \u0645\u062a\u0634\u06a9\u0631\u0645 \ud83d\ude04<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D8%B1%D8%A7%D9%87_%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C_%D8%B3%D8%A7%D8%AE%D8%AA%D8%A7%D8%B1_%D9%BE%D8%B1%D9%88%DA%98%D9%87\"><\/span>\n<p>  \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc \u0633\u0627\u062e\u062a\u0627\u0631 \u067e\u0631\u0648\u0698\u0647<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u067e\u0633 \u0627\u0632 \u0645\u0642\u062f\u0627\u0631\u062f\u0647\u06cc \u0627\u0648\u0644\u06cc\u0647\u060c \u0628\u06cc\u0627\u06cc\u06cc\u062f \u0633\u0627\u062e\u062a\u0627\u0631 \u067e\u0631\u0648\u0698\u0647 \u062e\u0648\u062f \u0631\u0627 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u0645. \u0645\u0646 \u0647\u062f\u0641 \u0647\u0631 \u062f\u0627\u06cc\u0631\u06a9\u062a\u0648\u0631\u06cc \u0648 \u0641\u0627\u06cc\u0644 \u0631\u0627 \u062a\u0648\u0636\u06cc\u062d \u062e\u0648\u0627\u0647\u0645 \u062f\u0627\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nb\">mkdir<\/span> <span class=\"nt\">-p<\/span> app\/components\/<span class=\"o\">{<\/span>news-feed,price-ticker<span class=\"o\">}<\/span> __tests__ types\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u062f\u0631 \u067e\u0627\u06cc\u0627\u0646 \u0627\u06cc\u0646 \u0622\u0645\u0648\u0632\u0634 \u0628\u0627\u06cc\u062f \u0628\u0647 \u0633\u0627\u062e\u062a\u0627\u0631 \u0632\u06cc\u0631 \u0628\u0631\u0633\u06cc\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>crypto-news-aggregator\/\n\u251c\u2500\u2500 __tests__\/                    # Test files\n\u2502   \u251c\u2500\u2500 Home.test.tsx\n\u2502   \u251c\u2500\u2500 NewsCard.test.tsx\n\u2502   \u2514\u2500\u2500 PriceTicker.test.tsx\n\u251c\u2500\u2500 app\/                          # Next.js app directory\n\u2502   \u251c\u2500\u2500 components\/               # React components\n\u2502   \u2502   \u251c\u2500\u2500 news-feed\/            # News-related components\n\u2502   \u2502   \u2502   \u251c\u2500\u2500 NewsCard.tsx\n\u2502   \u2502   \u2502   \u2514\u2500\u2500 index.ts\n\u2502   \u2502   \u2514\u2500\u2500 price-ticker\/         # Price ticker components\n\u2502   \u2502       \u251c\u2500\u2500 PriceTicker.tsx\n\u2502   \u2502       \u2514\u2500\u2500 index.ts\n\u2502   \u251c\u2500\u2500 layout.tsx               # Root layout component\n\u2502   \u251c\u2500\u2500 page.module.css          # Styles for main page\n\u2502   \u2514\u2500\u2500 page.tsx                 # Main page component\n\u251c\u2500\u2500 public\/                      # Static assets\n\u251c\u2500\u2500 types\/                       # TypeScript type definitions\n\u2502   \u251c\u2500\u2500 cache.ts\n\u2502   \u251c\u2500\u2500 crypto.ts\n\u2502   \u251c\u2500\u2500 env.d.ts\n\u2502   \u251c\u2500\u2500 index.ts\n\u2502     \u2514\u2500\u2500 news.ts\n\u251c\u2500\u2500 .env.example                # Example environment variables\n\u251c\u2500\u2500 .env.local                  # Environment variables (gitignored)\n\u251c\u2500\u2500 .eslintrc.json              # ESLint configuration\n\u251c\u2500\u2500 .gitignore                  # Git ignore rules\n\u251c\u2500\u2500 eslint.config.mjs           # ESLint module configuration\n\u251c\u2500\u2500 jest.config.mjs             # Jest configuration\n\u251c\u2500\u2500 jest.setup.js               # Jest setup file\n\u251c\u2500\u2500 next-env.d.ts               # Next.js TypeScript declarations\n\u251c\u2500\u2500 next.config.js              # Next.js configuration\n\u251c\u2500\u2500 package-lock.json           # Locked dependency versions\n\u251c\u2500\u2500 package.json                # Project dependencies\n\u251c\u2500\u2500 README.md\n\u251c\u2500\u2500 tsconfig.json               # TypeScript configuration\n\u2514\u2500\u2500 types.d.ts                  # Global TypeScript declarations\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0627\u0645\u0627 \u0642\u0628\u0644 \u0627\u0632 \u0627\u06cc\u0646\u06a9\u0647 \u0628\u0647 \u0622\u0646\u062c\u0627 \u0628\u0631\u0633\u06cc\u0645\u060c \u0628\u0627\u06cc\u062f \u062f\u0627\u06cc\u0631\u06a9\u062a\u0648\u0631\u06cc \u067e\u0631\u0648\u0698\u0647 \u0631\u0627 \u06a9\u0645\u06cc \u062a\u0645\u06cc\u0632 \u06a9\u0646\u06cc\u0645 \u0648 \u0633\u067e\u0633 \u0686\u0646\u062f \u0641\u0627\u06cc\u0644 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u0645.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"%D9%81%D8%A7%DB%8C%D9%84_%D9%87%D8%A7%DB%8C%DB%8C_%DA%A9%D9%87_%D9%85%DB%8C_%D8%AA%D9%88%D8%A7%D9%86_%D8%A8%D8%A7_%D8%AE%DB%8C%D8%A7%D9%84_%D8%B1%D8%A7%D8%AD%D8%AA_%D9%BE%D8%A7%DA%A9_%DA%A9%D8%B1%D8%AF\"><\/span>\n<p>  \u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc\u06cc \u06a9\u0647 \u0645\u06cc \u062a\u0648\u0627\u0646 \u0628\u0627 \u062e\u06cc\u0627\u0644 \u0631\u0627\u062d\u062a \u067e\u0627\u06a9 \u06a9\u0631\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<ul>\n<li>app\/globals.css (\u0627\u06af\u0631 \u0627\u0632 \u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc module.css \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u062f)<\/li>\n<li>\u0647\u0645\u0647 <code>.svg<\/code> \u0641\u0627\u06cc\u0644 \u0647\u0627 (\u062f\u0631 <code>\/public<\/code> \u062f\u0627\u06cc\u0631\u06a9\u062a\u0648\u0631\u06cc)<\/li>\n<li>README.md (\u062d\u0630\u0641 \u06cc\u0627 \u0628\u0647\u200c\u0631\u0648\u0632\u0631\u0633\u0627\u0646\u06cc\u060c \u0632\u06cc\u0631\u0627 \u0627\u06cc\u0646 \u0628\u0631\u0646\u0627\u0645\u0647 \u067e\u06cc\u0634\u200c\u0641\u0631\u0636 \u0627\u0632 create-next-app \u0627\u0633\u062a)<\/li>\n<\/ul>\n<p>\u0627\u06af\u0631 favicon.ico \u0634\u0645\u0627 \u062f\u0631 \u062f\u0627\u06cc\u0631\u06a9\u062a\u0648\u0631\u06cc \u0628\u0631\u0646\u0627\u0645\u0647 \u0627\u0633\u062a\u060c \u0622\u0646 \u0631\u0627 \u0628\u0647 \u067e\u0648\u0634\u0647 \u0639\u0645\u0648\u0645\u06cc \u0645\u0646\u062a\u0642\u0644 \u06a9\u0646\u06cc\u062f. \u062f\u0631 \u062d\u0627\u0644\u06cc \u06a9\u0647 \u0641\u0627\u0648\u06cc\u06a9\u0648\u0646 \u0645\u06cc \u062a\u0648\u0627\u0646\u062f \u062f\u0631 \u0647\u0631 \u062f\u0648 \u0645\u06a9\u0627\u0646 \u06a9\u0627\u0631 \u06a9\u0646\u062f\u060c \u0622\u0646 \u0631\u0627 \u0628\u0647 \u0622\u0646 \u0645\u0646\u062a\u0642\u0644 \u06a9\u0646\u06cc\u062f <code>public\/<\/code> \u0627\u0632 \u0633\u0627\u062e\u062a\u0627\u0631 \u0645\u062a\u0639\u0627\u0631\u0641 \u067e\u06cc\u0631\u0648\u06cc \u0645\u06cc \u06a9\u0646\u062f \u0648 \u0645\u06a9\u0627\u0646 \u062f\u0627\u0631\u0627\u06cc\u06cc \u0631\u0627 \u0648\u0627\u0636\u062d \u062a\u0631 \u0645\u06cc \u06a9\u0646\u062f.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"%D8%AA%D8%B3%D8%AA_%DA%A9%D8%B1%D8%AF%D9%86\"><\/span>\n<p>  \u062a\u0633\u062a \u06a9\u0631\u062f\u0646<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0645\u0627 \u0628\u0627\u06cc\u062f \u0686\u0646\u062f\u06cc\u0646 \u0628\u0633\u062a\u0647 \u0622\u0632\u0645\u0627\u06cc\u0634\u06cc \u0631\u0627 \u0646\u0635\u0628 \u06a9\u0646\u06cc\u0645<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"nx\">npm<\/span> <span class=\"nx\">install<\/span> <span class=\"o\">--<\/span><span class=\"nx\">save<\/span><span class=\"o\">-<\/span><span class=\"nx\">dev<\/span> <span class=\"p\">@<\/span><span class=\"nd\">testing<\/span><span class=\"o\">-<\/span><span class=\"nx\">library<\/span><span class=\"o\">\/<\/span><span class=\"nx\">react<\/span> <span class=\"p\">@<\/span><span class=\"nd\">testing<\/span><span class=\"o\">-<\/span><span class=\"nx\">library<\/span><span class=\"o\">\/<\/span><span class=\"nx\">jest<\/span><span class=\"o\">-<\/span><span class=\"nx\">dom<\/span> <span class=\"nx\">jest<\/span> <span class=\"nx\">jest<\/span><span class=\"o\">-<\/span><span class=\"nx\">environment<\/span><span class=\"o\">-<\/span><span class=\"nx\">jsdom<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0628\u06cc\u0627\u06cc\u06cc\u062f \u0628\u0641\u0647\u0645\u06cc\u0645 \u06a9\u0647 \u0647\u0631 \u0628\u0633\u062a\u0647 \u0686\u0647 \u06a9\u0627\u0631\u06cc \u0627\u0646\u062c\u0627\u0645 \u0645\u06cc \u062f\u0647\u062f:<\/p>\n<ul>\n<li>\n<code>@testing-library\/react<\/code>: \u0627\u0628\u0632\u0627\u0631\u0647\u0627\u06cc\u06cc \u0631\u0627 \u0628\u0631\u0627\u06cc \u0622\u0632\u0645\u0627\u06cc\u0634 \u0627\u062c\u0632\u0627\u06cc React \u0627\u0631\u0627\u0626\u0647 \u0645\u06cc \u062f\u0647\u062f<\/li>\n<li>\n<code>@testing-library\/jest-dom<\/code>: \u0647\u0645\u0633\u0627\u0646 Jest \u0633\u0641\u0627\u0631\u0634\u06cc \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc \u06a9\u0646\u062f<\/li>\n<li>\n<code>jest<\/code>: \u0686\u0627\u0631\u0686\u0648\u0628 \u0627\u0635\u0644\u06cc \u062a\u0633\u062a<\/li>\n<li>\n<code>jest-environment-jsdom<\/code>: \u06cc\u06a9 \u0645\u062d\u06cc\u0637 \u0645\u0631\u0648\u0631\u06af\u0631 \u0631\u0627 \u0628\u0631\u0627\u06cc \u062a\u0633\u062a \u0647\u0627\u06cc \u0645\u0627 \u0634\u0628\u06cc\u0647 \u0633\u0627\u0632\u06cc \u0645\u06cc \u06a9\u0646\u062f<\/li>\n<\/ul>\n<p>\u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>types.d.ts<\/code> \u0628\u0631\u0627\u06cc \u062a\u0633\u062a \u062a\u0639\u0627\u0631\u06cc\u0641 \u0646\u0648\u0639<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"k\">import<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">@testing-library\/jest-dom<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"kr\">declare<\/span> <span class=\"nb\">global<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">namespace<\/span> <span class=\"nx\">jest<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kr\">interface<\/span> <span class=\"nx\">Matchers<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">R<\/span><span class=\"o\">&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">toBeInTheDocument<\/span><span class=\"p\">():<\/span> <span class=\"nx\">R<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">}<\/span>\n  <span class=\"kr\">interface<\/span> <span class=\"nx\">Window<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nl\">fetch<\/span><span class=\"p\">:<\/span> <span class=\"nx\">jest<\/span><span class=\"p\">.<\/span><span class=\"nx\">Mock<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<span class=\"k\">export<\/span> <span class=\"p\">{};<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u062d\u0627\u0644 \u0628\u06cc\u0627\u06cc\u06cc\u062f \u062a\u0639\u0627\u0631\u06cc\u0641 \u0646\u0648\u0639 TypeScript \u0631\u0627 \u0646\u0635\u0628 \u06a9\u0646\u06cc\u0645 \u062a\u0627 \u0648\u06cc\u0631\u0627\u06cc\u0634\u06af\u0631 \u06a9\u062f \u0645\u0627 \u0628\u062a\u0648\u0627\u0646\u062f Node.js\u060c React \u0648 Jest API\u0647\u0627 \u0631\u0627 \u062f\u0631\u06a9 \u06a9\u0646\u062f\u060c \u0648 \u0627\u0645\u06a9\u0627\u0646 \u062a\u06a9\u0645\u06cc\u0644 \u062e\u0648\u062f\u06a9\u0627\u0631 \u0648 \u06af\u0631\u0641\u062a\u0646 \u062e\u0637\u0627\u0647\u0627\u06cc \u0646\u0648\u0639 \u062f\u0631 \u0637\u0648\u0644 \u062a\u0648\u0633\u0639\u0647 \u0631\u0627 \u0641\u0631\u0627\u0647\u0645 \u06a9\u0646\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"nx\">npm<\/span> <span class=\"nx\">install<\/span> <span class=\"o\">--<\/span><span class=\"nx\">save<\/span><span class=\"o\">-<\/span><span class=\"nx\">dev<\/span> <span class=\"p\">@<\/span><span class=\"nd\">types<\/span><span class=\"sr\">\/node @types\/<\/span><span class=\"nx\">react<\/span> <span class=\"p\">@<\/span><span class=\"nd\">types<\/span><span class=\"sr\">\/jes<\/span><span class=\"err\">t\n<\/span><\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u067e\u0633 \u0627\u0632 \u0646\u0635\u0628 \u0628\u0633\u062a\u0647 \u0647\u0627\u060c \u0628\u0627\u06cc\u062f \u062c\u0633\u062a \u0631\u0627 \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u06a9\u0646\u06cc\u0645. \u0627\u06cc\u062c\u0627\u062f \u06cc\u06a9 <code>jest.config.mjs<\/code> \u0641\u0627\u06cc\u0644 \u062f\u0631 \u0631\u06cc\u0634\u0647 \u067e\u0631\u0648\u0698\u0647 \u062e\u0648\u062f<\/p>\n<p><code>jest.config.mjs<\/code>:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"k\">import<\/span> <span class=\"nx\">nextJest<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">next\/jest.js<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"nx\">createJestConfig<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">nextJest<\/span><span class=\"p\">({<\/span>\n  <span class=\"na\">dir<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.\/<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n<span class=\"p\">});<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"nf\">createJestConfig<\/span><span class=\"p\">({<\/span>\n  <span class=\"na\">testEnvironment<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">jest-environment-jsdom<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n  <span class=\"na\">setupFilesAfterEnv<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\"><rootdir>\/jest.setup.js<\/rootdir><\/span><span class=\"dl\">'<\/span><span class=\"p\">]<\/span>\n<span class=\"p\">});<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0627\u06cc\u062c\u0627\u062f \u06cc\u06a9 <code>jest.setup.js<\/code> \u0641\u0627\u06cc\u0644 \u0628\u0631\u0627\u06cc \u0648\u0627\u0631\u062f \u06a9\u0631\u062f\u0646 \u062a\u0637\u0628\u06cc\u0642 \u062f\u0647\u0646\u062f\u0647 \u0647\u0627\u06cc DOM.<\/p>\n<p><code>jest.setup.js<\/code>:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"k\">import<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">@testing-library\/jest-dom<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u062f\u0631 \u0646\u0647\u0627\u06cc\u062a\u060c \u0627\u06cc\u0646 \u062e\u0637\u0648\u0637 \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f \u062a\u0627 \u0627\u0633\u06a9\u0631\u06cc\u067e\u062a \u0622\u0632\u0645\u0627\u06cc\u0634\u06cc \u0634\u0645\u0627 \u0627\u062c\u0631\u0627 \u0634\u0648\u062f <code>package.json<\/code> \u0632\u06cc\u0631 <code>scripts<\/code>:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"dl\">\"<\/span><span class=\"s2\">test<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">jest<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n<span class=\"dl\">\"<\/span><span class=\"s2\">test:watch<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">jest --watch<\/span><span class=\"dl\">\"<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0628\u0646\u0627\u0628\u0631\u0627\u06cc\u0646 \u0628\u0647 \u0627\u06cc\u0646 \u0635\u0648\u0631\u062a \u062e\u0648\u0627\u0647\u062f \u0628\u0648\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code>  <span class=\"dl\">\"<\/span><span class=\"s2\">scripts<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n    <span class=\"dl\">\"<\/span><span class=\"s2\">dev<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">next dev<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"dl\">\"<\/span><span class=\"s2\">build<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">next build<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"dl\">\"<\/span><span class=\"s2\">start<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">next start<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"dl\">\"<\/span><span class=\"s2\">lint<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">next lint<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"dl\">\"<\/span><span class=\"s2\">test<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">jest<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"dl\">\"<\/span><span class=\"s2\">test:watch<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">jest --watch<\/span><span class=\"dl\">\"<\/span>\n  <span class=\"p\">},<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0627\u06a9\u0646\u0648\u0646 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u062a\u0633\u062a \u0647\u0627 \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f <code>npm test<\/code> \u06cc\u0627 <code>npm run test:watch<\/code> \u0628\u0631\u0627\u06cc \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0634\u0627 \u0627\u0645\u0627 \u0645\u0627 \u0647\u0646\u0648\u0632 \u0647\u06cc\u0686 \u062a\u0633\u062a\u06cc \u0646\u062f\u0627\u0631\u06cc\u0645\u060c \u0628\u0647 \u0632\u0648\u062f\u06cc \u06cc\u06a9 \u062a\u0633\u062a \u0627\u0636\u0627\u0641\u0647 \u062e\u0648\u0627\u0647\u06cc\u0645 \u06a9\u0631\u062f.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"%D8%AF%D8%B1%DB%8C%D8%A7%D9%81%D8%AA_%D9%86%D8%B4%D8%A7%D9%86%D9%87_API_NewsDataHub_%D8%B4%D9%85%D8%A7\"><\/span>\n<p>  \u062f\u0631\u06cc\u0627\u0641\u062a \u0646\u0634\u0627\u0646\u0647 API NewsDataHub \u0634\u0645\u0627<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0628\u06cc\u0627\u06cc\u06cc\u062f \u0631\u0648\u0646\u062f \u062f\u0631\u06cc\u0627\u0641\u062a \u062a\u0648\u06a9\u0646 API \u0634\u0645\u0627 \u0631\u0627 \u0637\u06cc \u06a9\u0646\u06cc\u0645.<\/p>\n<p>\u0628\u0647 NewsDataHub.com \u0645\u0631\u0627\u062c\u0639\u0647 \u06a9\u0646\u06cc\u062f<\/p>\n<p>\u0627\u06cc\u062c\u0627\u062f \u062d\u0633\u0627\u0628 \u06a9\u0627\u0631\u0628\u0631\u06cc (\u0628\u062f\u0648\u0646 \u0646\u06cc\u0627\u0632 \u0628\u0647 \u06a9\u0627\u0631\u062a \u0627\u0639\u062a\u0628\u0627\u0631\u06cc)<\/p>\n<ul>\n<li>\u0622\u062f\u0631\u0633 \u0627\u06cc\u0645\u06cc\u0644 \u062e\u0648\u062f \u0631\u0627 \u062f\u0631 \u0641\u0631\u0645 \u062b\u0628\u062a \u0646\u0627\u0645 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/li>\n<li>\u0628\u0627\u06cc\u062f \u0627\u06cc\u0645\u06cc\u0644 \u062e\u0648\u062f \u0631\u0627 \u0628\u0631\u0627\u06cc \u06a9\u062f \u062a\u0627\u06cc\u06cc\u062f \u0628\u0631\u0631\u0633\u06cc \u06a9\u0646\u06cc\u062f<\/li>\n<li>\u0647\u0646\u06af\u0627\u0645\u06cc \u06a9\u0647 \u062d\u0633\u0627\u0628 \u062e\u0648\u062f \u0631\u0627 \u062a\u0623\u06cc\u06cc\u062f \u06a9\u0631\u062f\u06cc\u062f\u060c \u0628\u0647 \u062f\u0627\u0634\u0628\u0648\u0631\u062f \u062e\u0648\u062f \u0645\u0646\u062a\u0642\u0644 \u062e\u0648\u0627\u0647\u06cc\u062f \u0634\u062f\u060c \u062c\u0627\u06cc\u06cc \u06a9\u0647 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u06a9\u0644\u06cc\u062f API \u062e\u0648\u062f \u0631\u0627 \u067e\u06cc\u062f\u0627 \u06a9\u0646\u06cc\u062f<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"%D8%A7%D9%81%D8%B2%D9%88%D8%AF%D9%86_%DA%A9%D9%84%DB%8C%D8%AF_API_%D8%A8%D9%87_%D9%BE%D8%B1%D9%88%DA%98%D9%87_%D8%B4%D9%85%D8%A7\"><\/span>\n<p>  \u0627\u0641\u0632\u0648\u062f\u0646 \u06a9\u0644\u06cc\u062f API \u0628\u0647 \u067e\u0631\u0648\u0698\u0647 \u0634\u0645\u0627<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0627\u06cc\u062c\u0627\u062f \u06cc\u06a9 <code>.env.example<\/code> \u062f\u0631 \u0631\u06cc\u0634\u0647 \u067e\u0631\u0648\u0698\u0647 \u062e\u0648\u062f \u0641\u0627\u06cc\u0644 \u06a9\u0646\u06cc\u062f \u062a\u0627 \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u06cc\u06a9 \u0627\u0644\u06af\u0648 \u0628\u0631\u0627\u06cc \u0645\u062a\u063a\u06cc\u0631\u0647\u0627\u06cc \u0645\u062d\u06cc\u0637 \u0645\u0648\u0631\u062f \u0646\u06cc\u0627\u0632 \u0639\u0645\u0644 \u06a9\u0646\u062f<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"nx\">NEXT_PUBLIC_API_URL<\/span><span class=\"o\">=<\/span><span class=\"nx\">https<\/span><span class=\"p\">:<\/span><span class=\"c1\">\/\/api.newsdatahub.com\/v1\/news<\/span>\n<span class=\"nx\">NEXT_PUBLIC_API_TOKEN<\/span><span class=\"o\">=<\/span><span class=\"nx\">your_token_here<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0633\u067e\u0633 \u0628\u0631\u0627\u06cc \u06a9\u067e\u06cc \u0645\u0648\u0627\u0631\u062f \u0632\u06cc\u0631 \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f <code>.env.example<\/code> \u0642\u0627\u0644\u0628 \u0628\u0647 <code>.env.local<\/code> \u06a9\u0647 \u062f\u0631 \u0622\u0646 \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u0648\u0627\u0642\u0639\u06cc \u0634\u0645\u0627 \u062e\u0648\u0627\u0647\u062f \u0628\u0648\u062f<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"nx\">cp<\/span> <span class=\"p\">.<\/span><span class=\"nx\">env<\/span><span class=\"p\">.<\/span><span class=\"nx\">example<\/span> <span class=\"p\">.<\/span><span class=\"nx\">env<\/span><span class=\"p\">.<\/span><span class=\"nx\">local<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D8%AC%D8%A7%DB%8C%DA%AF%D8%B2%DB%8C%D9%86_%DA%A9%D9%86%DB%8C%D8%AF_your_token_here_%D8%AF%D8%B1_envlocal_%D8%A8%D8%A7_%D8%AA%D9%88%DA%A9%D9%86_NewsDataHub_API_%D8%AE%D9%88%D8%AF_%D8%A7%D8%B2_%D8%AF%D8%A7%D8%B4%D8%A8%D9%88%D8%B1%D8%AF_%D8%AE%D9%88%D8%AF\"><\/span>\n<p>  <strong>\u062c\u0627\u06cc\u06af\u0632\u06cc\u0646 \u06a9\u0646\u06cc\u062f <code>your_token_here<\/code> \u062f\u0631 <code>.env.local<\/code> \u0628\u0627 \u062a\u0648\u06a9\u0646 NewsDataHub API \u062e\u0648\u062f \u0627\u0632 \u062f\u0627\u0634\u0628\u0648\u0631\u062f \u062e\u0648\u062f.<\/strong><br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p><code>.env.example<\/code>  \u0628\u0647 git \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u06cc\u06a9 \u0627\u0644\u06af\u0648 \u0645\u062a\u0639\u0647\u062f \u0627\u0633\u062a\u060c while <code>.env.local<\/code> \u062d\u0627\u0648\u06cc \u0627\u0633\u0631\u0627\u0631 \u0648\u0627\u0642\u0639\u06cc \u0627\u0633\u062a \u0648 \u0646\u0627\u062f\u06cc\u062f\u0647 \u06af\u0631\u0641\u062a\u0647 \u0645\u06cc \u0634\u0648\u062f.<\/p>\n<p>\u0647\u0646\u06af\u0627\u0645 \u0627\u0631\u062c\u0627\u0639 \u0628\u0647 \u06a9\u0644\u06cc\u062f API \u0627\u0632 \u06a9\u0644\u0645\u0627\u062a &#8220;token&#8221; \u0648 &#8220;key&#8221; \u0628\u0647 \u062c\u0627\u06cc \u06cc\u06a9\u062f\u06cc\u06af\u0631 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u06cc\u0645. \u0647\u0646\u06af\u0627\u0645\u06cc \u06a9\u0647 \u062a\u0648\u06a9\u0646 API \u062e\u0648\u062f \u0631\u0627 \u062f\u0627\u0631\u06cc\u062f\u060c \u0622\u0646 \u0631\u0627 \u0628\u0647 \u067e\u0631\u0648\u0698\u0647 \u062e\u0648\u062f \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f <code>.env.local<\/code> \u0641\u0627\u06cc\u0644:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">NEXT_PUBLIC_API_URL<\/span><span class=\"o\">=<\/span>https:\/\/api.newsdatahub.com\/v1\n<span class=\"nv\">NEXT_PUBLIC_API_TOKEN<\/span><span class=\"o\">=<\/span>your_newsdatahub_token\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D8%AA%D9%86%D8%B8%DB%8C%D9%85%D8%A7%D8%AA_%D9%88_%D9%86%D9%85%D8%A7%DB%8C_%DA%A9%D9%84%DB%8C_%D9%81%D8%A7%DB%8C%D9%84_%D9%87%D8%A7%DB%8C_%D9%BE%DB%8C%DA%A9%D8%B1%D8%A8%D9%86%D8%AF%DB%8C\"><\/span>\n<p>  \u062a\u0646\u0638\u06cc\u0645\u0627\u062a \u0648 \u0646\u0645\u0627\u06cc \u06a9\u0644\u06cc \u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0628\u06cc\u0627\u06cc\u06cc\u062f \u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc \u067e\u06cc\u06a9\u0631\u0628\u0646\u062f\u06cc \u0636\u0631\u0648\u0631\u06cc \u0631\u0627 \u062a\u0646\u0638\u06cc\u0645 \u06a9\u0646\u06cc\u0645. \u0645\u0646 \u0647\u062f\u0641 \u0648 \u0645\u062d\u062a\u0648\u0627\u06cc \u0647\u0631 \u06cc\u06a9 \u0631\u0627 \u062a\u0648\u0636\u06cc\u062d \u0645\u06cc \u062f\u0647\u0645:<\/p>\n<h3><span class=\"ez-toc-section\" id=\"%D8%A8%D9%87_%D8%B1%D9%88%D8%B2_%D8%B1%D8%B3%D8%A7%D9%86%DB%8C_gitignore\"><\/span>\n<p>  \u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc .gitignore<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u06cc\u0646 <code>.gitignore<\/code> \u0641\u0627\u06cc\u0644 \u0628\u0647 \u0637\u0648\u0631 \u062e\u0648\u062f\u06a9\u0627\u0631 \u062f\u0631 \u0637\u0648\u0644 \u0627\u0648\u0644\u06cc\u0647 \u0633\u0627\u0632\u06cc \u067e\u0631\u0648\u0698\u0647 \u0627\u06cc\u062c\u0627\u062f \u0634\u062f. \u0628\u0647 Git \u0645\u06cc \u06af\u0648\u06cc\u062f \u06a9\u062f\u0627\u0645 \u0641\u0627\u06cc\u0644 \u0647\u0627 \u0648 \u067e\u0648\u0634\u0647 \u0647\u0627 \u0631\u0627 \u0627\u0632 \u06a9\u0646\u062a\u0631\u0644 \u0646\u0633\u062e\u0647 \u062d\u0630\u0641 \u06a9\u0646\u062f.<\/p>\n<p>\u0628\u06cc\u0627\u06cc\u06cc\u062f \u0627\u0632 \u062e\u0648\u062f\u0645\u0627\u0646 \u0645\u0637\u0645\u0626\u0646 \u0634\u0648\u06cc\u0645 <code>.env.local<\/code> \u0641\u0627\u06cc\u0644 \u0628\u0627 \u0627\u0641\u0632\u0648\u062f\u0646 \u0645\u0648\u0627\u0631\u062f \u0632\u06cc\u0631 \u0628\u0647 \u0622\u0646 \u0646\u0627\u062f\u06cc\u062f\u0647 \u06af\u0631\u0641\u062a\u0647 \u0645\u06cc \u0634\u0648\u062f <code>.gitignore<\/code>.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code># Environment files\n.env*.local\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D8%AA%D9%86%D8%B8%DB%8C%D9%85_%D8%AA%D8%B9%D8%A7%D8%B1%DB%8C%D9%81_%D9%86%D9%88%D8%B9_%D9%85%D8%AD%DB%8C%D8%B7\"><\/span>\n<p>  \u062a\u0646\u0638\u06cc\u0645 \u062a\u0639\u0627\u0631\u06cc\u0641 \u0646\u0648\u0639 \u0645\u062d\u06cc\u0637<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>types\/env.d.ts<\/code> \u0628\u0631\u0627\u06cc \u0627\u0631\u0627\u0626\u0647 \u062a\u0639\u0627\u0631\u06cc\u0641 \u0646\u0648\u0639 TypeScript \u0628\u0631\u0627\u06cc \u0645\u062a\u063a\u06cc\u0631\u0647\u0627\u06cc \u0645\u062d\u06cc\u0637\u06cc:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"kr\">declare<\/span> <span class=\"nb\">global<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">namespace<\/span> <span class=\"nx\">NodeJS<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kr\">interface<\/span> <span class=\"nx\">ProcessEnv<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nl\">NEXT_PUBLIC_API_URL<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n      <span class=\"nl\">NEXT_PUBLIC_API_TOKEN<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"p\">{};<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0627\u06cc\u0646 \u0641\u0627\u06cc\u0644 \u0628\u0647 TypeScript \u062f\u0631 \u0645\u0648\u0631\u062f \u0645\u062a\u063a\u06cc\u0631\u0647\u0627\u06cc \u0645\u062d\u06cc\u0637\u06cc \u0645\u0627 \u0645\u06cc \u06af\u0648\u06cc\u062f \u0648 \u0627\u0645\u06a9\u0627\u0646 \u0628\u0631\u0631\u0633\u06cc \u0635\u062d\u06cc\u062d \u0646\u0648\u0639 \u0631\u0627 \u062f\u0631 \u0647\u0646\u06af\u0627\u0645 \u062f\u0633\u062a\u0631\u0633\u06cc \u0641\u0631\u0627\u0647\u0645 \u0645\u06cc \u06a9\u0646\u062f <code>process.env<\/code> \u0645\u0642\u0627\u062f\u06cc\u0631 \u0648 \u0627\u0631\u0627\u0626\u0647 \u067e\u06cc\u0634\u0646\u0647\u0627\u062f\u0627\u062a \u062a\u06a9\u0645\u06cc\u0644 \u062e\u0648\u062f\u06a9\u0627\u0631. \u0628\u062f\u0648\u0646 \u0622\u0646\u060c TypeScript \u0627\u06cc\u0646 \u0645\u062a\u063a\u06cc\u0631\u0647\u0627 \u0631\u0627 \u0627\u0632 \u0646\u0648\u0639 \u062e\u0648\u062f \u062f\u0631 \u0646\u0638\u0631 \u0645\u06cc \u06af\u06cc\u0631\u062f <code>any<\/code> .<\/p>\n<h3><span class=\"ez-toc-section\" id=\"%D8%B1%D8%A7%D9%87_%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C_ESLint\"><\/span>\n<p>  \u0631\u0627\u0647 \u0627\u0646\u062f\u0627\u0632\u06cc ESLint<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f <code>.eslintrc.json<\/code> \u0628\u0631\u0627\u06cc \u0641\u0639\u0627\u0644 \u06a9\u0631\u062f\u0646 \u0642\u0648\u0627\u0646\u06cc\u0646 \u067e\u06cc\u0634\u200c\u0641\u0631\u0636 Next.js \u0628\u0631\u0627\u06cc \u0639\u0645\u0644\u06a9\u0631\u062f \u0648 \u0628\u0647\u062a\u0631\u06cc\u0646 \u0634\u06cc\u0648\u0647\u200c\u0647\u0627.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"p\">{<\/span>\n  <span class=\"dl\">\"<\/span><span class=\"s2\">extends<\/span><span class=\"dl\">\"<\/span><span class=\"p\">:<\/span> <span class=\"p\">[<\/span>\n    <span class=\"dl\">\"<\/span><span class=\"s2\">next\/core-web-vitals<\/span><span class=\"dl\">\"<\/span>\n  <span class=\"p\">]<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D8%AD%D8%A7%D9%84%D8%A7_%D8%A8%DB%8C%D8%A7%DB%8C%DB%8C%D8%AF_%DA%A9%D8%AF_%D9%BE%D8%B1%D9%88%DA%98%D9%87_%D8%B1%D8%A7_%D8%A7%D8%B6%D8%A7%D9%81%D9%87_%DA%A9%D9%86%DB%8C%D9%85\"><\/span>\n<p>  \u062d\u0627\u0644\u0627 \u0628\u06cc\u0627\u06cc\u06cc\u062f \u06a9\u062f \u067e\u0631\u0648\u0698\u0647 \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u0645<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>types\/cache.ts<\/code>.<\/p>\n<p>\u0633\u0627\u062e\u062a\u0627\u0631 \u0633\u06cc\u0633\u062a\u0645 \u062d\u0627\u0641\u0638\u0647 \u067e\u0646\u0647\u0627\u0646 \u0633\u0645\u062a \u0633\u0631\u0648\u06cc\u0633 \u06af\u06cc\u0631\u0646\u062f\u0647 \u0645\u0627 \u0631\u0627 \u062a\u0639\u0631\u06cc\u0641 \u0645\u06cc \u06a9\u0646\u062f \u0648 \u0646\u062d\u0648\u0647 \u0630\u062e\u06cc\u0631\u0647 \u0645\u0647\u0631\u0647\u0627\u06cc \u0632\u0645\u0627\u0646\u06cc \u0648 \u062f\u0627\u062f\u0647 \u0647\u0627\u06cc \u062e\u0628\u0631\u06cc \u0631\u0627 \u0645\u0634\u062e\u0635 \u0645\u06cc \u06a9\u0646\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">NewsItem<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kr\">interface<\/span> <span class=\"nx\">CacheData<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nl\">timestamp<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">data<\/span><span class=\"p\">:<\/span> <span class=\"nx\">NewsItem<\/span><span class=\"p\">[];<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>types\/crypto.ts<\/code>.<br \/>\u0633\u0627\u062e\u062a\u0627\u0631 \u062f\u0627\u062f\u0647 \u0642\u06cc\u0645\u062a \u0627\u0631\u0632\u0647\u0627\u06cc \u062f\u06cc\u062c\u06cc\u062a\u0627\u0644 \u0631\u0627 \u0627\u0632 \u0637\u0631\u06cc\u0642 CoinCap API\u060c \u0627\u0632 \u062c\u0645\u0644\u0647 \u0642\u06cc\u0645\u062a\u060c \u0627\u0631\u0632\u0634 \u0628\u0627\u0632\u0627\u0631 \u0648 \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a 24 \u0633\u0627\u0639\u062a\u0647 \u062a\u0639\u0631\u06cc\u0641 \u0645\u06cc\u200c\u06a9\u0646\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"k\">export<\/span> <span class=\"kd\">type<\/span> <span class=\"nx\">CoinData<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n  <span class=\"p\">[<\/span><span class=\"na\">key<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">]:<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">usd<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">usd_market_cap<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">usd_24h_vol<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">usd_24h_change<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">last_updated_at<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f  <code>news.ts<\/code><br \/>\u062d\u0627\u0648\u06cc \u0631\u0627\u0628\u0637\u200c\u0647\u0627\u06cc\u06cc \u0628\u0631\u0627\u06cc \u0645\u0648\u0627\u0631\u062f \u062e\u0628\u0631\u06cc \u0627\u0632 NewsDataHub API \u0648 \u0644\u0648\u0627\u0632\u0645 \u062c\u0627\u0646\u0628\u06cc \u0628\u0631\u0627\u06cc \u0645\u0624\u0644\u0641\u0647 NewsCard \u0645\u0627.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"k\">export<\/span> <span class=\"kr\">interface<\/span> <span class=\"nx\">NewsItem<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nl\">id<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">title<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">article_link<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">description<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">pub_date<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kr\">interface<\/span> <span class=\"nx\">NewsCardProps<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nl\">index<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n    <span class=\"nl\">item<\/span><span class=\"p\">:<\/span> <span class=\"nx\">NewsItem<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f <code>types\/index.ts<\/code>.<br \/>\u0646\u0642\u0637\u0647 \u0635\u0627\u062f\u0631\u0627\u062a \u0645\u0631\u06a9\u0632\u06cc \u0628\u0631\u0627\u06cc \u0647\u0645\u0647 \u062a\u0639\u0627\u0631\u06cc\u0641 \u0646\u0648\u0639\u060c \u0627\u0645\u06a9\u0627\u0646 \u0648\u0627\u0631\u062f\u0627\u062a \u067e\u0627\u06a9 \u0631\u0627 \u0641\u0631\u0627\u0647\u0645 \u0645\u06cc \u06a9\u0646\u062f.<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"k\">export<\/span> <span class=\"o\">*<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.\/cache<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">export<\/span> <span class=\"o\">*<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.\/news<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">export<\/span> <span class=\"o\">*<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.\/crypto<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D9%BE%DB%8C%D8%A7%D8%AF%D9%87_%D8%B3%D8%A7%D8%B2%DB%8C_%DA%A9%D8%A7%D9%85%D9%BE%D9%88%D9%86%D9%86%D8%AA_NewsCard_%D9%88_PriceTicker\"><\/span>\n<p>  \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0627\u0645\u067e\u0648\u0646\u0646\u062a NewsCard \u0648 PriceTicker<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u062f\u0631 \u0645\u0631\u062d\u0644\u0647 \u0628\u0639\u062f\u060c \u0645\u0627 \u0627\u062c\u0632\u0627\u06cc \u062e\u0648\u062f \u0648 \u0633\u0628\u06a9 \u0622\u0646\u0647\u0627 \u0631\u0627 \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u0645\u06cc \u06a9\u0646\u06cc\u0645. \u0647\u0631 \u062c\u0632\u0621 \u0628\u0627\u06cc\u062f \u062f\u0631 \u062f\u0627\u06cc\u0631\u06a9\u062a\u0648\u0631\u06cc \u0645\u0631\u0628\u0648\u0637\u0647 \u062e\u0648\u062f \u0628\u0627\u0634\u062f.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"%D8%AC%D8%B2%D8%A1_NewsCard\"><\/span>\n<p>  \u062c\u0632\u0621 NewsCard<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p><code>app\/components\/news-feed\/NewsCard.tsx<\/code><\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"k\">import<\/span> <span class=\"nx\">styles<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.\/styles.module.css<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">NewsCardProps<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">@\/types<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">const<\/span> <span class=\"nx\">NewsCard<\/span><span class=\"p\">:<\/span> <span class=\"nx\">React<\/span><span class=\"p\">.<\/span><span class=\"nx\">FC<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">NewsCardProps<\/span><span class=\"o\">&gt;<\/span> <span class=\"o\">=<\/span> <span class=\"p\">({<\/span><span class=\"nx\">index<\/span><span class=\"p\">,<\/span> <span class=\"nx\">item<\/span><span class=\"p\">})<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">key<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">index<\/span><span class=\"si\">}<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">styles<\/span><span class=\"p\">.<\/span><span class=\"nx\">newsCard<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">h2<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">styles<\/span><span class=\"p\">.<\/span><span class=\"nx\">newsTitle<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span><span class=\"si\">{<\/span><span class=\"nx\">item<\/span><span class=\"p\">.<\/span><span class=\"nx\">title<\/span><span class=\"si\">}<\/span><span class=\"p\"\/><span class=\"nt\">h2<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span><span class=\"si\">{<\/span><span class=\"nx\">item<\/span><span class=\"p\">.<\/span><span class=\"nx\">description<\/span><span class=\"p\">.<\/span><span class=\"nf\">slice<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">200<\/span><span class=\"p\">)<\/span><span class=\"o\">+<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">...<\/span><span class=\"dl\">\"<\/span><span class=\"si\">}<\/span> Read more \n        <span class=\"p\">&lt;<\/span><span class=\"nt\">br<\/span><span class=\"p\">\/&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">br<\/span><span class=\"p\">\/&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">a<\/span> <span class=\"na\">href<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">item<\/span><span class=\"p\">.<\/span><span class=\"nx\">article_link<\/span><span class=\"si\">}<\/span> <span class=\"na\">target<\/span><span class=\"p\">=<\/span><span class=\"s\">\"_blank\"<\/span>  <span class=\"na\">rel<\/span><span class=\"p\">=<\/span><span class=\"s\">\"noopener noreferrer\"<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">styles<\/span><span class=\"p\">.<\/span><span class=\"nx\">newsLink<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"si\">{<\/span><span class=\"nx\">item<\/span><span class=\"p\">.<\/span><span class=\"nx\">article_link<\/span><span class=\"si\">}<\/span>\n            <span class=\"p\"\/><span class=\"nt\">a<\/span><span class=\"p\">&gt;<\/span>    \n        <span class=\"p\"\/><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span>\n\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">styles<\/span><span class=\"p\">.<\/span><span class=\"nx\">newsDate<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"si\">{<\/span><span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">item<\/span><span class=\"p\">.<\/span><span class=\"nx\">pub_date<\/span><span class=\"p\">).<\/span><span class=\"nf\">toLocaleDateString<\/span><span class=\"p\">()<\/span><span class=\"si\">}<\/span>\n        <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><code>app\/components\/news-feed\/styles.module.css<\/code><\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"p\">.<\/span><span class=\"nx\">newsCard<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">padding<\/span><span class=\"p\">:<\/span> <span class=\"mi\">15<\/span><span class=\"nx\">px<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">border<\/span><span class=\"p\">:<\/span> <span class=\"mi\">1<\/span><span class=\"nx\">px<\/span> <span class=\"nx\">solid<\/span> <span class=\"err\">#<\/span><span class=\"nx\">ddd<\/span><span class=\"p\">;<\/span>\n  <span class=\"nx\">border<\/span><span class=\"o\">-<\/span><span class=\"nx\">radius<\/span><span class=\"p\">:<\/span> <span class=\"mi\">4<\/span><span class=\"nx\">px<\/span><span class=\"p\">;<\/span>\n  <span class=\"nx\">margin<\/span><span class=\"o\">-<\/span><span class=\"nx\">bottom<\/span><span class=\"p\">:<\/span> <span class=\"mi\">15<\/span><span class=\"nx\">px<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"p\">.<\/span><span class=\"nx\">newsTitle<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">margin<\/span><span class=\"p\">:<\/span> <span class=\"mi\">0<\/span> <span class=\"mi\">0<\/span> <span class=\"mi\">10<\/span><span class=\"nx\">px<\/span> <span class=\"mi\">0<\/span><span class=\"p\">;<\/span>\n  <span class=\"nx\">font<\/span><span class=\"o\">-<\/span><span class=\"nx\">size<\/span><span class=\"p\">:<\/span> <span class=\"mf\">1.2<\/span><span class=\"nx\">em<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">color<\/span><span class=\"p\">:<\/span> <span class=\"err\">#<\/span><span class=\"mi\">2<\/span><span class=\"nx\">e009a<\/span><span class=\"p\">;<\/span>\n  <span class=\"nx\">font<\/span><span class=\"o\">-<\/span><span class=\"nx\">family<\/span><span class=\"p\">:<\/span> <span class=\"nx\">math<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"p\">.<\/span><span class=\"nx\">newsDate<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">color<\/span><span class=\"p\">:<\/span> <span class=\"err\">#<\/span><span class=\"mi\">666<\/span><span class=\"p\">;<\/span>\n  <span class=\"nx\">font<\/span><span class=\"o\">-<\/span><span class=\"nx\">size<\/span><span class=\"p\">:<\/span> <span class=\"mf\">0.9<\/span><span class=\"nx\">em<\/span><span class=\"p\">;<\/span>\n  <span class=\"nx\">margin<\/span><span class=\"o\">-<\/span><span class=\"nx\">top<\/span><span class=\"p\">:<\/span> <span class=\"mi\">10<\/span><span class=\"nx\">px<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"p\">.<\/span><span class=\"nx\">newsLink<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">color<\/span><span class=\"p\">:<\/span><span class=\"nx\">darkcyan<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"p\">.<\/span><span class=\"nx\">newsLink<\/span><span class=\"p\">:<\/span><span class=\"nx\">hover<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">color<\/span><span class=\"p\">:<\/span> <span class=\"nf\">rgb<\/span><span class=\"p\">(<\/span><span class=\"mi\">3<\/span><span class=\"p\">,<\/span> <span class=\"mi\">79<\/span><span class=\"p\">,<\/span> <span class=\"mi\">79<\/span><span class=\"p\">);<\/span>\n  <span class=\"nl\">cursor<\/span><span class=\"p\">:<\/span> <span class=\"nx\">pointer<\/span><span class=\"p\">;<\/span>\n  <span class=\"nx\">text<\/span><span class=\"o\">-<\/span><span class=\"nx\">decoration<\/span><span class=\"p\">:<\/span> <span class=\"nx\">underline<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><code>app\/components\/news-feed\/index.tsx<\/code><\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"k\">export<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">NewsCard<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.\/NewsCard<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%DA%A9%D8%A7%D9%85%D9%BE%D9%88%D9%86%D9%86%D8%AA_PriceTicker\"><\/span>\n<p>  \u06a9\u0627\u0645\u067e\u0648\u0646\u0646\u062a PriceTicker<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p><code>app\/components\/price-ticker\/PriceTicker.tsx<\/code><\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useEffect<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">react<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">styles<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.\/styles.module.css<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">CoinData<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">@\/types<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">const<\/span>  <span class=\"nx\">PriceTicker<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">prices<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setPrices<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">CoinData<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">({});<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">error<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setError<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">string<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">loading<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setLoading<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useState<\/span><span class=\"p\">(<\/span><span class=\"kc\">true<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">fetchPrices<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">response<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">fetch<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">https:\/\/api.coingecko.com\/api\/v3\/simple\/price?ids=bitcoin,ethereum,dogecoin&amp;vs_currencies=usd&amp;include_24hr_change=true<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">response<\/span><span class=\"p\">.<\/span><span class=\"nx\">ok<\/span><span class=\"p\">)<\/span> <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to fetch prices<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"kd\">const<\/span> <span class=\"nx\">data<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">response<\/span><span class=\"p\">.<\/span><span class=\"nf\">json<\/span><span class=\"p\">();<\/span>\n\n      <span class=\"nf\">setPrices<\/span><span class=\"p\">(<\/span><span class=\"nx\">data<\/span><span class=\"p\">);<\/span>\n      <span class=\"nf\">setError<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">err<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">setError<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to load prices<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n      <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Price fetch error:<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">err<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">finally<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">setLoading<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"nf\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nf\">fetchPrices<\/span><span class=\"p\">();<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">interval<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">setInterval<\/span><span class=\"p\">(<\/span><span class=\"nx\">fetchPrices<\/span><span class=\"p\">,<\/span> <span class=\"mi\">60000<\/span><span class=\"p\">);<\/span> <span class=\"c1\">\/\/ Update every minute<\/span>\n    <span class=\"k\">return <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nf\">clearInterval<\/span><span class=\"p\">(<\/span><span class=\"nx\">interval<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[]);<\/span>\n\n  <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">loading<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span> <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">styles<\/span><span class=\"p\">.<\/span><span class=\"nx\">ticker<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>Loading prices...<span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;;<\/span>\n  <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span> <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">styles<\/span><span class=\"p\">.<\/span><span class=\"nx\">ticker<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>Price data unavailable<span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;;<\/span>\n\n  <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">styles<\/span><span class=\"p\">.<\/span><span class=\"nx\">ticker<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"si\">{<\/span><span class=\"nb\">Object<\/span><span class=\"p\">.<\/span><span class=\"nf\">entries<\/span><span class=\"p\">(<\/span><span class=\"nx\">prices<\/span><span class=\"p\">).<\/span><span class=\"nf\">map<\/span><span class=\"p\">(([<\/span><span class=\"nx\">coinId<\/span><span class=\"p\">,<\/span> <span class=\"nx\">data<\/span><span class=\"p\">])<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">price<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">usd<\/span><span class=\"p\">.<\/span><span class=\"nf\">toLocaleString<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">en-US<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n          <span class=\"na\">style<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">currency<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">currency<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">USD<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">minimumFractionDigits<\/span><span class=\"p\">:<\/span> <span class=\"mi\">2<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">maximumFractionDigits<\/span><span class=\"p\">:<\/span> <span class=\"mi\">2<\/span>\n        <span class=\"p\">});<\/span>\n\n        <span class=\"kd\">const<\/span> <span class=\"nx\">change<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">usd_24h_change<\/span> <span class=\"o\">||<\/span> <span class=\"mi\">0<\/span><span class=\"p\">;<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">changeClass<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">change<\/span> <span class=\"o\">&gt;=<\/span> <span class=\"mi\">0<\/span> <span class=\"p\">?<\/span> <span class=\"nx\">styles<\/span><span class=\"p\">.<\/span><span class=\"nx\">positive<\/span> <span class=\"p\">:<\/span> <span class=\"nx\">styles<\/span><span class=\"p\">.<\/span><span class=\"nx\">negative<\/span><span class=\"p\">;<\/span>\n\n        <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">key<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">coinId<\/span><span class=\"si\">}<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">styles<\/span><span class=\"p\">.<\/span><span class=\"nx\">cryptoPrice<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nt\">span<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">styles<\/span><span class=\"p\">.<\/span><span class=\"nx\">symbol<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span><span class=\"si\">{<\/span><span class=\"nx\">coinId<\/span><span class=\"p\">.<\/span><span class=\"nf\">toUpperCase<\/span><span class=\"p\">()<\/span><span class=\"si\">}<\/span><span class=\"p\"\/><span class=\"nt\">span<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nt\">span<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">styles<\/span><span class=\"p\">.<\/span><span class=\"nx\">price<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span><span class=\"si\">{<\/span><span class=\"nx\">price<\/span><span class=\"si\">}<\/span><span class=\"p\"\/><span class=\"nt\">span<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nt\">span<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"s2\">`<\/span><span class=\"p\">${<\/span><span class=\"nx\">styles<\/span><span class=\"p\">.<\/span><span class=\"nx\">change<\/span><span class=\"p\">}<\/span><span class=\"s2\"> <\/span><span class=\"p\">${<\/span><span class=\"nx\">changeClass<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n       <span class=\"si\">{<\/span><span class=\"nx\">change<\/span> <span class=\"o\">&gt;=<\/span> <span class=\"mi\">0<\/span> <span class=\"p\">?<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">\u2191<\/span><span class=\"dl\">'<\/span> <span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">\u2193<\/span><span class=\"dl\">'<\/span><span class=\"si\">}<\/span>\n                <span class=\"si\">{<\/span><span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">abs<\/span><span class=\"p\">(<\/span><span class=\"nx\">change<\/span><span class=\"p\">).<\/span><span class=\"nf\">toFixed<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">)<\/span><span class=\"si\">}<\/span>%\n     <span class=\"p\"\/><span class=\"nt\">span<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">);<\/span>\n      <span class=\"p\">})<\/span><span class=\"si\">}<\/span>\n    <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n<span class=\"p\">);<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><code>app\/components\/price-ticker\/styles.module.css<\/code><\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight css\"><code><span class=\"nc\">.ticker<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">background<\/span><span class=\"p\">:<\/span> <span class=\"m\">#1a1a1a<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">color<\/span><span class=\"p\">:<\/span> <span class=\"no\">white<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">padding<\/span><span class=\"p\">:<\/span> <span class=\"m\">10px<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">border-radius<\/span><span class=\"p\">:<\/span> <span class=\"m\">8px<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">margin-bottom<\/span><span class=\"p\">:<\/span> <span class=\"m\">20px<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">overflow-x<\/span><span class=\"p\">:<\/span> <span class=\"nb\">auto<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">display<\/span><span class=\"p\">:<\/span> <span class=\"n\">flex<\/span><span class=\"p\">;<\/span>\n  <span class=\"py\">gap<\/span><span class=\"p\">:<\/span> <span class=\"m\">20px<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">align-items<\/span><span class=\"p\">:<\/span> <span class=\"nb\">center<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nc\">.cryptoPrice<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">display<\/span><span class=\"p\">:<\/span> <span class=\"n\">flex<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">align-items<\/span><span class=\"p\">:<\/span> <span class=\"nb\">center<\/span><span class=\"p\">;<\/span>\n  <span class=\"py\">gap<\/span><span class=\"p\">:<\/span> <span class=\"m\">8px<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">padding<\/span><span class=\"p\">:<\/span> <span class=\"m\">4px<\/span> <span class=\"m\">8px<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">background<\/span><span class=\"p\">:<\/span> <span class=\"n\">rgba<\/span><span class=\"p\">(<\/span><span class=\"m\">255<\/span><span class=\"p\">,<\/span> <span class=\"m\">255<\/span><span class=\"p\">,<\/span> <span class=\"m\">255<\/span><span class=\"p\">,<\/span> <span class=\"m\">0.1<\/span><span class=\"p\">);<\/span>\n  <span class=\"nl\">border-radius<\/span><span class=\"p\">:<\/span> <span class=\"m\">4px<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">white-space<\/span><span class=\"p\">:<\/span> <span class=\"nb\">nowrap<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nc\">.symbol<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">font-weight<\/span><span class=\"p\">:<\/span> <span class=\"nb\">bold<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">color<\/span><span class=\"p\">:<\/span> <span class=\"m\">#ffd700<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nc\">.price<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">font-family<\/span><span class=\"p\">:<\/span> <span class=\"nb\">monospace<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nc\">.change<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">font-size<\/span><span class=\"p\">:<\/span> <span class=\"m\">0.9em<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">padding<\/span><span class=\"p\">:<\/span> <span class=\"m\">2px<\/span> <span class=\"m\">6px<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">border-radius<\/span><span class=\"p\">:<\/span> <span class=\"m\">4px<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nc\">.positive<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">color<\/span><span class=\"p\">:<\/span> <span class=\"m\">#00ff00<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nc\">.negative<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">color<\/span><span class=\"p\">:<\/span> <span class=\"m\">#ff4444<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">@keyframes<\/span> <span class=\"n\">slide<\/span> <span class=\"p\">{<\/span>\n  <span class=\"err\">0<\/span><span class=\"o\">%<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nl\">transform<\/span><span class=\"p\">:<\/span> <span class=\"n\">translateX<\/span><span class=\"p\">(<\/span><span class=\"m\">100%<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">}<\/span>\n  <span class=\"err\">100<\/span><span class=\"o\">%<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nl\">transform<\/span><span class=\"p\">:<\/span> <span class=\"n\">translateX<\/span><span class=\"p\">(<\/span><span class=\"m\">-100%<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><code>app\/components\/news-feed\/index.tsx<\/code><\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"k\">export<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">PriceTicker<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.\/PriceTicker<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D8%B3%D8%A7%D8%AE%D8%AA_%D9%85%D8%A4%D9%84%D9%81%D9%87_%D8%B5%D9%81%D8%AD%D9%87_%D8%A7%D8%B5%D9%84%DB%8C\"><\/span>\n<p>  \u0633\u0627\u062e\u062a \u0645\u0624\u0644\u0641\u0647 \u0635\u0641\u062d\u0647 \u0627\u0635\u0644\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u062f\u0631 Next.js App Router\u060c \u0635\u0641\u062d\u0647 \u0627\u0635\u0644\u06cc \u0628\u0631\u0646\u0627\u0645\u0647 \u0645\u0627 \u062f\u0631 \u0622\u0646 \u0642\u0631\u0627\u0631 \u062f\u0627\u0631\u062f <code>app\/page.tsx<\/code>. \u062f\u0631 \u062d\u0627\u0644\u06cc \u06a9\u0647 \u0641\u0627\u06cc\u0644 \u0642\u0631\u0627\u0631 \u0627\u0633\u062a \u0646\u0627\u0645\u06af\u0630\u0627\u0631\u06cc \u0634\u0648\u062f <code>page.tsx<\/code> \u0628\u0647 \u062f\u0646\u0628\u0627\u0644 \u0642\u0631\u0627\u0631\u062f\u0627\u062f\u0647\u0627\u06cc Next.js\u060c \u06a9\u0627\u0645\u067e\u0648\u0646\u0646\u062a \u062e\u0648\u062f \u0631\u0627 \u0646\u0627\u0645\u06af\u0630\u0627\u0631\u06cc \u0645\u06cc \u06a9\u0646\u06cc\u0645 <code>Home<\/code> \u062a\u0627 \u0628\u0647 \u0648\u0636\u0648\u062d \u0647\u062f\u0641 \u0622\u0646 \u0631\u0627 \u0628\u0647 \u0639\u0646\u0648\u0627\u0646 \u0635\u0641\u062d\u0647 \u0627\u0635\u0644\u06cc \u0628\u0631\u0646\u0627\u0645\u0647 \u0645\u0627 \u0646\u0634\u0627\u0646 \u062f\u0647\u062f.<\/p>\n<p>\u067e\u06cc\u0634 \u0628\u0631\u0648\u06cc\u062f \u0648 \u0628\u0647 \u0631\u0648\u0632 \u06a9\u0646\u06cc\u062f  <code>app\/components\/page.tsx<\/code> \u0628\u0627 \u06a9\u062f \u0632\u06cc\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"dl\">'<\/span><span class=\"s1\">use client<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useEffect<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">react<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">PriceTicker<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">@\/app\/components\/price-ticker<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">NewsCard<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">@\/app\/components\/news-feed<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">CacheData<\/span><span class=\"p\">,<\/span> <span class=\"nx\">NewsItem<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">@\/types<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">styles<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.\/page.module.css<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n<span class=\"c1\">\/\/ Environment variables for API configuration<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">API_URL<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">process<\/span><span class=\"p\">.<\/span><span class=\"nx\">env<\/span><span class=\"p\">.<\/span><span class=\"nx\">NEXT_PUBLIC_API_URL<\/span><span class=\"p\">;<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">API_TOKEN<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">process<\/span><span class=\"p\">.<\/span><span class=\"nx\">env<\/span><span class=\"p\">.<\/span><span class=\"nx\">NEXT_PUBLIC_API_TOKEN<\/span><span class=\"p\">;<\/span>\n\n<span class=\"c1\">\/\/ Cache duration set to one hour<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">CACHE_DURATION<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">1000<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">60<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">60<\/span><span class=\"p\">;<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">TOPICS<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"dl\">'<\/span><span class=\"s1\">cryptocurrency<\/span><span class=\"dl\">'<\/span><span class=\"p\">];<\/span>\n\n<span class=\"c1\">\/\/ In-memory cache for storing news data<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">cache<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Record<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"nx\">CacheData<\/span><span class=\"o\">&gt;<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{};<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">Home<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n  <span class=\"c1\">\/\/ State management using React hooks<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">news<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setNews<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">NewsItem<\/span><span class=\"p\">[]<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">([]);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">loading<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setLoading<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useState<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">error<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setError<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">string<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">lastUpdated<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setLastUpdated<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"o\">&lt;<\/span><span class=\"nb\">Date<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"c1\">\/\/ Fetches news data with built-in caching<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">fetchNews<\/span> <span class=\"o\">=<\/span> <span class=\"k\">async <\/span><span class=\"p\">(<\/span><span class=\"nx\">topics<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">[])<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">cacheKey<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">topics<\/span><span class=\"p\">.<\/span><span class=\"nf\">sort<\/span><span class=\"p\">().<\/span><span class=\"nf\">join<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">,<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">cachedData<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">cache<\/span><span class=\"p\">[<\/span><span class=\"nx\">cacheKey<\/span><span class=\"p\">];<\/span>\n\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">cachedData<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">.<\/span><span class=\"nf\">now<\/span><span class=\"p\">()<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">cachedData<\/span><span class=\"p\">.<\/span><span class=\"nx\">timestamp<\/span> <span class=\"o\">&lt;<\/span> <span class=\"nx\">CACHE_DURATION<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">setNews<\/span><span class=\"p\">(<\/span><span class=\"nx\">cachedData<\/span><span class=\"p\">.<\/span><span class=\"nx\">data<\/span><span class=\"p\">);<\/span>\n      <span class=\"nf\">setLastUpdated<\/span><span class=\"p\">(<\/span><span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">cachedData<\/span><span class=\"p\">.<\/span><span class=\"nx\">timestamp<\/span><span class=\"p\">));<\/span>\n      <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"nf\">setLoading<\/span><span class=\"p\">(<\/span><span class=\"kc\">true<\/span><span class=\"p\">);<\/span>\n    <span class=\"nf\">setError<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n\n    <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">response<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nf\">fetch<\/span><span class=\"p\">(<\/span><span class=\"s2\">`<\/span><span class=\"p\">${<\/span><span class=\"nx\">API_URL<\/span><span class=\"p\">}<\/span><span class=\"s2\">?language=en&amp;topic=cryptocurrency`<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">headers<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n          <span class=\"dl\">'<\/span><span class=\"s1\">x-api-key<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span> <span class=\"nx\">API_TOKEN<\/span><span class=\"p\">,<\/span>\n          <span class=\"dl\">'<\/span><span class=\"s1\">Content-Type<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">application\/json<\/span><span class=\"dl\">'<\/span>\n        <span class=\"p\">},<\/span>\n      <span class=\"p\">});<\/span>\n\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">response<\/span><span class=\"p\">.<\/span><span class=\"nx\">ok<\/span><span class=\"p\">)<\/span> <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"nc\">Error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Failed to fetch news<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"kd\">const<\/span> <span class=\"nx\">articles<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">response<\/span><span class=\"p\">.<\/span><span class=\"nf\">json<\/span><span class=\"p\">();<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"na\">data<\/span><span class=\"p\">:<\/span> <span class=\"nx\">NewsItem<\/span><span class=\"p\">[]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">articles<\/span><span class=\"p\">.<\/span><span class=\"nx\">data<\/span><span class=\"p\">;<\/span>\n\n      <span class=\"nx\">cache<\/span><span class=\"p\">[<\/span><span class=\"nx\">cacheKey<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n        <span class=\"na\">timestamp<\/span><span class=\"p\">:<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">.<\/span><span class=\"nf\">now<\/span><span class=\"p\">(),<\/span>\n        <span class=\"nx\">data<\/span>\n      <span class=\"p\">};<\/span>\n\n      <span class=\"nf\">setNews<\/span><span class=\"p\">(<\/span><span class=\"nx\">data<\/span><span class=\"p\">);<\/span>\n      <span class=\"nf\">setLastUpdated<\/span><span class=\"p\">(<\/span><span class=\"k\">new<\/span> <span class=\"nc\">Date<\/span><span class=\"p\">());<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">catch <\/span><span class=\"p\">(<\/span><span class=\"nx\">err<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">setError<\/span><span class=\"p\">(<\/span><span class=\"nx\">err<\/span> <span class=\"k\">instanceof<\/span> <span class=\"nb\">Error<\/span> <span class=\"p\">?<\/span> <span class=\"nx\">err<\/span><span class=\"p\">.<\/span><span class=\"nx\">message<\/span> <span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">An error occurred<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">finally<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">setLoading<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"c1\">\/\/ Fetch data when component mounts<\/span>\n  <span class=\"nf\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nf\">fetchNews<\/span><span class=\"p\">(<\/span><span class=\"nx\">TOPICS<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[]);<\/span>\n\n  <span class=\"c1\">\/\/ Handler for manual refresh<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">handleRefresh<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">cacheKey<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">TOPICS<\/span><span class=\"p\">.<\/span><span class=\"nf\">sort<\/span><span class=\"p\">().<\/span><span class=\"nf\">join<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">,<\/span><span class=\"dl\">'<\/span><span class=\"p\">);<\/span>\n    <span class=\"k\">delete<\/span> <span class=\"nx\">cache<\/span><span class=\"p\">[<\/span><span class=\"nx\">cacheKey<\/span><span class=\"p\">];<\/span>\n    <span class=\"nf\">fetchNews<\/span><span class=\"p\">(<\/span><span class=\"nx\">TOPICS<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">styles<\/span><span class=\"p\">.<\/span><span class=\"nx\">container<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nc\">PriceTicker<\/span> <span class=\"p\">\/&gt;<\/span>\n\n      <span class=\"si\">{<\/span><span class=\"nx\">lastUpdated<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">(<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">styles<\/span><span class=\"p\">.<\/span><span class=\"nx\">lastUpdated<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n          Last updated: <span class=\"si\">{<\/span><span class=\"nx\">lastUpdated<\/span><span class=\"p\">.<\/span><span class=\"nf\">toLocaleTimeString<\/span><span class=\"p\">()<\/span><span class=\"si\">}<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">button<\/span> <span class=\"na\">onClick<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">handleRefresh<\/span><span class=\"si\">}<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">styles<\/span><span class=\"p\">.<\/span><span class=\"nx\">refreshButton<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n            Refresh\n          <span class=\"p\"\/><span class=\"nt\">button<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n\n      <span class=\"si\">{<\/span><span class=\"nx\">error<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">styles<\/span><span class=\"p\">.<\/span><span class=\"nx\">error<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span><span class=\"si\">{<\/span><span class=\"nx\">error<\/span><span class=\"si\">}<\/span><span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span><span class=\"si\">}<\/span>\n\n      <span class=\"si\">{<\/span><span class=\"nx\">loading<\/span> <span class=\"p\">?<\/span> <span class=\"p\">(<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">styles<\/span><span class=\"p\">.<\/span><span class=\"nx\">loading<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>Loading...<span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">)<\/span> <span class=\"p\">:<\/span> <span class=\"p\">(<\/span>\n        <span class=\"nx\">news<\/span><span class=\"p\">.<\/span><span class=\"nf\">map<\/span><span class=\"p\">((<\/span><span class=\"nx\">item<\/span><span class=\"p\">:<\/span> <span class=\"nx\">NewsItem<\/span><span class=\"p\">,<\/span> <span class=\"nx\">index<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">(<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nc\">NewsCard<\/span> <span class=\"na\">key<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">item<\/span><span class=\"p\">.<\/span><span class=\"nx\">id<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">index<\/span><span class=\"si\">}<\/span> <span class=\"na\">item<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">item<\/span><span class=\"si\">}<\/span> <span class=\"na\">index<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">index<\/span><span class=\"si\">}<\/span> <span class=\"p\">\/&gt;<\/span>\n        <span class=\"p\">))<\/span>\n      <span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n    <span class=\"p\"\/><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">);<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc <code>page.module.css<\/code>  \u0628\u0627 \u0633\u0628\u06a9 \u0647\u0627\u06cc \u0632\u06cc\u0631<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight css\"><code><span class=\"nc\">.container<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">max-width<\/span><span class=\"p\">:<\/span> <span class=\"m\">800px<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">margin<\/span><span class=\"p\">:<\/span> <span class=\"m\">0<\/span> <span class=\"nb\">auto<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">padding<\/span><span class=\"p\">:<\/span> <span class=\"m\">20px<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nc\">.topics<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">margin-bottom<\/span><span class=\"p\">:<\/span> <span class=\"m\">20px<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nc\">.topic<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">margin-right<\/span><span class=\"p\">:<\/span> <span class=\"m\">10px<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">padding<\/span><span class=\"p\">:<\/span> <span class=\"m\">5px<\/span> <span class=\"m\">10px<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">border<\/span><span class=\"p\">:<\/span> <span class=\"m\">1px<\/span> <span class=\"nb\">solid<\/span> <span class=\"m\">#ddd<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">border-radius<\/span><span class=\"p\">:<\/span> <span class=\"m\">4px<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">background<\/span><span class=\"p\">:<\/span> <span class=\"nb\">none<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">cursor<\/span><span class=\"p\">:<\/span> <span class=\"nb\">pointer<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nc\">.topicSelected<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">background<\/span><span class=\"p\">:<\/span> <span class=\"m\">#007bff<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">color<\/span><span class=\"p\">:<\/span> <span class=\"no\">white<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">border-color<\/span><span class=\"p\">:<\/span> <span class=\"m\">#007bff<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nc\">.error<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">color<\/span><span class=\"p\">:<\/span> <span class=\"m\">#dc3545<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">padding<\/span><span class=\"p\">:<\/span> <span class=\"m\">10px<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">border<\/span><span class=\"p\">:<\/span> <span class=\"m\">1px<\/span> <span class=\"nb\">solid<\/span> <span class=\"m\">#dc3545<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">border-radius<\/span><span class=\"p\">:<\/span> <span class=\"m\">4px<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">margin-bottom<\/span><span class=\"p\">:<\/span> <span class=\"m\">15px<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nc\">.loading<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">text-align<\/span><span class=\"p\">:<\/span> <span class=\"nb\">center<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">padding<\/span><span class=\"p\">:<\/span> <span class=\"m\">20px<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nc\">.lastUpdated<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">color<\/span><span class=\"p\">:<\/span> <span class=\"m\">#666<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">font-size<\/span><span class=\"p\">:<\/span> <span class=\"m\">0.9em<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">margin-bottom<\/span><span class=\"p\">:<\/span> <span class=\"m\">15px<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"nc\">.refreshButton<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">background<\/span><span class=\"p\">:<\/span> <span class=\"m\">#007bff<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">color<\/span><span class=\"p\">:<\/span> <span class=\"no\">white<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">border<\/span><span class=\"p\">:<\/span> <span class=\"nb\">none<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">padding<\/span><span class=\"p\">:<\/span> <span class=\"m\">5px<\/span> <span class=\"m\">10px<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">border-radius<\/span><span class=\"p\">:<\/span> <span class=\"m\">4px<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">cursor<\/span><span class=\"p\">:<\/span> <span class=\"nb\">pointer<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">margin-left<\/span><span class=\"p\">:<\/span> <span class=\"m\">10px<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0628\u0647 \u0631\u0648\u0632 \u0631\u0633\u0627\u0646\u06cc <code>app\/layout.tsx<\/code> \u0628\u0627 \u0645\u0648\u0627\u0631\u062f \u0632\u06cc\u0631:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"kd\">function<\/span> <span class=\"nf\">RootLayout<\/span><span class=\"p\">({<\/span>\n  <span class=\"nx\">children<\/span><span class=\"p\">,<\/span>\n<span class=\"p\">}:<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">children<\/span><span class=\"p\">:<\/span> <span class=\"nx\">React<\/span><span class=\"p\">.<\/span><span class=\"nx\">ReactNode<\/span>\n<span class=\"p\">})<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">html<\/span> <span class=\"na\">lang<\/span><span class=\"p\">=<\/span><span class=\"s\">\"en\"<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">head<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">title<\/span><span class=\"p\">&gt;<\/span>Crypto News Aggregator Application<span class=\"p\"\/><span class=\"nt\">title<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">meta<\/span> <span class=\"na\">name<\/span><span class=\"p\">=<\/span><span class=\"s\">\"description\"<\/span> <span class=\"na\">content<\/span><span class=\"p\">=<\/span><span class=\"s\">\"Crypto News Aggregator Application\"<\/span> <span class=\"p\">\/&gt;<\/span>\n      <span class=\"p\"\/><span class=\"nt\">head<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">body<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"si\">{<\/span><span class=\"nx\">children<\/span><span class=\"si\">}<\/span>\n      <span class=\"p\"\/><span class=\"nt\">body<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\"\/><span class=\"nt\">html<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D8%A7%D8%AC%D8%B1%D8%A7%DB%8C_%D9%BE%D8%B1%D9%88%DA%98%D9%87_%D8%B4%D9%85%D8%A7\"><\/span>\n<p>  \u0627\u062c\u0631\u0627\u06cc \u067e\u0631\u0648\u0698\u0647 \u0634\u0645\u0627<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0627\u062f\u0627\u0645\u0647 \u062f\u0647\u06cc\u062f \u0648 \u067e\u0631\u0648\u0698\u0647 \u062e\u0648\u062f \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"nx\">npm<\/span> <span class=\"nx\">run<\/span> <span class=\"nx\">dev<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u0628\u0631\u0646\u0627\u0645\u0647 \u062f\u0631 \u062d\u0627\u0644 \u0627\u062c\u0631\u0627 \u062e\u0648\u062f \u0631\u0627 \u062f\u0631 https:\/\/localhost:3000 \u067e\u06cc\u062f\u0627 \u06a9\u0646\u06cc\u062f<\/p>\n<p>\u0628\u0627\u0628\u062a \u0627\u062a\u0645\u0627\u0645 \u067e\u0631\u0648\u0698\u0647 \u062a\u0628\u0631\u06cc\u06a9 \u0645\u06cc \u06af\u0648\u06cc\u0645! \ud83c\udfc6 \ud83d\udc4f<\/p>\n<h2><span class=\"ez-toc-section\" id=\"%D8%AA%D8%B3%D8%AA_%DA%A9%D8%A7%D9%85%D9%BE%D9%88%D9%86%D9%86%D8%AA_%D8%B5%D9%81%D8%AD%D9%87\"><\/span>\n<p>  \u062a\u0633\u062a \u06a9\u0627\u0645\u067e\u0648\u0646\u0646\u062a \u0635\u0641\u062d\u0647<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0645\u0627 \u0645\u06cc\u200c\u062e\u0648\u0627\u0647\u06cc\u0645 \u0622\u0632\u0645\u0627\u06cc\u0634\u06cc \u0628\u0631\u0627\u06cc \u0645\u0624\u0644\u0641\u0647 Home \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u0645 \u06a9\u0647 \u062a\u0623\u06cc\u06cc\u062f \u0645\u06cc\u200c\u06a9\u0646\u062f \u06a9\u0647 \u0645\u062d\u062a\u0648\u0627\u06cc \u0627\u062e\u0628\u0627\u0631 \u067e\u0633 \u0627\u0632 \u0648\u0627\u06a9\u0634\u06cc \u062f\u0627\u062f\u0647\u200c\u0647\u0627 \u0628\u0647 \u062f\u0631\u0633\u062a\u06cc \u0627\u0631\u0627\u0626\u0647 \u0645\u06cc\u200c\u0634\u0648\u062f. \u0627\u062f\u0627\u0645\u0647 \u062f\u0647\u06cc\u062f \u0648 \u0627\u06cc\u0646 \u0641\u0627\u06cc\u0644 \u0622\u0632\u0645\u0627\u06cc\u0634\u06cc \u0631\u0627 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f.<\/p>\n<p><code>__tests__\/Home.test.tsx<\/code><\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">render<\/span><span class=\"p\">,<\/span> <span class=\"nx\">screen<\/span><span class=\"p\">,<\/span> <span class=\"nx\">waitFor<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">@testing-library\/react<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Home<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">@\/app\/page<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n<span class=\"nf\">describe<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">Home<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nf\">beforeEach<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"c1\">\/\/ Set up test environment variables<\/span>\n    <span class=\"nx\">process<\/span><span class=\"p\">.<\/span><span class=\"nx\">env<\/span><span class=\"p\">.<\/span><span class=\"nx\">NEXT_PUBLIC_API_URL<\/span> <span class=\"o\">=<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">http:\/\/test-api.com<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n    <span class=\"nx\">process<\/span><span class=\"p\">.<\/span><span class=\"nx\">env<\/span><span class=\"p\">.<\/span><span class=\"nx\">NEXT_PUBLIC_API_TOKEN<\/span> <span class=\"o\">=<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">test-token<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"c1\">\/\/ Mock fetch for both API endpoints<\/span>\n    <span class=\"nb\">global<\/span><span class=\"p\">.<\/span><span class=\"nx\">fetch<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">jest<\/span><span class=\"p\">.<\/span><span class=\"nf\">fn<\/span><span class=\"p\">((<\/span><span class=\"nx\">url<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"c1\">\/\/ Mock responses for different API calls<\/span>\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">url<\/span><span class=\"p\">.<\/span><span class=\"nf\">includes<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">api.coingecko.com<\/span><span class=\"dl\">'<\/span><span class=\"p\">))<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">return<\/span> <span class=\"nb\">Promise<\/span><span class=\"p\">.<\/span><span class=\"nf\">resolve<\/span><span class=\"p\">({<\/span>\n          <span class=\"na\">ok<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span>\n          <span class=\"na\">json<\/span><span class=\"p\">:<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"p\">.<\/span><span class=\"nf\">resolve<\/span><span class=\"p\">({<\/span>\n            <span class=\"na\">bitcoin<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span> <span class=\"na\">usd<\/span><span class=\"p\">:<\/span> <span class=\"mi\">65000<\/span><span class=\"p\">,<\/span> <span class=\"na\">usd_24h_change<\/span><span class=\"p\">:<\/span> <span class=\"mf\">2.5<\/span> <span class=\"p\">}<\/span>\n          <span class=\"p\">}),<\/span>\n          <span class=\"na\">status<\/span><span class=\"p\">:<\/span> <span class=\"mi\">200<\/span><span class=\"p\">,<\/span>\n        <span class=\"p\">}<\/span> <span class=\"k\">as<\/span> <span class=\"nx\">Response<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">}<\/span>\n      <span class=\"k\">return<\/span> <span class=\"nb\">Promise<\/span><span class=\"p\">.<\/span><span class=\"nf\">resolve<\/span><span class=\"p\">({<\/span>\n        <span class=\"na\">ok<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span>\n        <span class=\"na\">json<\/span><span class=\"p\">:<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nb\">Promise<\/span><span class=\"p\">.<\/span><span class=\"nf\">resolve<\/span><span class=\"p\">({<\/span>\n          <span class=\"na\">data<\/span><span class=\"p\">:<\/span> <span class=\"p\">[{<\/span>\n            <span class=\"na\">id<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">1<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">title<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">News Title<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">description<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">News Description<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">url<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">https:\/\/test.com<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span>\n            <span class=\"na\">published_at<\/span><span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">2024-03-25<\/span><span class=\"dl\">'<\/span>\n          <span class=\"p\">}]<\/span>\n        <span class=\"p\">}),<\/span>\n        <span class=\"na\">status<\/span><span class=\"p\">:<\/span> <span class=\"mi\">200<\/span><span class=\"p\">,<\/span>\n      <span class=\"p\">}<\/span> <span class=\"k\">as<\/span> <span class=\"nx\">Response<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">})<\/span> <span class=\"k\">as<\/span> <span class=\"nx\">jest<\/span><span class=\"p\">.<\/span><span class=\"nx\">Mock<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">});<\/span>\n\n  <span class=\"nf\">test<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">renders news feed<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"k\">async <\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nf\">render<\/span><span class=\"p\">(&lt;<\/span><span class=\"nc\">Home<\/span> <span class=\"p\">\/&gt;);<\/span>\n    <span class=\"k\">await<\/span> <span class=\"nf\">waitFor<\/span><span class=\"p\">(<\/span>\n      <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nf\">expect<\/span><span class=\"p\">(<\/span><span class=\"nx\">screen<\/span><span class=\"p\">.<\/span><span class=\"nf\">getByText<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">News Title<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)).<\/span><span class=\"nf\">toBeInTheDocument<\/span><span class=\"p\">(),<\/span>\n      <span class=\"p\">{<\/span> <span class=\"na\">timeout<\/span><span class=\"p\">:<\/span> <span class=\"mi\">3000<\/span> <span class=\"p\">}<\/span>\n    <span class=\"p\">);<\/span>\n  <span class=\"p\">});<\/span>\n<span class=\"p\">});<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u062a\u0633\u062a \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight tsx\"><code><span class=\"nx\">npm<\/span> <span class=\"nx\">run<\/span> <span class=\"nx\">test<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u0648\u0627\u0631\u062f \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u0627\u06cc\u0646 \u0622\u0632\u0645\u0627\u06cc\u0634 \u062a\u0623\u06cc\u06cc\u062f \u0645\u06cc\u200c\u06a9\u0646\u062f \u06a9\u0647 \u0645\u0624\u0644\u0641\u0647 Home \u0645\u0627 \u0628\u0627 \u0645\u0648\u0641\u0642\u06cc\u062a \u0645\u062d\u062a\u0648\u0627\u06cc \u0627\u062e\u0628\u0627\u0631 \u0631\u0627 \u067e\u0633 \u0627\u0632 \u0648\u0627\u06a9\u0634\u06cc \u062f\u0627\u062f\u0647\u200c\u0647\u0627 \u0627\u0631\u0627\u0626\u0647 \u0645\u06cc\u200c\u06a9\u0646\u062f. <\/p>\n<p>\u062a\u0633\u062a \u0647\u0627\u06cc \u0627\u0636\u0627\u0641\u06cc \u0628\u0631\u0627\u06cc \u0627\u062c\u0632\u0627\u06cc PriceTicker \u0648 NewsCard \u0631\u0627 \u0645\u06cc \u062a\u0648\u0627\u0646 \u062f\u0631 \u0645\u062e\u0632\u0646 GitHub \u067e\u0631\u0648\u0698\u0647 \u06cc\u0627\u0641\u062a. \u0627\u06cc\u0646 \u062a\u0633\u062a\u200c\u0647\u0627 \u0639\u0645\u0644\u06a9\u0631\u062f \u0648 \u0631\u0641\u062a\u0627\u0631 \u0631\u0646\u062f\u0631\u06cc\u0646\u06af \u0631\u0627 \u067e\u0648\u0634\u0634 \u0645\u06cc\u200c\u062f\u0647\u0646\u062f. \u0645\u0646 \u0634\u0645\u0627 \u0631\u0627 \u062a\u0634\u0648\u06cc\u0642 \u0645\u06cc \u06a9\u0646\u0645 \u06a9\u0647 \u062a\u0633\u062a \u0647\u0627\u06cc \u0628\u06cc\u0634\u062a\u0631\u06cc \u0628\u0631\u0627\u06cc \u0627\u06cc\u0646 \u067e\u0631\u0648\u0698\u0647 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0646\u06cc\u062f.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"%D8%A8%D9%87%D8%A8%D9%88%D8%AF_%D8%A8%DB%8C%D8%B4%D8%AA%D8%B1_%D8%A7%DB%8C%D9%86_%D9%BE%D8%B1%D9%88%DA%98%D9%87_%D8%B1%D8%A7_%D8%AF%D8%B1_%D9%86%D8%B8%D8%B1_%D8%A8%DA%AF%DB%8C%D8%B1%DB%8C%D8%AF\"><\/span>\n<p>  \u0628\u0647\u0628\u0648\u062f \u0628\u06cc\u0634\u062a\u0631 \u0627\u06cc\u0646 \u067e\u0631\u0648\u0698\u0647 \u0631\u0627 \u062f\u0631 \u0646\u0638\u0631 \u0628\u06af\u06cc\u0631\u06cc\u062f.<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0686\u0646\u062f \u0627\u06cc\u062f\u0647:<\/p>\n<ul>\n<li>\u0627\u062c\u0631\u0627\u06cc \u062d\u0627\u0644\u062a \u0647\u0627\u06cc \u0628\u0627\u0631\u06af\u0630\u0627\u0631\u06cc \u0645\u0646\u0627\u0633\u0628<\/li>\n<li>\u0635\u0641\u062d\u0647 \u0628\u0646\u062f\u06cc \u0628\u0631\u0627\u06cc \u0627\u062e\u0628\u0627\u0631 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f<\/li>\n<li>\u0630\u062e\u06cc\u0631\u0647 \u0633\u0627\u0632\u06cc \u067e\u06cc\u0686\u06cc\u062f\u0647 \u062a\u0631\u06cc \u0631\u0627 \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0646\u06cc\u062f<\/li>\n<li>\u0645\u062c\u0645\u0648\u0639\u0647 \u0622\u0632\u0645\u0627\u06cc\u0634\u06cc \u0631\u0627 \u062a\u0642\u0648\u06cc\u062a \u06a9\u0646\u06cc\u062f<\/li>\n<li>\u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u067e\u0627\u0631\u0627\u0645\u062a\u0631 \u067e\u0631\u0633 \u0648 \u062c\u0648 \u0645\u0648\u0636\u0648\u0639 \u0631\u0627 \u0628\u0631\u0627\u06cc \u0648\u0627\u06a9\u0634\u06cc \u0627\u0646\u0648\u0627\u0639 \u0645\u062e\u062a\u0644\u0641 \u0627\u062e\u0628\u0627\u0631 \u062a\u063a\u06cc\u06cc\u0631 \u062f\u0647\u06cc\u062f<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"%D8%A7%D8%B2_%D8%A7%DB%8C%D9%86%DA%A9%D9%87_%D8%AF%D9%86%D8%A8%D8%A7%D9%84_%D9%85%DB%8C_%DA%A9%D9%86%DB%8C%D8%AF_%D9%85%D8%AA%D8%B4%DA%A9%D8%B1%D9%85_%F0%9F%98%84\"><\/span>\n<p>  \u0627\u0632 \u0627\u06cc\u0646\u06a9\u0647 \u062f\u0646\u0628\u0627\u0644 \u0645\u06cc \u06a9\u0646\u06cc\u062f \u0645\u062a\u0634\u06a9\u0631\u0645 \ud83d\ude04<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0627\u0639\u062a\u0628\u0627\u0631 \u062a\u0635\u0648\u06cc\u0631 \u062c\u0644\u062f: \u0639\u06a9\u0633 \u062a\u0648\u0633\u0637 \u067e\u0631\u0648\u0698\u0647 \u0633\u0647\u0627\u0645 RDNE: https:\/\/www.pexels.com\/photo\/selective-focus-photo-of-silver-and-gold-bitcoins-8369648\/<\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Summarize this content to 400 words in Persian Lang \u062f\u0631 \u0627\u06cc\u0646 \u0645\u0642\u0627\u0644\u0647\u060c \u0645\u06cc\u200c\u062e\u0648\u0627\u0647\u06cc\u0645 \u06cc\u06a9 \u0628\u0631\u0646\u0627\u0645\u0647 \u0633\u0627\u062f\u0647 \u0627\u0645\u0627 \u0645\u0641\u06cc\u062f \u0628\u0631\u0627\u06cc \u062c\u0645\u0639\u200c\u0622\u0648\u0631\u06cc \u0627\u062e\u0628\u0627\u0631 \u0627\u0631\u0632\u0647\u0627\u06cc \u062f\u06cc\u062c\u06cc\u062a\u0627\u0644 \u0628\u0633\u0627\u0632\u06cc\u0645 \u06a9\u0647 \u0627\u0632 NewsDataHub \u0648 API\u0647\u0627\u06cc CoinGecko \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc\u200c\u06a9\u0646\u062f. \u0647\u062f\u0641 \u0627\u06cc\u0646 \u0645\u0642\u0627\u0644\u0647 \u06cc\u06a9 \u062a\u0648\u0633\u0639\u0647\u200c\u062f\u0647\u0646\u062f\u0647 \u0633\u0637\u062d \u0645\u0628\u062a\u062f\u06cc \u0627\u0633\u062a &#8211; \u0627\u06af\u0631 \u0641\u06a9\u0631 \u0645\u06cc\u200c\u06a9\u0646\u06cc\u062f \u0647\u0631 \u0628\u062e\u0634 \u0627\u0631\u0632\u0634\u06cc \u0628\u0647 \u062a\u062c\u0631\u0628\u0647 \u06cc\u0627\u062f\u06af\u06cc\u0631\u06cc \u0634\u0645\u0627 \u0646\u0645\u06cc\u200c\u0627\u0641\u0632\u0627\u06cc\u062f\u060c \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u06cc\u062f \u0627\u0632 \u0622\u0646 &hellip;<\/p>\n","protected":false},"author":2,"featured_media":88710,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"","fifu_image_alt":"","footnotes":""},"categories":[339],"tags":[],"class_list":["post-88709","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dev"],"_links":{"self":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts\/88709","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/comments?post=88709"}],"version-history":[{"count":0,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts\/88709\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/media\/88710"}],"wp:attachment":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/media?parent=88709"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/categories?post=88709"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/tags?post=88709"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}