tree: ece6d717480bd1d98645b8f06a4eb27a047081d5 [path history] [tgz]
  1. app/
  2. public/
  3. scripts/
  4. tests/
  5. .dockerignore
  6. .gitignore
  7. Dockerfile
  8. eslint.config.js
  9. package-lock.json
  10. package.json
  11. pom.xml
  12. prettier.config.js
  13. react-router.config.ts
  14. README.md
  15. tsconfig.json
  16. vite.config.ts
  17. vitest.config.ts
hbase-website/README.md

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

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
    • 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

Progressive Enhancement

The website uses progressive enhancement (learn more), 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
  • 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:

// ✅ CORRECT - Use custom Link component
import { Link } from "@/components/link";

export const MyComponent = () => (
  <Link to="/team">Team</Link>
);
// ❌ 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:

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:

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

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:

npm run lint

Fix linting and formatting issues:

npm run lint:fix

Testing

The project uses Vitest for testing React components.

Run tests:

# 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:

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:

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:

# Example for GitHub Actions, GitLab CI, etc.
- npm run ci  # Runs all checks and build

Building for Production

Create an optimized production build:

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:

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):

# From HBase root directory
mvn clean install

Build the Website:

# 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:

# 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:

# 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:

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:

# 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:

npx react-router typegen

Port Already in Use

If npm run dev fails because port 5173 is in use:

# 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:

rm -rf node_modules/ build/ .react-router/
npm install
npm run build

Additional Resources


Built with ❤️ for the Apache HBase community.