6 |
7 |
8 |
9 | ## Credits/Disclaimer
10 |
11 | This website, created solely for educational purposes, demonstrates web scraping and proxy techniques. The images are accessed through publicly available media using MKBHD's Panels app API.
12 |
13 | API information available [here](https://github.com/panels-app/panels-api).
14 |
--------------------------------------------------------------------------------
/components.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://ui.shadcn.com/schema.json",
3 | "style": "default",
4 | "rsc": true,
5 | "tsx": true,
6 | "tailwind": {
7 | "config": "tailwind.config.ts",
8 | "css": "src/app/globals.css",
9 | "baseColor": "neutral",
10 | "cssVariables": true,
11 | "prefix": ""
12 | },
13 | "aliases": {
14 | "components": "@/components",
15 | "utils": "@/lib/utils",
16 | "ui": "@/components/ui",
17 | "lib": "@/lib",
18 | "hooks": "@/hooks"
19 | }
20 | }
--------------------------------------------------------------------------------
/src/lib/error.ts:
--------------------------------------------------------------------------------
1 | import { toast } from "sonner"
2 |
3 | export function getErrorMessage(err: unknown) {
4 | if (err instanceof Error) {
5 | return err.message
6 | }
7 |
8 | return "Something went wrong. Please try again later."
9 | }
10 |
11 | export function showErrorToast(err: unknown) {
12 | const errorMessage = getErrorMessage(err)
13 | return toast.error(errorMessage)
14 | }
15 |
16 | export function catchError(err: unknown) {
17 | return {
18 | data: null,
19 | error: getErrorMessage(err),
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 | .yarn/install-state.gz
8 |
9 | # testing
10 | /coverage
11 |
12 | /node
13 |
14 | # next.js
15 | /.next/
16 | /out/
17 |
18 | # production
19 | /build
20 |
21 | # misc
22 | .DS_Store
23 | *.pem
24 |
25 | # debug
26 | npm-debug.log*
27 | yarn-debug.log*
28 | yarn-error.log*
29 |
30 | # local env files
31 | .env*.local
32 | .env
33 |
34 | # vercel
35 | .vercel
36 |
37 | # typescript
38 | *.tsbuildinfo
39 | next-env.d.ts
40 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": ["dom", "dom.iterable", "esnext"],
4 | "allowJs": true,
5 | "skipLibCheck": true,
6 | "strict": true,
7 | "noEmit": true,
8 | "esModuleInterop": true,
9 | "module": "esnext",
10 | "moduleResolution": "bundler",
11 | "resolveJsonModule": true,
12 | "isolatedModules": true,
13 | "jsx": "preserve",
14 | "incremental": true,
15 | "plugins": [
16 | {
17 | "name": "next"
18 | }
19 | ],
20 | "paths": {
21 | "@/*": ["./src/*"]
22 | }
23 | },
24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
25 | "exclude": ["node_modules"]
26 | }
27 |
--------------------------------------------------------------------------------
/src/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import "./globals.css"
2 | import type { Metadata } from "next"
3 | import { Inter } from "next/font/google"
4 | import { Disclaimer } from "@/components/disclaimer"
5 |
6 | const inter = Inter({ subsets: ["latin"] })
7 |
8 | export const metadata: Metadata = {
9 | title: "Panels Wallpapers",
10 | }
11 |
12 | export default function RootLayout({
13 | children,
14 | }: Readonly<{
15 | children: React.ReactNode
16 | }>) {
17 | return (
18 |
19 |
20 |