Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
name: End-to-end Tests
on:
push:
branches: [main, develop]
branches: [main, develop, prod]
pull_request:
branches: [main, develop]
branches: [main, develop, prod]
jobs:
e2e:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6
- name: Prepare .env file
run: |
rm -f .env && touch .env
echo "NEXT_PUBLIC_FORMSPREE_ID=fake123" >> .env
echo "NEXT_PUBLIC_RECAPTCHA_SITE_KEY=123fAkE" >> .env
- uses: actions/setup-node@v3
- uses: actions/setup-node@v6
with:
node-version: '18.x'
node-version: '24.x'
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: npm run test
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v5
if: always()
with:
name: playwright-report
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
name: Lint, Format and Build
on:
push:
branches: [main, develop]
branches: [main, develop, prod]
pull_request:
branches: [main, develop]
branches: [main, develop, prod]
jobs:
validate:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: '14.x'
node-version: '24.x'
- name: Install dependencies
run: npm ci
- name: Run code validation (includes linting, prettier and building)
Expand Down
1 change: 0 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ Please note we have a [code of conduct](https://github.com/reactdeveloperske/rea
If you're ready to contribute and create your PR, it will help to set up a local environment so you can see your changes.

1. Set up your development environment

- install your favorite text editor/IDE
- install [Nodejs](nodejs.org)

Expand Down
36 changes: 36 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@

# minimal alpine image for quick dev build
# FROM mhart/alpine-node


FROM node:alpine
WORKDIR /app
COPY . .
RUN yarn install
RUN yarn build
EXPOSE 3000
CMD ["yarn", "start"]



#For production environment
# FROM node:alpine as BUILD_IMAGE
# WORKDIR /app
# COPY package.json yarn.lock ./
# # install dependencies
# RUN yarn install --frozen-lockfile
# COPY . .
# # build
# RUN yarn build
# # remove dev dependencies
# RUN npm prune --production

# FROM node:alpine
# WORKDIR /app
# # copy from build image
# COPY --from=BUILD_IMAGE /app/package.json ./package.json
# COPY --from=BUILD_IMAGE /app/node_modules ./node_modules
# COPY --from=BUILD_IMAGE /app/.next ./.next
# COPY --from=BUILD_IMAGE /app/public ./public
# EXPOSE 3000
# CMD ["yarn", "start"]
137 changes: 127 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,137 @@
<h1 align="center" style="margin-top: 1em; margin-bottom: 3em;">
<p><a href="https://reactdevske.netlify.app/"><img alt="logo" src="./public/reactdevske.svg" alt="reactdevske" width="125"></a></p>
<p> <img src="https://media.giphy.com/media/hvRJCLFzcasrR4ia7z/giphy.gif" alt="Waving Hand" width="25px" height="25px"> Welcome to Reactjs Developer Community Kenya Website!</p>
<p><a href="https://reactdevske.netlify.app/"><img alt="logo" src="./public/reactdevske.svg" width="125"></a></p>
<p> <img src="https://media.giphy.com/media/hvRJCLFzcasrR4ia7z/giphy.gif" alt="Waving Hand" width="25px" height="25px"> React Developers Community — Kenya</p>
</h1>

This is the repo for the showcase website of the React Developer Community in Kenya
This repository contains the source for the community showcase website maintained by the React Developers Community (Kenya). The site is built with Next.js, TypeScript and Tailwind CSS, includes end-to-end tests with Playwright, and is container-ready using Docker.

Check out the live version [HERE](https://reactdevske.vercel.app/)
Live production: https://www.reactdevske.org/

## Contributing to the project
**Table of contents**
- Overview
- Features
- Tech stack
- Quickstart
- Docker
- Testing
- Project structure
- Contributing
- License & contact

Contributions are always welcome!
**Overview**

See [`contributing.md`](https://github.com/reactdeveloperske/reactdevske-website/blob/main/CONTRIBUTING.md) for ways to get started.
This site showcases the community, upcoming events, contact information and resources for React developers in Kenya. It's intended as a community-maintained, easy-to-contribute codebase for public-facing content and event announcements.

Please adhere to this project's [`code of conduct`](https://github.com/reactdeveloperske/reactdevske-website/blob/main/CODE_OF_CONDUCT.md).
**Features**
- Responsive, accessible UI built with Next.js and Tailwind CSS.
- Pages for home, about, contact, events, news, forum and members.
- Reusable component library under `src/components`.
- Playwright end-to-end tests (see `e2e/`).
- Docker support for production-like local testing.

## Figma design file
**Tech stack**
- Next.js (pages-based) + React
- TypeScript
- Tailwind CSS
- Playwright for E2E testing
- Prettier, ESLint, and TypeScript for quality checks

Checkout the design file [`HERE`](https://www.figma.com/file/TVwnaDhBGeVdnVKdf6H91C/React-developers-community-website?node-id=741%3A976), feel free to use it to guide your contribution to our site.
**Quickstart (local development)**

Prerequisites:
- Node.js 16+ (or the version compatible with the `next` dependency)
- npm or yarn

Install dependencies:

```bash
npm install
# or
yarn install
```

Run the development server:

```bash
npm run dev
# opens at http://localhost:3000
```

Build for production:

```bash
npm run build
npm run start
```

Useful scripts (from `package.json`):
- `npm run dev` — starts Next.js in development mode
- `npm run build` — produces a production build
- `npm run start` — runs the production build
- `npm run lint` — runs ESLint
- `npm run test` — runs Playwright tests

**Docker**

This repository contains a `Dockerfile` and `docker-compose.yml` for running the app in a container.

Build & run with Docker Compose:

```bash
docker-compose up --build
```

The app will be available on the port configured in `docker-compose.yml` (default: 3000).

**Testing (Playwright)**

End-to-end tests are in the `e2e/` folder and are run using Playwright. To run tests locally:

```bash
npm run test
```

Playwright config is at `playwright.config.ts`.

**Project structure (important files & folders)**

- `public/` — static assets (images, manifest)
- `src/pages/` — Next.js pages (routes)
- `src/components/` — shared React components (Navbar, HeroHeader, Events, ContactUs, etc.)
- `src/styles/` — global and module CSS (Tailwind entry)
- `e2e/` — Playwright end-to-end tests
- `Dockerfile`, `docker-compose.yml` — container configuration
- `package.json`, `tsconfig.json`, `next.config.js` — build & tooling

If you want to explore components, start with:
- `src/components/HeroHeader` — site hero
- `src/components/Navbar` — navigation and menu
- `src/components/Events` — events listing and display
- `src/components/ContactUs` — contact form and footer

**Contributing**

Contributions are welcome. Please follow the contribution guidelines and community standards:

- Contribution guide: [CONTRIBUTING.md](CONTRIBUTING.md)
- Code of conduct: [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)

Suggested workflow:
1. Fork the repo and create a feature branch.
2. Run the dev server and make changes.
3. Ensure TypeScript and lint checks pass: `npm run typecheck` and `npm run lint`.
4. Add/update tests if applicable.
5. Open a pull request with a clear description of your changes.

**Maintainers & contact**
If you need help or want to propose changes not suitable for a PR, open an issue or reach out via the community channels listed in the repo.

**License**
This project is open source — see the `LICENSE` file for details.

**Design resources**
Figma design file used for the website is available here:
https://www.figma.com/file/TVwnaDhBGeVdnVKdf6H91C/React-developers-community-website

---
_Last updated: 2026-02-15_
23 changes: 23 additions & 0 deletions components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "src/styles/globals.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"iconLibrary": "lucide",
"rtl": false,
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"registries": {}
}
13 changes: 13 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version: '3.8'
services:
web:
build:
context: ./

volumes:
- .:/app
command: npm run dev
ports:
- "3000:3000"
environment:
NODE_ENV: development
2 changes: 1 addition & 1 deletion e2e/events.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ test.describe('Test if see more link is clickable', () => {
const [newPage] = await Promise.all([
context.waitForEvent('page'),
page.waitForLoadState(),
page.getByRole('link', { name: 'See More' }).click(),
page.getByRole('link', { name: 'See More Events' }).click(),
]);
await expect(newPage).toHaveURL(
'https://kommunity.com/reactjs-developer-community-kenya-reactdevske/events'
Expand Down
20 changes: 8 additions & 12 deletions e2e/hero-header.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { test, expect } from '@playwright/test';
import { expect, test } from '@playwright/test';

test.beforeEach(async ({ page }) => {
page.goto('http://localhost:3000');
Expand All @@ -13,7 +13,7 @@ test.describe('Test Hero Header Navigation Links', () => {
});

test('Events link should navigate to Events section', async ({ page }) => {
await page.getByRole('link', { name: 'Events' }).click();
await page.getByRole('link', { name: 'Events', exact: true }).click();
await expect(page).toHaveURL('/#events');
});

Expand All @@ -33,11 +33,9 @@ test.describe('Test Hero Header Navigation Links', () => {
page.waitForLoadState(),
page.getByRole('link', { name: 'Join Community' }).click(),
]);
await expect(newPage).toHaveURL(
new RegExp(
'^https://docs.google.com/forms/d/e/1FAIpQLSc_k5sffFTeL9oDug41nXU4Spw5cV84ExaL3jNFu_I1FTZO1w/viewform'
)
);
await newPage.waitForLoadState('load');
// Accept either the shortlink (bit.ly) or the final Google Forms URL
expect(newPage.url()).toMatch(/^(https:\/\/)?(bit\.ly|docs\.google\.com)/);
});

test('Join ReactDevsKe link should open google form in new tab', async ({
Expand All @@ -49,10 +47,8 @@ test.describe('Test Hero Header Navigation Links', () => {
page.waitForLoadState(),
page.getByRole('link', { name: 'Join ReactDevsKe' }).click(),
]);
await expect(newPage).toHaveURL(
new RegExp(
'^https://docs.google.com/forms/d/e/1FAIpQLSc_k5sffFTeL9oDug41nXU4Spw5cV84ExaL3jNFu_I1FTZO1w/viewform'
)
);
await newPage.waitForLoadState('load');
// Accept either the shortlink (bit.ly) or the final Google Forms URL
expect(newPage.url()).toMatch(/^(https:\/\/)?(bit\.ly|docs\.google\.com)/);
});
});
16 changes: 16 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import nextVitals from 'eslint-config-next/core-web-vitals';
import { defineConfig, globalIgnores } from 'eslint/config';

const eslintConfig = defineConfig([
...nextVitals,
// Override default ignores of eslint-config-next.
globalIgnores([
// Default ignores of eslint-config-next:
'.next/**',
'out/**',
'build/**',
'next-env.d.ts',
]),
]);

export default eslintConfig;
3 changes: 2 additions & 1 deletion next-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import './.next/dev/types/routes.d.ts';

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information.
16 changes: 12 additions & 4 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@
const nextConfig = {
reactStrictMode: true,
pageExtensions: ['page.tsx', 'api.ts'],
eslint: {
dirs: ['src', 'e2e'],
},
images: {
domains: ['bit.ly', 'res.cloudinary.com'],
remotePatterns: [
{
protocol: 'https',
hostname: 'bit.ly',
pathname: '/:path*',
},
{
protocol: 'https',
hostname: 'res.cloudinary.com',
pathname: '/:path*',
},
],
},
};

Expand Down
Loading