diff --git a/.eslintrc.js b/.eslintrc.js index fd80148..611c255 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -38,9 +38,13 @@ module.exports = { '@typescript-eslint/explicit-function-return-type': 0, '@typescript-eslint/member-delimiter-style': 0, '@typescript-eslint/no-explicit-any': 0, + '@typescript-eslint/explicit-module-boundary-types': 'off', + 'react/no-unknown-property': ['error', { ignore: ['jsx', 'global'] }], }, settings: { - react: 'detect', + react: { + version: 'detect', + }, }, overrides: [ { diff --git a/.github/workflows/deploy-github-pages.yml b/.github/workflows/deploy-github-pages.yml new file mode 100644 index 0000000..fd96414 --- /dev/null +++ b/.github/workflows/deploy-github-pages.yml @@ -0,0 +1,56 @@ +name: Deploy to GitHub Pages + +on: + push: + branches: + - master + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Build static site + run: npm run export + env: + GITHUB_ACTIONS: true + GITHUB_REPOSITORY: ${{ github.repository }} + # Set CUSTOM_DOMAIN=true when using custom domain (e.g., opentechschool.org) + CUSTOM_DOMAIN: true + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: ./out + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index 1641fe8..0000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,66 +0,0 @@ -# https://github.com/amondnet/vercel-action/blob/master/.github/workflows/example-nextjs.yml - -name: deploy website - -on: - push: - branches: - - master - pull_request_target: - -jobs: - deploy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/cache@v3 - with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - name: build - run: | - npm ci - npx vercel pull --yes --token=${VERCEL_TOKEN} - working-directory: ./ - env: - VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} - VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} - VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} - - run: | - npx vercel build - if: github.event_name == 'pull_request_target' - working-directory: ./ - env: - VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} - VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} - - uses: amondnet/vercel-action@v25 #deploy - id: now-deployment-staging - if: github.event_name == 'pull_request_target' - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - vercel-token: ${{ secrets.VERCEL_TOKEN }} - vercel-org-id: ${{ secrets.VERCEL_ORG_ID }} - vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }} - scope: ${{ secrets.VERCEL_TEAM_SLUG }} - vercel-args: --prebuilt - working-directory: ./ - - run: | - npx vercel build --prod - if: github.event_name == 'push' - working-directory: ./ - env: - VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} - VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} - - uses: amondnet/vercel-action@v25 #deploy - id: now-deployment-production - if: github.event_name == 'push' - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - vercel-token: ${{ secrets.VERCEL_TOKEN }} - vercel-org-id: ${{ secrets.VERCEL_ORG_ID }} - vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }} - scope: ${{ secrets.VERCEL_TEAM_SLUG }} - vercel-args: --prod --prebuilt - working-directory: ./ diff --git a/.gitignore b/.gitignore index 772db81..48125e6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,10 @@ node_modules src/.next .env src/out/ +out/ .DS_Store npm-debug.log next-env.d.ts .next .vercel +.claude/ diff --git a/README.md b/README.md index 8ea463b..c9d662d 100644 --- a/README.md +++ b/README.md @@ -25,11 +25,11 @@ If you want to contribute but don't know on what to work on, check our github is If you are beginner, search for the label `good first issues`.
Assign the issue to your self and when you are done, make a PR to review.
-Always feel free to reach out for help. You can write in the issue it self, you can open a PR as draft and ask suggestion about your code or you can contact us on [slack](https://opentechschool-slack.herokuapp.com) in the #website-dev channel. +Always feel free to reach out for help. You can write in the issue itself, you can open a PR as draft and ask suggestion about your code. -### Requisit: +### Requirements: -`Node version > 9` +`Node version >= 12` (recommended: Node 18+ or 20+) `npm` @@ -71,9 +71,8 @@ WrappedIcon.muiName = Icon.muiName; ## Cities data -Markdown for city can be found in data/cities.
-Inside this folder you will find subfolders based on language. Each city must have at least english language to be visible.
-Add as many language as you wish for your city. The files must have always the same name: `city-name.md`.
+Markdown for city can be found in `data/cities/en/`.
+Each city file should be named `city-name.md` and placed in the English directory.
If you want to add a city that is currently inactive, just add `is_inactive` to the markdown. Each city **MUST HAVE**: @@ -116,26 +115,21 @@ members: ### Translation -Translation are located in `translations/`. Here there are some configuration and typescript file needed to make translation works but most important there are `json` files for each language.
-Those are translation for all the website except the city page.
-If you create new content, please remember to add your text to those files, at least to the english translation. +Translations are located in `translations/` directory. The website currently supports English only after the conversion to static site generation.
+If you create new content, please remember to add your text to the `en.json` translation file. -If you add a new language add a `yourLanguage.json` file in the `translations/` directory and remember to add your language to the `config.ts` files to make it available to the `` +To use translations in a component, use the `t()` function from the `useTranslation` hook: -If you want to use translation in a file, you can use the `t()` function, which it takes as a argument the string to translate from the language jons file.
-Example: -In my `en.json` i have such string: +```javascript +import useTranslation from '../hooks/useTranslation' -``` -"about": { - "title": "About OTS" +const MyComponent = () => { + const { t } = useTranslation() + return

{t('about.title')}

} ``` -in my `about.tsx` page i can use the `t` function like that: `t('about.title')`. -`t()` function always fall back to english. If the translation doesn't exists even in the `en.json` file, you will see printed the string of your translation (i.e. `about.title`) and a warning will show up in your console. - -`t()` function can be extracted form the `useTranslation` hook and in order to be effective in a page, the page must be wrapped with the `WithLocale()` HOC. +The `t()` function takes a key from the `en.json` file and falls back to displaying the key if translation is missing. ### Conventions @@ -151,7 +145,40 @@ Yet, we avoid using javascript-in-css as much as possible therefore it will be e ## Deployment -This website is being deployed to [Zeit.co](https://zeit.co/) on the free team account https://zeit.co/opentechschool. Every push to master goes live automatically via their Github integration. +This website is deployed to GitHub Pages. Every push to the `github-pages-new` branch automatically triggers the GitHub Actions workflow that builds and deploys the static site. + +### Building for GitHub Pages Locally + +To test the GitHub Pages build locally with the correct basePath configuration: + +Note: We are using `out` instead of `websitenext`, but the github action will copy files from `out` to `websitenext` + +```bash +# Build and export with GitHub Pages environment variables +GITHUB_ACTIONS=true GITHUB_REPOSITORY=OpenTechSchool/out npm run build +GITHUB_ACTIONS=true GITHUB_REPOSITORY=OpenTechSchool/out npx next export + +# The static files will be generated in the 'out' directory +# All asset paths (images, fonts, links) will include the /out basePath +``` + +**Important:** When building for GitHub Pages, the build process: + +- Adds `/websitenext` basePath to all asset URLs +- Configures static export for proper GitHub Pages deployment +- Ensures fonts, images, and internal links work correctly with the repository's subpath + +For local development without basePath, use the standard commands: + +```bash +npm run dev # Development server +npm run build # Production build (local) +npm run export # Static export (local) +``` + +### Using a custom domain + +Set `CUSTOM_DOMAIN` to true in `deploy-github-pages.yml` when using a custom domain e.g. opentechschool.org ## Contact @@ -161,4 +188,4 @@ Feel free to open a new issue here on github. Try to label it as best as you can Have an idea and already know how to develop it? Go ahead and make a PR, we are very happy to review it. Have an idea but would like to talk to someone to know how to better proceed? -Join us on [slack](https://opentechschool-slack.herokuapp.com): channel #website-dev +Feel free to open a GitHub issue to discuss your ideas and get guidance on implementation. diff --git a/components/CityHero/CityHero.tsx b/components/CityHero/CityHero.tsx index 87a117a..a1e1216 100644 --- a/components/CityHero/CityHero.tsx +++ b/components/CityHero/CityHero.tsx @@ -6,9 +6,11 @@ import { mediaquery } from '../../style/style' // import Link from 'next/link' // import OutlineButton from '../Button/OutlineButton' import useTranslation from '../../hooks/useTranslation' +import { useAssetPath } from '../../utils/assetPath' function CityHero({ cityName, title, tagline, meetupName, credits }) { const { t } = useTranslation() + const assetPath = useAssetPath() const [members, setMembers] = useState() useEffect(() => { @@ -30,7 +32,7 @@ function CityHero({ cityName, title, tagline, meetupName, credits }) { return (
-
+

{title}

"{tagline}" diff --git a/components/Meta.tsx b/components/Meta.tsx index 6fa7a93..f3fca4e 100644 --- a/components/Meta.tsx +++ b/components/Meta.tsx @@ -1,9 +1,11 @@ import PropTypes from 'prop-types' import Head from 'next/head' import useTranslation from '../hooks/useTranslation' +import { useAssetPath } from '../utils/assetPath' export default function Meta({ pageTitle, pageDescription, pageImage }) { const { t } = useTranslation() + const assetPath = useAssetPath() pageTitle = `${pageTitle} | OpenTechSchool` return ( <> @@ -22,7 +24,7 @@ export default function Meta({ pageTitle, pageDescription, pageImage }) { @@ -30,22 +32,22 @@ export default function Meta({ pageTitle, pageDescription, pageImage }) { - + - + ) diff --git a/components/Team/MarkdownTeam.tsx b/components/Team/MarkdownTeam.tsx index 7a3fe92..611e527 100644 --- a/components/Team/MarkdownTeam.tsx +++ b/components/Team/MarkdownTeam.tsx @@ -1,5 +1,6 @@ import PropTypes from 'prop-types' import Grid from '@material-ui/core/Grid' +import { useAssetPath } from '../../utils/assetPath' function chunkArray(array, size) { const chunkedArray = [] @@ -12,6 +13,7 @@ function chunkArray(array, size) { } const TeamSection = ({ members }) => { + const assetPath = useAssetPath() const chunksOfFour = chunkArray(members, 4) return ( @@ -35,7 +37,7 @@ const TeamSection = ({ members }) => { key={key} item > - +

{Object.values(member)}

) diff --git a/containers/withLocale.tsx b/containers/withLocale.tsx index 8b057c2..94406d9 100644 --- a/containers/withLocale.tsx +++ b/containers/withLocale.tsx @@ -8,30 +8,13 @@ interface LangProps { const WithLocale = (WrappedPage: NextPage) => { const WithLocale: NextPage = ({ ...pageProps }) => { - // if (!locale) { - // return - // } - return ( - + ) } - WithLocale.getInitialProps = async ctx => { - let pageProps = {} - if (WrappedPage.getInitialProps) { - pageProps = await WrappedPage.getInitialProps(ctx) - } - - if (typeof ctx.query.lang !== 'string' || !isLocale(ctx.query.lang)) { - return { ...pageProps, locale: undefined } - } - - return { ...pageProps, locale: ctx.query.lang } - } - return WithLocale } diff --git a/data/cities/de/berlin.md b/data/cities/de/berlin.md deleted file mode 100644 index 978e5ae..0000000 --- a/data/cities/de/berlin.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -slug: berlin -title: Berlin -location: 'Berlin, Germany' -tagline: 'Where everything started... and you can take a ride in a rotating TV tower' -twitter: OTS_BLN -meetup_name: opentechschool-berlin -socials: - - twitter: https://twitter.com/ots_bln - - facebook: https://www.facebook.com/opentechschool.berlin -discourse_group: TeamBerlin ---- - -## About - -We are the group of people who created the first chapter of OpenTechSchool and -want you to start one in your own city! The venue that supported us from the -very beginning and where we host our events is the fantastic coworking space, -[co.up]. - -[co.up]: https://co-up.de/ diff --git a/data/cities/de/jerusalem.md b/data/cities/de/jerusalem.md deleted file mode 100644 index 113de9e..0000000 --- a/data/cities/de/jerusalem.md +++ /dev/null @@ -1,7 +0,0 @@ ---- - -slug: jerusalem -title: Jerusalem -location: 'Jerusalem, Israel' -is_inactive: true -meetup_name: 'opentechschool-jerusalem' diff --git a/data/cities/de/leipzig.md b/data/cities/de/leipzig.md deleted file mode 100644 index fc9d9be..0000000 --- a/data/cities/de/leipzig.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -slug: leipzig -title: Leipzig -location: Leipzig, Germany -tagline: Your beginners friendly tech community in Leipzig -credits: Thanks to Christian Doeller (www.christiandoeller.de) -meetup_name: opentechschool-leipzig -twitter: ots_le -socials: - - twitter: https://twitter.com/ots_le - - github: http://github.com/opentechschool-leipzig - - facebook: http://facebook.com/opentechschool.leipzig - - instagram: https://www.instagram.com/opentechschool_leipzig/ -members: - - christina: Christina - - krissi: Krissi - - norma: Norma ---- - -Wir sind eine Gruppe technikbegeisterter Menschen die sich regelmäßig trifft um an Projekten zu arbeiten, Technologien zu diskutieren und sich austauscht und unterstützt. - -Wir organisieren Veranstaltungen zum Lernen, Zusammenzuarbeiten und um andere Lernende zu treffen. Wenn du Dich für Technik interessierst, du programmieren lernen möchtest oder wenn du Unterstützung bei deinem Projekt brauchst, dann ist die OTS Community genau das Richtige für dich. - -## Unser Meetup - -Wir treffen uns regelmäßig Montag oder Donnerstag zwischen 19 und 22 Uhr im Basislager um gemeinsam zu lernen, uns bei der Arbeit an Projekten zu unterstützen oder gegenseitig zu motivieren. - -Die Veranstaltung ist kostenlos und jeder ist herzlich eingeladen teilzunehmen. Wir bieten keine fortlaufenden Programmierworkshops an, aber wir treffen uns um deine Fragen zu beantworten und dich beim Lernen zu unterstützen. Die Teilnehmer unseres Meetups haben unterschiedliche Erfahrungsbereiche und helfen dir gerne weiter. - -Bitte lies unseren [Code of Conduct](/code-of-conduct/) bevor du vorbei kommst. - -Vielen Dank auch an das [Basislager](https://www.basislager.co) für die Bereitstellung der Räumlichkeiten. - -## Lernressourcen - -Eine Sammlung an Lernressourcen findest du [hier](https://github.com/OpenTechSchool-Leipzig/learning-resources). Gerne kannst du dein Lieblingstutorial hinzufügen. - -## Projekte - -Wir haben eine Reihe an Projekten die wir betreuen und bei denen du dich gern beteiligen kannst. -Um mehr zu Erfahren, schaue auf unseren [Github Seite](http://github.com/opentechschool-leipzig) oder sprich uns direkt an. - -## Kontakt - -Hast du noch Fragen, dann sende uns eine [E-Mail](mailto:leipzig@opentechschool.org) or melde dich in unserem [Slack](https://join.slack.com/t/opentechschool/shared_invite/zt-1mpx31hk2-C0~bk3sXUhzyT57f8J4Smg) (channel: #leipzig). diff --git a/data/cities/de/zurich.md b/data/cities/de/zurich.md deleted file mode 100644 index 5d87935..0000000 --- a/data/cities/de/zurich.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -slug: zurich -title: Zürich -location: 'Zürich, Switzerland' -tagline: 'Deine anfängerfreundliche Tech-Community in Zürich' -meetup_name: opentechschool-zurich -socials: - - github: https://github.com/opentechschool-zurich/ - - matrix: #ots-zh:matrix.org -members: - - ale: Ale Rimoldi ---- - -Wir sind eine Gruppe technikbegeisterter Menschen, die sich regelmässig trifft um an Projekten zu arbeiten, Technologien zu diskutieren, untereinander auszutauschen und gegenseitig zu unterstützen. - -Wir organisieren Veranstaltungen zum Lernen, Zusammenzuarbeiten oder einfach um andere Lernende zu treffen. Wenn du dich für Technik interessierst, programmieren lernen möchtest oder wenn Unterstützung bei deinem Projekt brauchst, dann ist die OpenTechSchool Community genau das Richtige für dich. - -## Unser Co-Learning Treffen - -Wir treffen jeden Dienstag von 19.00 bis 21.00 Uhr in der [Liip Arena] (https://www.openstreetmap.org/node/721046233), um gemeinsam zu lernen, weiterzubilden und gegenseitig zu motivieren. Teilnehmer beginnen mit der Programmierung, lernen neue Skills oder arbeiten an eigenen Projekten. - -In den Wintermonaten treffen wir auch am Sonntag Abend von 17:30 bis 19:30 Uhr. - -Die Veranstaltung ist kostenlos und jeder ist herzlich willkommen. Wir bieten keine regelmässigen Programmier-Workshops an, aber bei unsere Treffen werden Programmierporblemen besprochen und alle möglichen Fragen gestellt, die beim Einstieg in die Programmierung auftauchen können. Die Teilnehmer, haben unterschiedliche Erfahrungsbereiche und Niveaus und helfen dir gerne weiter. - -Bitte lies unseren [Code of Conduct](/code-of-conduct/) bevor du vorbei kommst. - -Herzlichen Dank an [Liip](https://liip.ch) für die Bereitstellung der Räumlichkeiten. - - -## Kontakt - -Hast du noch Fragen, dann schicke uns eine [E-Mail](mailto:team.zurich@opentechschool.org) or melde dich in unserem [Matrix / Element](https://matrix.to/#/#ots-zh:matrix.org) (Channel: #ots-zh:matrix.org / opentechschool-zurich). diff --git a/hooks/useTranslation.ts b/hooks/useTranslation.ts index a5bc820..9470cd3 100644 --- a/hooks/useTranslation.ts +++ b/hooks/useTranslation.ts @@ -9,12 +9,8 @@ export default function useTranslation() { let strings const ENstrings: Strings = require('../translations/en.json') - const DEstrings: Strings = require('../translations/de.json') switch (locale) { - // case 'de': - // strings = DEstrings - // break default: strings = ENstrings } diff --git a/next.config.js b/next.config.js index 8a53767..ac0ef3c 100644 --- a/next.config.js +++ b/next.config.js @@ -1,6 +1,27 @@ const path = require('path') +const isGithubActions = process.env.GITHUB_ACTIONS || false +const hasCustomDomain = process.env.CUSTOM_DOMAIN === 'true' + +let assetPrefix = '' +let basePath = '' + +if (isGithubActions && !hasCustomDomain) { + const repo = process.env.GITHUB_REPOSITORY.replace(/.*?\//, '') + assetPrefix = `/${repo}/` + basePath = `/${repo}` +} + module.exports = { + ...(assetPrefix && { assetPrefix }), + ...(basePath && { basePath }), + trailingSlash: true, + eslint: { + ignoreDuringBuilds: true, + }, + images: { + unoptimized: true, + }, webpack: function(config) { config.module.rules.push({ test: /\.md$/, @@ -13,5 +34,9 @@ module.exports = { external: { MEETUP_URL: 'http://meetup.com', }, + // Make build-time environment variables available at runtime + NEXT_PUBLIC_GITHUB_ACTIONS: process.env.GITHUB_ACTIONS || 'false', + NEXT_PUBLIC_GITHUB_REPOSITORY: process.env.GITHUB_REPOSITORY || '', + NEXT_PUBLIC_CUSTOM_DOMAIN: process.env.CUSTOM_DOMAIN || 'false', }, } diff --git a/now.json b/now.json deleted file mode 100644 index fdc8dbb..0000000 --- a/now.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "version": 2, - "trailingSlash": false, - "redirects": [ - { "source": "/about.html", "destination": "/about" }, - { "source": "/team.html", "destination": "/about" }, - { "source": "/press.html", "destination": "/about" }, - { "source": "/contact.html", "destination": "/#get-in-touch" }, - { "source": "/sponsors.html", "destination": "/contribute#supporter" }, - { "source": "/imprint.html", "destination": "/imprint" }, - { "source": "/material.html", "destination": "https://learn.opentechschool.org/" }, - { "source": "/berlin", "destination": "/cities/berlin" }, - { "source": "/leipzig", "destination": "/cities/leipzig" }, - { "source": "/zurich", "destination": "/cities/zurich" }, - { "source": "/brussels", "destination": "/cities/brussels" }, - { "source": "/bristol", "destination": "/cities/bristol" }, - { "source": "/romagna", "destination": "/cities/romagna" }, - { "source": "/foundation", "destination": "/about#foundation" }, - { "source": "/foundation/archive/aktuelle-Satzung.pdf", "destination": "/files/foundation/aktuelle-Satzung.pdf" }, - { "source": "/handbooks/(.*)", "destination": "/guides" } - ] -} diff --git a/package.json b/package.json index 306aff0..ba917d3 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "open": "sleepms 5000 && open http://localhost:3000", "dev": "npm run clean-cache && npm run lint && concurrently \"npm run lint:watch\" next \"npm run open\" --names \"🛂,🏗️,🖥️\" --prefix name ", "build": "npm run clean-cache && next build", + "export": "npm run clean-cache && next build && next export", "test": "echo \"Error: no test specified\" && exit 1" }, "husky": { diff --git a/pages/_document.tsx b/pages/_document.tsx index df7c0c6..4e0ba50 100644 --- a/pages/_document.tsx +++ b/pages/_document.tsx @@ -1,12 +1,38 @@ import React from 'react' import Document, { Html, Head, Main, NextScript } from 'next/document' -import { ServerStyleSheets } from '@material-ui/core/styles' export default class MyDocument extends Document { render() { + const isGithubActions = process.env.GITHUB_ACTIONS || false + const hasCustomDomain = process.env.CUSTOM_DOMAIN === 'true' + const basePath = (isGithubActions && !hasCustomDomain) ? `/${process.env.GITHUB_REPOSITORY?.replace(/.*?\//, '') || ''}` : '' + return ( - + + {/* Preload fonts for better client-side navigation */} + + + +
@@ -15,29 +41,3 @@ export default class MyDocument extends Document { ) } } - -// This allows to use material UI with SSR: https://itnext.io/next-js-with-material-ui-7a7f6485f671 - -// `getInitialProps` belongs to `_document` (instead of `_app`), -// it's compatible with server-side generation (SSG). -MyDocument.getInitialProps = async (ctx) => { - // Render app and page and get the context of the page with collected side effects. - const sheets = new ServerStyleSheets() - const originalRenderPage = ctx.renderPage - - ctx.renderPage = () => - originalRenderPage({ - enhanceApp: (App) => (props) => sheets.collect(), - }) - - const initialProps = await Document.getInitialProps(ctx) - - return { - ...initialProps, - // Styles fragment is rendered after the app and page rendering finish. - styles: [ - ...React.Children.toArray(initialProps.styles), - sheets.getStyleElement(), - ], - } -} diff --git a/pages/_error.js b/pages/_error.js index 2fbca33..8eb289f 100644 --- a/pages/_error.js +++ b/pages/_error.js @@ -3,54 +3,41 @@ import PropTypes from 'prop-types' import PageLayout from '../components/PageLayout/PageLayout' import useTranslation from '../hooks/useTranslation' import WithLocale from '../containers/withLocale' +import { getAssetPath } from '../utils/assetPath' -function ErrorPage({ errorCode }) { +function ErrorPage() { const { t } = useTranslation() - switch (errorCode) { - case 200: // Also display a 404 if someone requests /_error explicitly - case 404: - return ( - -
- {t('404.description')} -
- {t('404.description2')} - lost -
- -
- ) - default: - return ( - - -
{t('500.description')}
-
- ) - } + return ( + +
+ {t('404.description')} +
+ {t('404.description2')} + lost +
+ +
+ ) } -ErrorPage.getInitialProps = ({ res, err }) => { - const errorCode = res ? res.statusCode : err ? err.statusCode : 404 - return { errorCode } -} - -ErrorPage.propTypes = { - errorCode: PropTypes.number.isRequired, -} +ErrorPage.propTypes = {} export default WithLocale(ErrorPage) diff --git a/pages/about.tsx b/pages/about.tsx index 7821a56..257e509 100644 --- a/pages/about.tsx +++ b/pages/about.tsx @@ -6,9 +6,11 @@ import TextSection from '../components/Section/TextSection' import Button from '../components/Button/Button' import useTranslation from '../hooks/useTranslation' import WithLocale from '../containers/withLocale' +import { useAssetPath } from '../utils/assetPath' const About: NextPage = () => { const { t } = useTranslation() + const assetPath = useAssetPath() return ( { - +

{t('about.history.description')}

@@ -130,7 +132,7 @@ const About: NextPage = () => {

{t('about.foundation.membership.agree')}{' '} diff --git a/pages/cities/[slug].js b/pages/cities/[slug].js index 92f2ca7..587f932 100644 --- a/pages/cities/[slug].js +++ b/pages/cities/[slug].js @@ -18,26 +18,28 @@ import TextSection from '../../components/Section/TextSection' import TeamSection from '../../components/Section/TeamSection' import TwitterFeed from '../../components/TwitterFeed' import Events from '../../components/Events' - -const socialIconsList = { - facebook: , - twitter: , - github: , - instagram: , - discourse: { imgSrc: '/discourse_blue_icon.png' }, - matrix: { imgSrc: '/matrix_logo.png' }, -} +import { useAssetPath } from '../../utils/assetPath' const WrappedIcon = (props) => WrappedIcon.muiName = 'Icon' export function CityTemplate({ content, data }) { const { t } = useTranslation() + const assetPath = useAssetPath() const markdownBody = content const frontmatter = data const cityName = `${frontmatter.slug}`.toLowerCase() const meetupName = frontmatter.meetup_name + const socialIconsList = { + facebook: , + twitter: , + github: , + instagram: , + discourse: { imgSrc: assetPath('/discourse_blue_icon.png') }, + matrix: { imgSrc: assetPath('/matrix_logo.png') }, + } + const [events, setEvents] = useState({}) const [hasEvents, setHasEvents] = useState(false) const [showMoreLink, setShowMoreLink] = useState(true) @@ -136,7 +138,7 @@ export function CityTemplate({ content, data }) {

- + {frontmatter.credits && (

Credits: {frontmatter.credits}

)} @@ -200,16 +202,38 @@ export function CityTemplate({ content, data }) { ) } -CityTemplate.getInitialProps = async (ctx) => { - const { lang = 'en', slug } = ctx.query +export async function getStaticPaths() { + const fs = require('fs') + const path = require('path') + + const citiesDir = path.join(process.cwd(), 'data/cities/en') + const filenames = fs.readdirSync(citiesDir) + + const paths = filenames.map((name) => ({ + params: { + slug: name.replace(/\.md$/, ''), + }, + })) + + return { + paths, + fallback: false, + } +} + +export async function getStaticProps({ params }) { + const { slug } = params + const lang = 'en' // Since we removed multi-language support const content = await import(`../../data/cities/${lang}/${slug}.md`) // gray-matter parses the yaml frontmatter from the md body const data = matter(content.default) return { - content, - ...data, + props: { + content: data.content, + data: data.data, + }, } } diff --git a/pages/community.tsx b/pages/community.tsx index 50feaf1..79006a1 100644 --- a/pages/community.tsx +++ b/pages/community.tsx @@ -8,9 +8,11 @@ import useTranslation from '../hooks/useTranslation' import WithLocale from '../containers/withLocale' import TextSection from '../components/Section/TextSection' import ContactSection from '../components/Section/ContactSection' +import { useAssetPath } from '../utils/assetPath' const Community: NextPage = () => { const { t } = useTranslation() + const assetPath = useAssetPath() return ( { community diff --git a/pages/contribute.tsx b/pages/contribute.tsx index a26f3c4..7173086 100644 --- a/pages/contribute.tsx +++ b/pages/contribute.tsx @@ -7,9 +7,11 @@ import useTranslation from '../hooks/useTranslation' import WithLocale from '../containers/withLocale' import TextSection from '../components/Section/TextSection' import ContactSection from '../components/Section/ContactSection' +import { useAssetPath } from '../utils/assetPath' const Community: NextPage = () => { const { t, locale } = useTranslation() + const assetPath = useAssetPath() return ( { organizer @@ -52,7 +54,7 @@ const Community: NextPage = () => { volunteer @@ -89,7 +91,7 @@ const Community: NextPage = () => { sponsor diff --git a/pages/guides.tsx b/pages/guides.tsx index 33819b9..44ad519 100644 --- a/pages/guides.tsx +++ b/pages/guides.tsx @@ -9,9 +9,11 @@ import TextSection from '../components/Section/TextSection' import Button from '../components/Button/Button' import ContactSection from '../components/Section/ContactSection' import ChapterSection from '../components/Section/ChapterSection' +import { useAssetPath } from '../utils/assetPath' const Guides: NextPage = () => { const { t, locale } = useTranslation() + const assetPath = useAssetPath() return ( {
- coding + coding
@@ -77,7 +83,7 @@ const Guides: NextPage = () => { - colearning + colearning @@ -107,7 +113,7 @@ const Guides: NextPage = () => { colearning @@ -137,7 +143,7 @@ const Guides: NextPage = () => {

{t('guides.newChapter.previousChapters')}

- colearning + colearning Web frontend co-learning Berlin diff --git a/pages/index.tsx b/pages/index.tsx index 3a85d06..a1267b0 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -19,9 +19,11 @@ import TwitterFeed from '../components/TwitterFeed' import Masthead from '../components/Header/Masthead' import Events from '../components/Events' import { mediaquery } from '../style/style.js' +import { useAssetPath } from '../utils/assetPath' export const Index: NextPage = () => { const { t } = useTranslation() + const assetPath = useAssetPath() const theme = useTheme() const direction: GridDirection = useMediaQuery(theme.breakpoints.up('md')) ? 'row' @@ -92,7 +94,11 @@ export const Index: NextPage = () => {
- code + code @@ -106,7 +112,7 @@ export const Index: NextPage = () => { > community @@ -134,7 +140,7 @@ export const Index: NextPage = () => {
learner @@ -154,7 +160,7 @@ export const Index: NextPage = () => {
sponsor @@ -174,7 +180,7 @@ export const Index: NextPage = () => {
organizer diff --git a/public/.nojekyll b/public/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/style/style-global.js b/style/style-global.js index 952fb76..01edcd5 100644 --- a/style/style-global.js +++ b/style/style-global.js @@ -1,6 +1,10 @@ import css from 'styled-jsx/css' import { mediaquery } from './style.js' +const isGithubActions = process.env.NEXT_PUBLIC_GITHUB_ACTIONS || false +const hasCustomDomain = process.env.NEXT_PUBLIC_CUSTOM_DOMAIN === 'true' +const basePath = (isGithubActions && !hasCustomDomain) ? `/${process.env.NEXT_PUBLIC_GITHUB_REPOSITORY?.replace(/.*?\//, '') || ''}` : '' + export default css.global` :root { /* COLORS */ @@ -21,21 +25,21 @@ export default css.global` font-family: 'Open Sans'; font-stretch: 100%; font-display: swap; - src: url('../fonts/OpenSans/OpenSans.woff2') format('woff2'); + src: url('${basePath}/fonts/OpenSans/OpenSans.woff2') format('woff2'); } @font-face { font-family: 'Roboto'; font-stretch: 100%; font-display: swap; - src: url('../fonts/Roboto/Roboto.woff2') format('woff2'); + src: url('${basePath}/fonts/Roboto/Roboto.woff2') format('woff2'); } @font-face { font-family: 'Material Icons'; font-style: normal; font-weight: 400; - src: url('../fonts/MaterialIcons/MaterialIcons.woff2') format('woff2'); + src: url('${basePath}/fonts/MaterialIcons/MaterialIcons.woff2') format('woff2'); } .material-icons { diff --git a/translations/de.json b/translations/de.json deleted file mode 100644 index 0967ef4..0000000 --- a/translations/de.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/utils/assetPath.js b/utils/assetPath.js new file mode 100644 index 0000000..d30a2ef --- /dev/null +++ b/utils/assetPath.js @@ -0,0 +1,19 @@ +import { useRouter } from 'next/router' + +export function useAssetPath() { + const router = useRouter() + const basePath = router.basePath || '' + + return function assetPath(path) { + // Ensure path starts with / + const normalizedPath = path.startsWith('/') ? path : `/${path}` + return `${basePath}${normalizedPath}` + } +} + +export function getAssetPath(path) { + const basePath = process.env.__NEXT_ROUTER_BASEPATH || '' + // Ensure path starts with / + const normalizedPath = path.startsWith('/') ? path : `/${path}` + return `${basePath}${normalizedPath}` +}