diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index e1e62b8..0000000 --- a/.editorconfig +++ /dev/null @@ -1,13 +0,0 @@ -# http://editorconfig.org -root = true - -[*] -indent_style = space -indent_size = 2 -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true - -[*.md] -trim_trailing_whitespace = false - diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index c585e19..0000000 --- a/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -out \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 3725308..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,37 +0,0 @@ -module.exports = { - extends: [ - "plugin:@typescript-eslint/recommended", - "plugin:react-hooks/recommended", - "plugin:react/recommended", - "plugin:jsx-a11y/recommended", - "plugin:@next/next/recommended", - "prettier", - ], - settings: { - react: { - version: "detect", - }, - }, - env: { - browser: true, - node: true, - }, - parser: "@typescript-eslint/parser", - parserOptions: { - ecmaVersion: 2020, - sourceType: "module", - ecmaFeatures: { - jsx: true, - }, - }, - rules: { - "@typescript-eslint/ban-types": "warn", - "no-use-before-define": 0, - "padded-blocks": 0, - "react/jsx-no-target-blank": 0, - "react/jsx-uses-react": 2, - "react/jsx-uses-vars": 2, - "react/prop-types": 0, - "react/react-in-jsx-scope": 2, - }, -}; diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..bffb357 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "next/core-web-vitals" +} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 97a3608..0000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: Scheduled build -on: - schedule: - - cron: "0 0 * * *" -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Trigger our build webhook on Netlify - run: curl -s -X POST "https://api.netlify.com/build_hooks/${TOKEN}" - env: - TOKEN: ${{ secrets.NETLIFY_CRON_BUILD_HOOK }} diff --git a/.gitignore b/.gitignore index e23ed7b..fd3dbb5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,36 @@ -*.log +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc .DS_Store -.history -.next -node_modules -out -package-lock.json \ No newline at end of file +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/.nvmrc b/.nvmrc index b6a7d89..209e3ef 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -16 +20 diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 2b3533c..0000000 --- a/.prettierignore +++ /dev/null @@ -1,2 +0,0 @@ -.next -out diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..d98169b --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + "printWidth": 120, + "singleQuote": true, + "trailingComma": "es5", + "tabWidth": 2, + "useTabs": false, + "plugins": ["prettier-plugin-tailwindcss"] +} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index be473d4..0000000 --- a/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -script: yarn build -language: node_js -node_js: - - "12.18" -install: - - yarn -test: - - yarn lint - - yarn build -deploy: - local_dir: out - provider: pages - fqdn: koodiklinikka.fi - skip_cleanup: true - github_token: "$GITHUB_TOKEN" - repo: koodiklinikka/koodiklinikka.github.io - target_branch: master - on: - branch: master diff --git a/LICENSE.md b/LICENSE.md index 3a8ee75..d713c8f 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 Riku Rouvila +Copyright (c) 2024 Petri Partio Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index ddf37f4..c403366 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,36 @@ -# Koodiklinikka +This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). -![Travis](https://travis-ci.org/koodiklinikka/koodiklinikka.fi.svg?branch=master) +## Getting Started -Koodiklinikka-logo +First, run the development server: -**Koodiklinikka.fi lähdekoodi**. [Issueita](https://github.com/koodiklinikka/koodiklinikka.fi/issues) ja [Pull Requestejä](https://github.com/koodiklinikka/koodiklinikka.fi/pulls) otetaan lämpimästi vastaan. Yritämme pitää kynnyksen kontribuoida projektiin alhaisena, jotta mahdollisimman moni pääsisi jättämään siihen jälkensä. Kaikki koodi katselmoidaan läpi ja mergetään projektiin kun näyttää hyvälle. Muutamasta mergetystä Pull Requestista oikeudet ylläpitää projektia. - -[Issueita](https://github.com/koodiklinikka/koodiklinikka.fi/issues) voidaan käyttää myös sivun: - -- toiminnallisuuteen -- designiin -- [HTTP-rajapintaan](https://github.com/koodiklinikka/koodiklinikka.fi-api) -- projektin hallintaan liittyviin asioihin -- tai koko Koodiklinikkaan yleisesti. - ---- - -## Projektin asennus - -### Vaaditut työkalut - -- Asenna [Node.js](http://nodejs.org) -- Asenna [Yarn 1.x](https://classic.yarnpkg.com/en/) -- Asenna [Git](https://git-scm.com/) client lähdekoodin hallintaan - -### Kloonaa projekti koneellesi - -```sh -git clone https://github.com/koodiklinikka/koodiklinikka.fi.git +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev ``` -### Käynnistä kehitystila +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. -```sh -cd koodiklinikka.fi -yarn -yarn start -``` +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. -### Avaa esikatselu selaimessa +This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. -Avaa selaimessasi: [`http://localhost:3000`](http://localhost:3000) +## Learn More -## Komennot +To learn more about Next.js, take a look at the following resources: -### `yarn` +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. -Asentaa projektin riippuvuudet +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! -### `yarn start` +## Deploy on Vercel -Kääntää lähdetiedostot ja palvelee sovellusta porttiin `3000` +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. -### `yarn build` - -Kääntää lähdetiedostot -> `out/` -hakemistoon +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/TODO.md b/TODO.md deleted file mode 100644 index b1c77d2..0000000 --- a/TODO.md +++ /dev/null @@ -1,6 +0,0 @@ -- Stripe - - Test ID `pk_test_OmNve9H1OuORlmD4rblpjgzh` - - Prod ID `pk_live_xrnwdLNXbt20LMxpIDffJnnC` -- API integration (test backend `https://lit-plateau-4689.herokuapp.com/`) -- Hero video -- Deployment diff --git a/app/globals.css b/app/globals.css new file mode 100644 index 0000000..d805cbf --- /dev/null +++ b/app/globals.css @@ -0,0 +1,99 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer utilities { + .text-balance { + text-wrap: balance; + } + + .text-shadow { + text-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + } +} + +.title-highlight { + background: linear-gradient(200deg, #ff0098 20%, #0ef 80%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + filter: drop-shadow(0 0 20px rgba(255, 0, 234, 0.2)); +} + +@supports (color: color(display-p3 1 1 1)) { + .title-highlight { + background: linear-gradient(200deg, oklch(68% 0.5 340) 20%, oklch(90% 0.5 200) 100%); + + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + filter: drop-shadow(0 0 20px oklch(80% 0.41 211 / 20%)); + } +} + +.bg-button { + background: linear-gradient(200deg, #f0f 20%, #ff00c4 100%); +} + +@supports (color: color(display-p3 1 1 1)) { + .bg-button { + background: linear-gradient(200deg, oklch(100% 0.5 340) 20%, oklch(86% 0.5 360) 100%); + } +} + +html { + background: #070b1e url('../public/background.webp'); + background-size: 1024px auto; + background-position: top center; + background-repeat: no-repeat; + scroll-behavior: smooth; +} + +@media (min-width: 1024px) { + html { + background-size: 100% auto; + } +} + +h1, +h2, +h3 { + text-wrap: balance; +} + +.checkbox svg { + display: none; +} + +input[type='checkbox']:checked + .checkbox { + background-color: #ef008e; + border-color: #ff0099; +} + +input[type='checkbox']:checked + .checkbox svg { + display: block; + align-items: center; + justify-items: center; + width: 80%; + height: auto; +} + +input[type='checkbox']:focus + .checkbox { + outline: 2px solid var(--tw-color-red-800); + outline-offset: 2px; +} + +@keyframes fadeInOut { + 0% { + opacity: 20%; + } + 50% { + opacity: 100%; + } + 100% { + opacity: 20%; + } +} + +.fade-in-out { + opacity: 20%; + animation: fadeInOut 4s ease-in-out infinite; +} diff --git a/app/icon.png b/app/icon.png new file mode 100644 index 0000000..c664406 Binary files /dev/null and b/app/icon.png differ diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 0000000..31b6bca --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,27 @@ +import type { Metadata } from 'next'; +import { Inter } from 'next/font/google'; +import './globals.css'; +import BottomFade from '@/components/BottomFade'; + +const inter = Inter({ subsets: ['latin'] }); + +export const metadata: Metadata = { + title: 'Koodiklinikka', + description: 'Yhteisö kaikille ohjelmoinnista ja ohjelmistoalasta kiinnostuneille harrastajille ja ammattilaisille', + robots: 'noindex', +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + {children} + + + + ); +} diff --git a/app/opengraph-image.alt.txt b/app/opengraph-image.alt.txt new file mode 100644 index 0000000..37f6a87 --- /dev/null +++ b/app/opengraph-image.alt.txt @@ -0,0 +1 @@ +Koodiklinikka on Suomen suurin ohjelmistoalan yhteisö, joka tuo alan ammattilaiset ja harrastajat yhteen diff --git a/app/opengraph-image.png b/app/opengraph-image.png new file mode 100644 index 0000000..297ef3f Binary files /dev/null and b/app/opengraph-image.png differ diff --git a/app/page.tsx b/app/page.tsx new file mode 100644 index 0000000..57b2f91 --- /dev/null +++ b/app/page.tsx @@ -0,0 +1,105 @@ +import shuffle from 'lodash.shuffle'; + +import ChannelGrid from '@/components/ChannelGrid'; +import FeatureImage from '@/components/FeatureImage'; +import Footer from '@/components/Footer'; +import Hero from '@/components/Hero'; +import Nav from '@/components/Nav'; +import Wrapper from '@/components/Wrapper'; + +async function getChannels() { + const res = await fetch('https://stats.koodiklinikka.fi/api/channels', { next: { revalidate: 3600 } }); + + if (!res.ok) { + // This will activate the closest `error.js` Error Boundary + throw new Error('Failed to fetch data'); + } + + return res.json(); +} + +export default async function Home() { + let channels: Channel[] = await getChannels(); + channels = channels.sort((a, b) => (a.messages_today > b.messages_today ? -1 : 1)); + + return ( + <> +