├── .husky ├── .gitignore ├── pre-commit └── pre-push ├── __tests__ ├── styleMock.js ├── stubs │ ├── index.js │ ├── useStubs.ts │ ├── buildUser.js │ └── utils.js ├── mocks │ ├── index.js │ ├── browser.js │ ├── server.js │ ├── handlers │ │ ├── index.js │ │ ├── graphql │ │ │ └── query_users_me.js │ │ ├── rest │ │ │ └── mswping.js │ │ └── storage.js │ └── MswProvider.tsx ├── chance.js ├── test-utils.js └── components │ └── SanityCheck.test.js ├── src ├── styles │ ├── globals.css │ ├── tailwind.css │ ├── antd.less │ ├── tailwind-antd-compat.less │ └── Home.module.css ├── components │ ├── LinkPreview │ │ ├── index.tsx │ │ ├── controller.tsx │ │ └── elements.tsx │ ├── _preview │ │ ├── containers │ │ │ ├── StripePreview │ │ │ │ ├── index.tsx │ │ │ │ ├── controller.tsx │ │ │ │ └── elements.tsx │ │ │ ├── VercelPreview │ │ │ │ ├── style.module.css │ │ │ │ └── index.tsx │ │ │ ├── TailwindPreview.tsx │ │ │ ├── BaseWebPreview │ │ │ │ ├── Rating.tsx │ │ │ │ ├── PinCode.tsx │ │ │ │ ├── DragAndDrop.tsx │ │ │ │ ├── Select.tsx │ │ │ │ ├── Menu.tsx │ │ │ │ ├── PaymentCard.tsx │ │ │ │ ├── ProgressBar.tsx │ │ │ │ ├── DatePicker.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── FileUploader.tsx │ │ │ ├── AntdPreview │ │ │ │ ├── Progress.tsx │ │ │ │ ├── ProgressCircle.tsx │ │ │ │ ├── Buttons.tsx │ │ │ │ ├── ModalBasic.tsx │ │ │ │ ├── CardWithLoading.tsx │ │ │ │ ├── Badge.tsx │ │ │ │ ├── Collapse.tsx │ │ │ │ ├── ProgressWithCustomStroke.tsx │ │ │ │ ├── SwitchablePicker.tsx │ │ │ │ ├── DatePickerSize.tsx │ │ │ │ ├── ModalDialog.tsx │ │ │ │ ├── Tabs.tsx │ │ │ │ ├── Carousel.tsx │ │ │ │ ├── Drawer.tsx │ │ │ │ ├── ModalWithFooter.tsx │ │ │ │ ├── DynamicBadge.tsx │ │ │ │ ├── AvatarGroup.tsx │ │ │ │ ├── TabsCloseable.tsx │ │ │ │ ├── Calendar.tsx │ │ │ │ ├── ModalDraggable.tsx │ │ │ │ ├── Table.tsx │ │ │ │ ├── Popconfirm.tsx │ │ │ │ └── index.tsx │ │ │ ├── LottiePreview.tsx │ │ │ ├── ContentPlaceholder.tsx │ │ │ ├── Grid.tsx │ │ │ └── TransitionsPreview.tsx │ │ ├── getGithubUrl.ts │ │ ├── components.tsx │ │ ├── index.tsx │ │ └── DisGui.tsx │ ├── base │ │ ├── transitions │ │ │ ├── types.tsx │ │ │ ├── FadeIn.tsx │ │ │ ├── Rotate90.tsx │ │ │ ├── SlideOver.tsx │ │ │ ├── FadeInScale.tsx │ │ │ ├── Collapse.tsx │ │ │ ├── PopOut.tsx │ │ │ └── SlideDown.tsx │ │ ├── Error404.tsx │ │ ├── lazyload.tsx │ │ ├── FullPageContainer.tsx │ │ ├── ErrorFallback.tsx │ │ ├── ErrorBoundary.tsx │ │ └── DotsLoader.tsx │ ├── SendFeedback.tsx │ ├── SEO.tsx │ └── ToggleDarkMode.tsx ├── lib │ ├── github │ │ └── getGithubUrl.ts │ ├── date │ │ └── dateFromSecond.ts │ ├── parseUrls.ts │ ├── unfurl │ │ └── getMetadata.ts │ ├── stripe │ │ ├── init.ts │ │ └── formatAmountForStripe.ts │ ├── analytic │ │ ├── nextjs-hook.ts │ │ └── index.ts │ └── logger.ts ├── config │ ├── app.ts │ ├── seo.ts │ └── analytic.ts ├── hooks │ └── useDarkMode.ts ├── utils │ └── trackGoal.ts └── services │ └── stripe-webhook │ ├── mock-db.ts │ └── index.ts ├── .vercelignore ├── docs ├── buildsize.jpeg └── lighthouse-report.jpg ├── public ├── favicon.ico ├── og-default.jpg ├── vercel.svg └── darkmode-noflash.js ├── next-env.d.ts ├── pages ├── _preview │ ├── [component].tsx │ └── StripePreview.tsx ├── api │ ├── hello.js │ ├── stripe │ │ ├── [...nextstripe].js │ │ ├── checkPayment.ts │ │ └── getCustomerPlans.ts │ ├── unfurl.ts │ └── webhook │ │ └── stripe.js ├── _app.tsx ├── robots.txt.tsx ├── _document.tsx └── index.tsx ├── .prettierrc ├── postcss.config.js ├── checkly ├── snippets │ ├── viewports_desktop.js │ ├── viewports_mobile.js │ ├── wait.js │ ├── publicPages.js │ ├── takeScreenshots.js │ └── takeScreenshot.js └── visual_tests │ └── public_pages.js ├── .github ├── test_checker.yml ├── stale.yml └── config.yml ├── .lintstagedrc ├── .babelrc ├── .vscode ├── settings.sample.json └── extensions.json ├── apollo.config.js ├── tailwind.config.js ├── .gitignore ├── jest.setup.js ├── jest.config.js ├── tsconfig.json ├── .env ├── next.config.js ├── README.md ├── next-handlers.js └── package.json /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /__tests__/styleMock.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; 2 | -------------------------------------------------------------------------------- /src/styles/globals.css: -------------------------------------------------------------------------------- 1 | @import './tailwind.css'; 2 | -------------------------------------------------------------------------------- /.vercelignore: -------------------------------------------------------------------------------- 1 | checkly 2 | 3 | # Ignore test files 4 | jest* 5 | __tests__/pages -------------------------------------------------------------------------------- /__tests__/stubs/index.js: -------------------------------------------------------------------------------- 1 | export * from './buildUser'; 2 | export * from './utils'; 3 | -------------------------------------------------------------------------------- /docs/buildsize.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzulfikar/nextjs-10/HEAD/docs/buildsize.jpeg -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzulfikar/nextjs-10/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn husky:pre-commit 5 | -------------------------------------------------------------------------------- /next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /public/og-default.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzulfikar/nextjs-10/HEAD/public/og-default.jpg -------------------------------------------------------------------------------- /docs/lighthouse-report.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzulfikar/nextjs-10/HEAD/docs/lighthouse-report.jpg -------------------------------------------------------------------------------- /pages/_preview/[component].tsx: -------------------------------------------------------------------------------- 1 | import Preview from '@src/components/_preview'; 2 | 3 | export default Preview; 4 | -------------------------------------------------------------------------------- /src/components/LinkPreview/index.tsx: -------------------------------------------------------------------------------- 1 | import controller from './controller'; 2 | 3 | export default controller; 4 | -------------------------------------------------------------------------------- /src/components/_preview/containers/StripePreview/index.tsx: -------------------------------------------------------------------------------- 1 | import controller from './controller'; 2 | 3 | export default controller; 4 | -------------------------------------------------------------------------------- /.husky/pre-push: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | # Make sure all codes are type-checked before pushing 5 | yarn husky:pre-push 6 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 2, 4 | "semi": true, 5 | "singleQuote": true, 6 | "printWidth": 80 7 | } -------------------------------------------------------------------------------- /src/components/_preview/containers/VercelPreview/style.module.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Inter:wght@900&display=swap'); 2 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | "@tailwindcss/jit": {}, 4 | autoprefixer: {}, 5 | "postcss-preset-env": {}, 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /__tests__/mocks/index.js: -------------------------------------------------------------------------------- 1 | if (typeof window === 'undefined') { 2 | require('./server').default.listen(); 3 | } else { 4 | require('./browser').default.start(); 5 | } 6 | -------------------------------------------------------------------------------- /__tests__/mocks/browser.js: -------------------------------------------------------------------------------- 1 | import { setupWorker } from 'msw'; 2 | import handlers from './handlers'; 3 | 4 | const worker = setupWorker(...handlers); 5 | 6 | export default worker; 7 | -------------------------------------------------------------------------------- /checkly/snippets/viewports_desktop.js: -------------------------------------------------------------------------------- 1 | const viewports = [{ width: 1280, height: 1280 }]; 2 | 3 | // [CHECKLY] Omit these lines when adding to checkly 4 | module.exports = viewports; 5 | -------------------------------------------------------------------------------- /src/lib/github/getGithubUrl.ts: -------------------------------------------------------------------------------- 1 | export default function getGithubUrl({ owner, repo, branch, file }) { 2 | return `https://github.com/${owner}/${repo}/blob/${branch}/${file}`; 3 | } 4 | -------------------------------------------------------------------------------- /__tests__/mocks/server.js: -------------------------------------------------------------------------------- 1 | import { setupServer } from 'msw/node'; 2 | import handlers from './handlers'; 3 | 4 | const server = setupServer(...handlers); 5 | 6 | export default server; 7 | -------------------------------------------------------------------------------- /pages/api/hello.js: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | 3 | export default (req, res) => { 4 | res.status(200).json({ name: 'John Doe' }) 5 | } 6 | -------------------------------------------------------------------------------- /checkly/snippets/viewports_mobile.js: -------------------------------------------------------------------------------- 1 | const viewports = [{ width: 375, height: 812 }]; // iPhone 11 Pro 2 | 3 | // [CHECKLY] Omit these lines when adding to checkly 4 | module.exports = viewports; 5 | -------------------------------------------------------------------------------- /src/config/app.ts: -------------------------------------------------------------------------------- 1 | export const appName = process.env.NEXT_PUBLIC_APP_NAME; 2 | export const baseUrl = process.env.NEXT_PUBLIC_BASE_URL; 3 | 4 | export default { 5 | appName, 6 | baseUrl, 7 | }; 8 | -------------------------------------------------------------------------------- /__tests__/mocks/handlers/index.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | /* GraphQL handlers */ 3 | require('./graphql/query_users_me').handler, 4 | 5 | /* REST handlers */ 6 | require('./rest/mswping').handler, 7 | ]; 8 | -------------------------------------------------------------------------------- /__tests__/chance.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Wrapper for chance.js 3 | */ 4 | 5 | import Chance from 'chance'; 6 | 7 | const seed = '123123'; 8 | const chance = new Chance(seed); 9 | 10 | export default chance; 11 | -------------------------------------------------------------------------------- /src/lib/date/dateFromSecond.ts: -------------------------------------------------------------------------------- 1 | export default function dateFromSecond(secs: number): Date { 2 | const t = new Date('1970-01-01T00:30:00Z'); // Unix epoch start. 3 | t.setSeconds(secs); 4 | return t; 5 | } 6 | -------------------------------------------------------------------------------- /checkly/snippets/wait.js: -------------------------------------------------------------------------------- 1 | const wait = (time) => 2 | new Promise(function (resolve) { 3 | setTimeout(resolve, time); 4 | }); 5 | 6 | // [CHECKLY] Omit these lines when adding to checkly 7 | module.exports = wait; 8 | -------------------------------------------------------------------------------- /src/components/base/transitions/types.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | export type TransitionProps = { 4 | show: boolean; 5 | appear?: boolean; 6 | duration?: string; 7 | children: ReactNode; 8 | }; 9 | -------------------------------------------------------------------------------- /.github/test_checker.yml: -------------------------------------------------------------------------------- 1 | # See docs: https://github.com/infection/tests-checker 2 | comment: "Hello! Please consider adding a test to make sure this change works as expected." 3 | fileExtensions: [".ts", ".js", ".tsx", ".jsx"] 4 | testDir: "__tests__" 5 | -------------------------------------------------------------------------------- /src/hooks/useDarkMode.ts: -------------------------------------------------------------------------------- 1 | import _useDarkMode from 'use-dark-mode'; 2 | 3 | export default function useDarkMode(initialValue: boolean) { 4 | return _useDarkMode(initialValue, { 5 | classNameDark: 'dark', 6 | classNameLight: 'light', 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /checkly/snippets/publicPages.js: -------------------------------------------------------------------------------- 1 | const publicPages = [ 2 | '/', 3 | '/signup', 4 | '/login', 5 | '/blog', 6 | '/legal/privacy-policy', 7 | '/help', 8 | '/features', 9 | ]; 10 | 11 | // [CHECKLY] Omit below lines when adding to checkly 12 | module.exports = publicPages; 13 | -------------------------------------------------------------------------------- /pages/api/stripe/[...nextstripe].js: -------------------------------------------------------------------------------- 1 | import NextStripe from 'next-stripe'; 2 | 3 | /** 4 | * Run this command to see what routes are handled by next-stripe: 5 | * `ls -1 node_modules/next-stripe/dist/server/routes` 6 | */ 7 | export default NextStripe({ 8 | stripe_key: process.env.STRIPE_RESTRICTED_KEY, 9 | }); 10 | -------------------------------------------------------------------------------- /.lintstagedrc: -------------------------------------------------------------------------------- 1 | { 2 | "src/**/*.{js,jsx,ts,tsx,json,css}": [ 3 | "prettier --write" 4 | ], 5 | "__tests__/**/*.{js,ts,json}": [ 6 | "prettier --write" 7 | ], 8 | "pages/**/*.{js,ts,jsx,tsx}": [ 9 | "prettier --write" 10 | ], 11 | "checkly/**/*.{js}": [ 12 | "prettier --write" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /__tests__/mocks/handlers/graphql/query_users_me.js: -------------------------------------------------------------------------------- 1 | import { graphql } from 'msw'; 2 | import { buildUser } from '@tests/stubs'; 3 | 4 | const user = buildUser(); 5 | 6 | const stub = { 7 | user: user, 8 | }; 9 | 10 | export const handler = graphql.query('users_me', (req, res, ctx) => { 11 | return res(ctx.data(stub)); 12 | }); 13 | -------------------------------------------------------------------------------- /src/lib/parseUrls.ts: -------------------------------------------------------------------------------- 1 | import linkifyIt from 'linkify-it'; 2 | 3 | let linkify = null; 4 | 5 | /** 6 | * Parse http(s) urls from text 7 | */ 8 | export default function parseUrls(text: string): linkifyIt.Match[] | null { 9 | if (!linkify) linkify = linkifyIt(); 10 | 11 | return linkify.match(text)?.filter(({ url }) => url.startsWith('http')); 12 | } 13 | -------------------------------------------------------------------------------- /src/components/_preview/containers/TailwindPreview.tsx: -------------------------------------------------------------------------------- 1 | export default function TailwindPreview() { 2 | return ( 3 |
4 | 5 | Hello from Tailwind v2! 6 | 7 |
8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "next/babel" 4 | ], 5 | "plugins": [ 6 | [ 7 | "import", 8 | { 9 | "libraryName": "antd" 10 | } 11 | ] 12 | ], 13 | "env": { 14 | "test": { 15 | "plugins": [ 16 | "dynamic-import-node" 17 | ] 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /.vscode/settings.sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | ".next": true, 4 | ".build": true, 5 | "node_modules": true 6 | }, 7 | "jest.autoEnable": false, 8 | "githubIssues.issueBranchTitle": "${user}/issue-${issueNumber}", 9 | "githubIssues.workingIssueFormatScm": "${issueTitle}. ${issueNumberLabel}", 10 | "githubPullRequests.telemetry.enabled": false 11 | } -------------------------------------------------------------------------------- /apollo.config.js: -------------------------------------------------------------------------------- 1 | if (!process.env.APOLLO_KEY) { 2 | throw new Error( 3 | 'Environment error: could not load `APOLLO_KEY` from `.env.local` file.' 4 | ); 5 | } 6 | 7 | module.exports = { 8 | client: { 9 | service: { 10 | name: process.env.NEXT_PUBLIC_APOLLO_SERVICE, 11 | url: process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT, 12 | }, 13 | includes: ['./src/**/*.ts'], 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /src/components/base/Error404.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | import Error from 'next/error'; 3 | 4 | import logger from '@src/lib/logger'; 5 | 6 | /** 7 | * `Error404` renders a full page 404 error message and logs the request. 8 | */ 9 | export default function Error404() { 10 | useEffect(() => { 11 | logger.info('page not found:', window.location.href); 12 | }, []); 13 | 14 | return ; 15 | } 16 | -------------------------------------------------------------------------------- /src/components/base/lazyload.tsx: -------------------------------------------------------------------------------- 1 | import dynamic from 'next/dynamic'; 2 | 3 | import DotsLoader from './DotsLoader'; 4 | 5 | /** 6 | * `lazyload` wraps next/dynamic with common defaults for our app context. 7 | */ 8 | const lazyload: typeof dynamic = ( 9 | component, 10 | { ssr = true, loading = () => } = {} 11 | ) => 12 | dynamic(component, { 13 | loading, 14 | ssr, 15 | }); 16 | 17 | export default lazyload; 18 | -------------------------------------------------------------------------------- /src/utils/trackGoal.ts: -------------------------------------------------------------------------------- 1 | import { events } from '@src/config/analytic'; 2 | import { trackGoal as _trackGoal } from '@src/lib/analytic'; 3 | 4 | export default function trackGoal( 5 | event: keyof typeof events, 6 | centValue?: number 7 | ) { 8 | if (process.env.NODE_ENV === 'production') { 9 | _trackGoal({ ...events[event], centValue }); 10 | } else { 11 | console.log('[dev][analytic] trackGoal:', events[event]); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/lib/unfurl/getMetadata.ts: -------------------------------------------------------------------------------- 1 | type MetadataResponse = { 2 | metadata?: any; 3 | error?: any; 4 | }; 5 | 6 | export default async function getMetadata( 7 | unfurlEndpoint: string, 8 | targetUrl: string 9 | ): Promise { 10 | return fetch(`${unfurlEndpoint}?url=${encodeURI(targetUrl)}`) 11 | .then(async (res) => ({ metadata: await res.json() })) 12 | .catch((e) => ({ error: '[unfurl] getMetadata failed: ' + e.message })); 13 | } 14 | -------------------------------------------------------------------------------- /src/components/_preview/containers/BaseWebPreview/Rating.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {StarRating} from 'baseui/rating'; 3 | 4 | RatingDemo.title ="Rating" 5 | RatingDemo.url ="https://v9-9-0.baseweb.design/components/rating" 6 | 7 | export default function RatingDemo() { 8 | const [value, setValue] = React.useState(1); 9 | return ( 10 | setValue(value)} 13 | /> 14 | ); 15 | }; -------------------------------------------------------------------------------- /src/components/_preview/containers/BaseWebPreview/PinCode.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { PinCode } from 'baseui/pin-code'; 3 | 4 | PinCodeDemo.title = 'PinCode'; 5 | PinCodeDemo.url = 'https://v9-9-0.baseweb.design/components/pin-code'; 6 | 7 | export default function PinCodeDemo() { 8 | const [values, setValues] = React.useState(['', '', '', '']); 9 | return ( 10 | setValues(values)} /> 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /__tests__/mocks/handlers/rest/mswping.js: -------------------------------------------------------------------------------- 1 | import { rest } from 'msw'; 2 | 3 | /** 4 | * /mswping is a handler to verify that msw is actually running. 5 | * To test, run this code in your browser console: 6 | * 7 | * `fetch('/mswping').then(res => res.json()).then(console.log).catch(console.log)` 8 | */ 9 | export const handler = rest.get('/mswping', (req, res, ctx) => { 10 | return res( 11 | ctx.json({ 12 | ok: true, 13 | msg: 'msw is running!', 14 | }) 15 | ); 16 | }); 17 | -------------------------------------------------------------------------------- /__tests__/mocks/handlers/storage.js: -------------------------------------------------------------------------------- 1 | let storage = {}; 2 | 3 | function put(key, fn) { 4 | if (!process.browser) return; 5 | 6 | const data = fn(get(key)); 7 | 8 | console.log('[msw] storage.put:', key, data); 9 | 10 | storage[key] = data; 11 | } 12 | 13 | function get(key) { 14 | if (!process.browser) return; 15 | 16 | console.log('[msw] storage.get:', key, storage[key]); 17 | 18 | return storage[key]; 19 | } 20 | 21 | module.exports.get = get; 22 | module.exports.put = put; 23 | -------------------------------------------------------------------------------- /__tests__/test-utils.js: -------------------------------------------------------------------------------- 1 | import { render } from '@testing-library/react'; 2 | 3 | // Add in any providers here if necessary: 4 | // (ReduxProvider, ThemeProvider, etc) 5 | const Providers = ({ children }) => { 6 | return children; 7 | }; 8 | 9 | const customRender = (ui, options = {}) => 10 | render(ui, { wrapper: Providers, ...options }); 11 | 12 | // re-export everything 13 | export * from '@testing-library/react'; 14 | 15 | // override render method 16 | export { customRender as render }; 17 | -------------------------------------------------------------------------------- /src/components/base/FullPageContainer.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Get css class for FullPageContainer. 3 | * By default, `bgColor` is not specified. 4 | */ 5 | export const className = ({ bgColor = '' } = {} as any) => 6 | `${bgColor} h-screen flex flex-col xy-center`; 7 | 8 | export default function FullPageContainer({ 9 | bgColor = undefined, 10 | children, 11 | ...props 12 | }) { 13 | return ( 14 |
15 | {children} 16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /pages/_app.tsx: -------------------------------------------------------------------------------- 1 | // NOTE: somehow the styles won't be applied if using `import` 2 | require('@src/styles/globals.css'); 3 | 4 | import { DefaultSeo } from 'next-seo'; 5 | 6 | import useAnalytic from '@src/lib/analytic/nextjs-hook'; 7 | import seoConfig from '@src/config/seo'; 8 | 9 | function MyApp({ Component, pageProps }) { 10 | useAnalytic(); 11 | 12 | return ( 13 | <> 14 | 15 | 16 | 17 | ); 18 | } 19 | 20 | export default MyApp; 21 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | purge: [ 3 | "./pages/**/*.{js,jsx,ts,tsx}", 4 | "./src/**/*.{js,jsx,ts,tsx}" 5 | ], 6 | darkMode: 'class', 7 | theme: {}, 8 | corePlugins: { 9 | // If tailwind conflicts with your existing styles, try set `preflight` 10 | // to false to disable tailwind css reset. 11 | // See: https://tailwindcss.com/docs/preflight#disabling-preflight 12 | preflight: true, 13 | }, 14 | plugins: [ 15 | require('@tailwindcss/line-clamp'), 16 | ] 17 | }; 18 | -------------------------------------------------------------------------------- /src/lib/stripe/init.ts: -------------------------------------------------------------------------------- 1 | import Stripe from 'stripe'; 2 | 3 | /** 4 | * @description 5 | * Create stripe instance (server-side) using `STRIPE_RESTRICTED_KEY` environment variable. 6 | * 7 | * @example 8 | * import initStripe from '@src/lib/stripe/init 9 | * const stripe = initStripe() 10 | */ 11 | const initStripe = () => 12 | new Stripe(process.env.STRIPE_RESTRICTED_KEY, { 13 | // https://github.com/stripe/stripe-node#configuration 14 | apiVersion: '2020-08-27', 15 | }); 16 | 17 | export default initStripe; 18 | -------------------------------------------------------------------------------- /pages/robots.txt.tsx: -------------------------------------------------------------------------------- 1 | const getRobots = () => `# Welcome to ${process.env.NEXT_PUBLIC_APP_NAME} 2 | Sitemap: ${process.env.NEXT_PUBLIC_BASE_URL}/sitemap.xml 3 | 4 | User-agent: * 5 | Allow: /* 6 | 7 | Disallow: /api/* 8 | Disallow: /_preview/* 9 | `; 10 | 11 | export default function RobotsTxtPage() { 12 | return null; 13 | } 14 | 15 | export async function getServerSideProps({ res }) { 16 | res.setHeader('Content-Type', 'text/plain'); 17 | res.write(getRobots()); 18 | res.end(); 19 | 20 | return { props: {} }; 21 | } 22 | -------------------------------------------------------------------------------- /src/components/_preview/containers/AntdPreview/Progress.tsx: -------------------------------------------------------------------------------- 1 | import { Progress } from 'antd'; 2 | 3 | ProgressDemo.title = 'Progress'; 4 | ProgressDemo.url = 'https://ant.design/components/progress/'; 5 | 6 | export default function ProgressDemo() { 7 | return ( 8 | <> 9 | 10 | 11 | 12 | 13 | 14 | 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /src/components/_preview/containers/AntdPreview/ProgressCircle.tsx: -------------------------------------------------------------------------------- 1 | import { Space, Progress } from 'antd'; 2 | 3 | ProgressCircle.title = 'ProgressCircle'; 4 | ProgressCircle.url = 'https://ant.design/components/progress/'; 5 | 6 | export default function ProgressCircle() { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import Document, { Html, Head, Main, NextScript } from 'next/document'; 2 | 3 | class MyDocument extends Document { 4 | render() { 5 | return ( 6 | 7 | 8 | 9 | 10 | 11 |