| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| # Apache HBase Website |
| |
| The official website for Apache HBase, built with modern web technologies to provide a fast, accessible, and maintainable web presence. |
| |
| --- |
| |
| ## Table of Contents |
| |
| - [Content Editing](#content-editing) |
| - [Development](#development) |
| - [Prerequisites](#prerequisites) |
| - [Technology Stack](#technology-stack) |
| - [Project Architecture](#project-architecture) |
| - [Getting Started](#getting-started) |
| - [Development Workflow](#development-workflow) |
| - [Building for Production](#building-for-production) |
| - [Maven Integration](#maven-integration) |
| - [Deployment](#deployment) |
| - [Troubleshooting](#troubleshooting) |
| |
| --- |
| |
| ## Content Editing |
| |
| Most pages (except the home page) store content in **Markdown (`.md`)** or **JSON (`.json`)** files located in `app/pages/[page-name]/`. This makes it easy to update content without touching code. |
| |
| **Examples:** |
| - `app/pages/team/content.md` - Markdown content for team page |
| - `app/pages/powered-by-hbase/companies.json` - JSON data for companies |
| - `app/pages/news/events.json` - JSON data for news/events |
| |
| Edit these files with any text editor, then run `npm run build` to regenerate the site. |
| |
| --- |
| |
| ## Development |
| |
| ### Prerequisites |
| |
| Before you begin, ensure you have the following installed: |
| |
| - **Node.js version 22** - JavaScript runtime (like the JVM for Java) |
| - Download from [nodejs.org](https://nodejs.org/) |
| - Verify installation: `node --version` (should show v20.19+ or v22.12+) |
| |
| - **NPM** - Node Package Manager (like Maven for Java) |
| - Comes bundled with Node.js |
| - Verify installation: `npm --version` |
| |
| ### Technology Stack |
| |
| This website uses modern web technologies. Here's what each one does (with Java analogies): |
| |
| #### Core Framework |
| - **React Router** - Full-stack web framework with Server-Side Generation (SSG) |
| - Handles routing (like Spring MVC controllers) |
| - Provides server-side rendering for better performance and SEO |
| - Enables progressive enhancement (see below) |
| - [Documentation](https://reactrouter.com/) |
| |
| #### Progressive Enhancement |
| |
| The website uses **progressive enhancement** ([learn more](https://reactrouter.com/explanation/progressive-enhancement)), which means: |
| |
| - **With JavaScript enabled**: Users get a Single Page Application (SPA) experience |
| - Fast page transitions without full page reloads |
| - Smooth animations and interactive features |
| - Enhanced user experience |
| |
| - **Without JavaScript**: Users still get a fully functional website |
| - All links and forms work via traditional HTML |
| - Content is accessible to everyone |
| - Better for search engines and accessibility tools |
| |
| This approach ensures the website works for all users, regardless of their browser capabilities or connection speed. |
| |
| #### UI Components |
| - **shadcn/ui** - Pre-built, accessible UI components |
| - Built on top of Radix UI primitives |
| - Similar to a component library like PrimeFaces or Vaadin in Java |
| - Provides buttons, cards, navigation menus, etc. |
| - [Documentation](https://ui.shadcn.com/) |
| |
| - **Radix UI** - Low-level, accessible UI primitives |
| - The foundation that shadcn/ui builds upon |
| - Handles complex accessibility (ARIA) requirements automatically |
| - Think of it as the "Spring Framework" for UI components |
| |
| #### Styling |
| - **TailwindCSS** - Utility-first CSS framework |
| - Instead of writing CSS files, you apply classes directly in components |
| - Example: `className="text-blue-500 font-bold"` makes blue, bold text |
| |
| #### Code Quality Tools |
| - **TypeScript** - Typed superset of JavaScript |
| - Similar to Java's type system |
| - Catches errors at compile-time instead of runtime |
| - Provides autocomplete and better IDE support |
| |
| - **ESLint + Prettier** - Code linting and formatting (like Checkstyle + google-java-format) |
| - ESLint analyzes code for potential errors and enforces coding standards |
| - Prettier handles automatic code formatting (spacing, indentation, etc.) |
| - Integrated together: `npm run lint:fix` handles both linting and formatting |
| - Configuration: `eslint.config.js` and `prettier.config.js` |
| |
| ### Project Architecture |
| |
| The project follows a clear directory structure with separation of concerns: |
| |
| ``` |
| my-react-router-app/ |
| ├── app/ # Application source code |
| │ ├── ui/ # Reusable UI components (no business logic) |
| │ │ ├── button.tsx # Generic button component |
| │ │ ├── card.tsx # Card container component |
| │ │ └── ... # Other UI primitives |
| │ │ |
| │ ├── components/ # Reusable components WITH business logic |
| │ │ ├── site-navbar.tsx # Website navigation bar |
| │ │ ├── site-footer.tsx # Website footer |
| │ │ ├── theme-toggle.tsx # Dark/light mode toggle |
| │ │ └── markdown-layout.tsx # Layout for markdown content pages |
| │ │ |
| │ ├── pages/ # Complete pages (composed of ui + components) |
| │ │ ├── home/ # Home page |
| │ │ │ ├── index.tsx # Main page component (exported) |
| │ │ │ ├── hero.tsx # Hero section (not exported) |
| │ │ │ ├── features.tsx # Features section (not exported) |
| │ │ │ └── ... |
| │ │ ├── downloads/ # Downloads page |
| │ │ │ ├── index.tsx # Main page component (exported) |
| │ │ │ └── content.md # Markdown content |
| │ │ └── ... |
| │ │ |
| │ ├── routes/ # Route definitions and metadata |
| │ │ ├── home.tsx # Home route configuration |
| │ │ ├── download.tsx # Downloads route configuration |
| │ │ └── ... |
| │ │ |
| │ ├── lib/ # Utility functions and integrations |
| │ │ ├── utils.ts # Helper functions |
| │ │ └── theme-provider.tsx # Theme management |
| │ │ |
| │ ├── routes.ts # Main routing configuration |
| │ ├── root.tsx # Root layout component |
| │ └── app.css # Global styles |
| │ |
| ├── build/ # Generated files (DO NOT EDIT) |
| │ |
| ├── public/ # Static files (copied as-is to build/) |
| │ ├── favicon.ico # Website icon |
| │ └── images/ # Images and other static assets |
| │ |
| ├── node_modules/ # Dependencies (like Maven's .m2 directory) |
| ├── package.json # Project metadata and dependencies (like pom.xml) |
| ├── tsconfig.json # TypeScript configuration |
| └── react-router.config.ts # React Router framework configuration |
| ``` |
| |
| #### Key Principles |
| |
| 1. **UI Components (`/ui`)**: Pure, reusable components with no business logic |
| - Can be used anywhere in the application |
| - Only concerned with appearance and basic interaction |
| |
| 2. **Business Components (`/components`)**: Reusable across pages |
| - May contain business logic specific to HBase website |
| - Examples: navigation, footer, theme toggle |
| |
| 3. **Pages (`/pages`)**: Complete pages combining ui and components |
| - Each page has its own directory |
| - Only `index.tsx` is exported |
| - Internal components stay within the page directory |
| - If a component needs to be reused, move it to `/components` |
| |
| 4. **Routes (`/routes`)**: Define routing and metadata |
| - Maps URLs to pages |
| - Sets page titles, meta tags, etc. |
| |
| #### Important Conventions |
| |
| ##### Custom Link Component |
| |
| **Always use the custom Link component from `@/components/link` instead of importing Link directly from `react-router`.** |
| |
| The HBase website includes pages that are not part of this React Router application (e.g., documentation pages, API docs). The custom Link component automatically determines whether a link should trigger a hard reload or use React Router's client-side navigation: |
| |
| **Usage:** |
| |
| ```typescript |
| // ✅ CORRECT - Use custom Link component |
| import { Link } from "@/components/link"; |
| |
| export const MyComponent = () => ( |
| <Link to="/team">Team</Link> |
| ); |
| ``` |
| |
| ```typescript |
| // ❌ WRONG - Do not import Link from react-router |
| import { Link } from "react-router"; |
| |
| export const MyComponent = () => ( |
| <Link to="/team">Team</Link> |
| ); |
| ``` |
| |
| The ESLint configuration includes a custom rule (`custom/no-react-router-link`) that will throw an error if you attempt to import `Link` from `react-router`, helping enforce this convention automatically. |
| |
| ### Getting Started |
| |
| #### 1. Install Dependencies |
| |
| Think of this as `mvn install`: |
| |
| ```bash |
| npm install |
| ``` |
| |
| This downloads all required packages from npm (similar to Maven Central). |
| |
| #### 2. Generate Developers Data |
| |
| **Important:** Before starting the development server, generate the `developers.json` file from the root `pom.xml`: |
| |
| ```bash |
| npm run extract-developers |
| ``` |
| |
| This extracts the developer information from the parent `pom.xml` file and creates `app/pages/team/developers.json`, which is required for the Team page to work properly. Re-run this command whenever the developers section in `pom.xml` changes. |
| |
| #### 3. Start Development Server |
| |
| ```bash |
| npm run dev |
| ``` |
| |
| This starts a local development server with: |
| - **Hot Module Replacement (HMR)**: Code changes appear instantly without full page reload |
| - **Live at**: `http://localhost:5173` |
| |
| ### Development Workflow |
| |
| #### Making Changes |
| |
| 1. **Edit code** in the `app/` directory |
| 2. **Save the file** - changes appear automatically in the browser |
| 3. **Check for errors** in the terminal where `npm run dev` is running |
| |
| #### Common Tasks |
| |
| **Add a new page:** |
| 1. Create directory in `app/pages/my-new-page/` |
| 2. Create `index.tsx` in that directory |
| 3. Create route file in `app/routes/my-new-page.tsx` |
| 4. Register route in `app/routes.ts` |
| |
| **Update content:** |
| - Edit the appropriate `.md` or `.json` file |
| - Changes appear automatically |
| |
| **Add a UI component:** |
| - Check if shadcn/ui has what you need first |
| - Only create custom components if necessary |
| |
| **Check code quality:** |
| ```bash |
| npm run lint |
| ``` |
| |
| **Fix linting and formatting issues:** |
| ```bash |
| npm run lint:fix |
| ``` |
| |
| ### Testing |
| |
| The project uses [Vitest](https://vitest.dev/) for testing React components. |
| |
| **Run tests:** |
| ```bash |
| # Run tests in watch mode (for development) |
| npm test |
| |
| # Run tests once (for CI/CD) |
| npm run test:run |
| |
| # Run tests with UI |
| npm run test:ui |
| ``` |
| |
| **Test coverage includes:** |
| - Home Page - Hero section, buttons, features, use cases, community sections |
| - Theme Toggle - Light/dark mode switching |
| - Navigation - Navbar, dropdown menus, links |
| - Markdown Rendering - Headings, lists, code blocks, tables, links |
| |
| **Writing new tests:** |
| |
| Use the `renderWithProviders` utility in `test/utils.tsx` to ensure components have access to routing and theme context: |
| |
| ```typescript |
| import { renderWithProviders, screen } from './utils' |
| import { MyComponent } from '@/components/my-component' |
| |
| describe('MyComponent', () => { |
| it('renders correctly', () => { |
| renderWithProviders(<MyComponent />) |
| expect(screen.getByText('Hello World')).toBeInTheDocument() |
| }) |
| }) |
| ``` |
| |
| **CI/CD Workflow:** |
| |
| Before merging or deploying, run the full CI pipeline: |
| |
| ```bash |
| npm run ci |
| ``` |
| |
| This command runs all quality checks and builds the project: |
| 1. `npm run lint` - Check linting |
| 2. `npm run typecheck` - Check types |
| 3. `npm run test:run` - Run tests |
| 4. `npm run build` - Build for production |
| |
| All checks must pass before code is considered ready for deployment. |
| |
| **CI/CD Pipeline Example:** |
| ```yaml |
| # Example for GitHub Actions, GitLab CI, etc. |
| - npm run ci # Runs all checks and build |
| ``` |
| |
| ### Building for Production |
| |
| Create an optimized production build: |
| |
| ```bash |
| npm run build |
| ``` |
| |
| This command: |
| 1. Compiles TypeScript to JavaScript |
| 2. Bundles and minifies all code |
| 3. Optimizes images and assets |
| 4. Generates static HTML files |
| 5. Outputs everything to `build/` directory |
| |
| **Generated files location:** |
| ``` |
| build/ |
| ├── client/ # Everything needed for the website |
| │ ├── *.html # Pre-rendered HTML pages |
| │ ├── assets/ # Optimized JavaScript and CSS |
| │ │ ├── *.js # JavaScript bundles (minified) |
| │ │ ├── *.css # Stylesheets (minified) |
| │ │ └── manifest-*.js # Asset manifest |
| │ └── images/ # Optimized images |
| └── server/ # Server-side code (if applicable) |
| ``` |
| |
| The `build/client/` directory contains everything needed to deploy the website to any static file host. |
| |
| ### Maven Integration |
| |
| The website is integrated with the Apache HBase Maven build system using the `frontend-maven-plugin`. The website is configured to build **only during site generation** (`mvn site`) and will not build during regular Maven lifecycle phases like `mvn clean install`. |
| |
| #### When the Website Builds |
| |
| The website build is triggered **only** when you run: |
| |
| ```bash |
| mvn site |
| ``` |
| |
| The website will **NOT** build during regular commands like: |
| - `mvn clean install` |
| - `mvn package` |
| - `mvn compile` |
| |
| This keeps regular HBase builds fast while still allowing the website to be generated when needed. |
| |
| #### What Gets Executed During `mvn site` |
| |
| When you run `mvn site`, the website module automatically: |
| |
| 1. **Cleans previous build artifacts** |
| - Removes `build/` directory |
| - Removes `node_modules/` directory |
| - Ensures a fresh build environment |
| |
| 2. **Installs Node.js v22.20.0 and npm 11.6.2** (if not already available) |
| - Installed to `target/` directory |
| - Does not affect your system Node/npm installation |
| |
| 3. **Runs `npm install`** to install all dependencies |
| - Reads from `package.json` |
| - Installs to `node_modules/` |
| |
| 4. **Extracts developers data** from the parent `pom.xml` |
| - Creates `app/pages/team/developers.json` |
| - Required for the Team page |
| |
| 5. **Runs `npm run ci`** which executes: |
| - `npm run lint` - ESLint code quality checks |
| - `npm run typecheck` - TypeScript type checking |
| - `npm run test:run` - Vitest unit tests |
| - `npm run build` - Production build |
| |
| 6. **Build Output**: Generated files are in `build/` directory |
| |
| #### Maven Commands |
| |
| **Build HBase WITHOUT the Website (default):** |
| ```bash |
| # From HBase root directory |
| mvn clean install |
| ``` |
| |
| **Build the Website:** |
| ```bash |
| # From HBase root or hbase-website directory |
| mvn site |
| ``` |
| |
| This generates the full HBase website including documentation and the React-based website. |
| |
| **Build Website Only:** |
| ```bash |
| # From hbase-website directory |
| cd hbase-website |
| mvn site |
| ``` |
| |
| #### Maven Lifecycle Phases |
| |
| The frontend-maven-plugin binds to these **site-specific** Maven phases: |
| |
| - **pre-site**: Installs Node.js/npm, runs `npm install`, and extracts developers data |
| - **site**: Runs `npm run ci` (lint, typecheck, test, build) |
| |
| #### Integration with CI/CD |
| |
| The Maven configuration ensures consistent builds across different environments: |
| |
| - **Local Development**: Developers can build HBase with `mvn clean install` (website not included) |
| - **Website Generation**: Use `mvn site` to generate the full website and documentation |
| - **CI/CD Pipelines**: Automated builds work out-of-the-box with Maven |
| - **No Manual Steps**: No need to manually run `npm install` or `npm run ci` when using `mvn site` |
| |
| #### Maven Troubleshooting |
| |
| **Build Fails During npm install:** |
| |
| ```bash |
| # Clean and rebuild |
| cd hbase-website |
| mvn clean site |
| ``` |
| |
| This will: |
| - Remove `build/` directory |
| - Remove `node_modules/` directory |
| - Remove `target/` directory |
| - Reinstall Node.js and npm |
| - Install all dependencies fresh |
| - Run the full build pipeline |
| |
| **Build Fails During npm run ci:** |
| |
| This usually indicates: |
| - ESLint errors (code quality issues) |
| - TypeScript type errors |
| - Failing unit tests |
| - Build configuration issues |
| |
| To diagnose, run the commands directly: |
| ```bash |
| cd hbase-website |
| npm install |
| npm run lint # Check linting |
| npm run typecheck # Check types |
| npm run test:run # Check tests |
| npm run build # Check build |
| ``` |
| |
| Fix any errors and try the Maven build again. |
| |
| #### Configuration Files |
| |
| - **pom.xml**: Maven configuration using frontend-maven-plugin |
| - **package.json**: npm scripts and dependencies |
| - **.gitignore**: Excludes `target/`, `node/`, `node_modules/`, `build/` |
| |
| #### For HBase Developers |
| |
| The website only builds when you explicitly run `mvn site`. |
| |
| If you're working on the website: |
| |
| ```bash |
| # Use npm for faster development iteration |
| cd hbase-website |
| npm install |
| npm run dev # Start dev server with hot reload |
| |
| # Or use Maven to build the website |
| cd hbase-website |
| mvn site |
| ``` |
| |
| ### Deployment |
| |
| #### Static Hosting |
| |
| Since this site uses Static Site Generation (SSG), you can deploy the `build/client/` directory to any static file host: |
| |
| - **Apache HTTP Server**: Copy `build/client/` contents to your web root |
| - **Nginx**: Copy `build/client/` contents to your web root |
| - **GitHub Pages**: Push `build/client/` to `gh-pages` branch |
| |
| ### Troubleshooting |
| |
| #### TypeScript Types Are Broken |
| |
| If you see type errors related to React Router's `+types`, regenerate them: |
| |
| ```bash |
| npx react-router typegen |
| ``` |
| |
| #### Port Already in Use |
| |
| If `npm run dev` fails because port 5173 is in use: |
| |
| ```bash |
| # Kill the process using the port |
| lsof -ti:5173 | xargs kill -9 |
| |
| # Or change the port in vite.config.ts |
| ``` |
| |
| #### Need to Clean Everything |
| |
| Nuclear option - removes all generated files: |
| |
| ```bash |
| rm -rf node_modules/ build/ .react-router/ |
| npm install |
| npm run build |
| ``` |
| |
| --- |
| |
| ## Additional Resources |
| |
| - **React Router Documentation**: https://reactrouter.com/ |
| - **Progressive Enhancement Explained**: https://reactrouter.com/explanation/progressive-enhancement |
| - **shadcn/ui Components**: https://ui.shadcn.com/ |
| - **TailwindCSS Docs**: https://tailwindcss.com/ |
| - **TypeScript Handbook**: https://www.typescriptlang.org/docs/ |
| |
| --- |
| |
| Built with ❤️ for the Apache HBase community. |