Development Setup - gaulatti/autostrada-frontend GitHub Wiki

This guide provides step-by-step instructions for setting up the Autostrada frontend development environment, including configuration, local development, testing, and common workflows.

Prerequisites

Before you begin, ensure you have the following installed:

  • Node.js (v14.x or later)
  • npm (v6.x or later), yarn, or pnpm
  • Git for version control
  • A code editor like Visual Studio Code (recommended)
  • AWS CLI (if working with AWS services locally)

Initial Setup

1. Clone the Repository

git clone https://github.com/gaulatti/autostrada.git
cd autostrada/frontend

2. Install Dependencies

npm install

3. Configure Environment Variables

Create a .env file in the frontend directory with the following variables:

# API Configuration
VITE_API_FQDN=localhost
VITE_API_PORT=3000

# Authentication
VITE_COGNITO_USER_POOL_ID=your-cognito-pool-id
VITE_COGNITO_CLIENT_ID=your-cognito-client-id
VITE_USER_POOL_DOMAIN=your-cognito-domain
VITE_FQDN=localhost

# Feature Flags
VITE_ENABLE_EXPERIMENTAL_FEATURES=false

For local development, you can use the following options:

  • Use a development Cognito user pool (ask a team member for credentials)
  • Set up a local mock authentication server (see the "Mock Auth Server" section below)
  • Connect to the development API environment

4. Start the Development Server

npm run dev

This will start the Vite development server, typically at http://localhost:5173.

Connect to Backend Services

The frontend requires a running backend service to function properly. You have several options:

Option 1: Connect to Local Backend

  1. Follow the setup instructions in the /service/README.md to run the backend service locally
  2. Make sure your .env file points to the local service:
    VITE_API_FQDN=localhost
    VITE_API_PORT=3000
    

Option 2: Connect to Development Environment

To connect to the development backend:

  1. Update your .env file with the development API endpoint:

    VITE_API_FQDN=api-dev.autostrada.example.com
    # Remove or comment out VITE_API_PORT when using FQDN
    
  2. Obtain development environment credentials from your team lead

Authentication Setup

Setting Up a Mock Auth Server

For local development without AWS Cognito, you can use a mock authentication server:

  1. Install the mock auth server:

    npm install --save-dev @autostrada/mock-auth-server
  2. Start the mock server:

    npx mock-auth-server
  3. Update your .env file to use the mock auth server:

    VITE_USE_MOCK_AUTH=true
    VITE_MOCK_AUTH_URL=http://localhost:9000
    
  4. Use the following test credentials:

Using AWS Cognito

If you're using the real Cognito user pool:

  1. Make sure your .env file contains the correct Cognito settings
  2. Sign up for an account in the Cognito user pool (or ask for test credentials)
  3. You might need to confirm your email address before logging in

Code Structure

Understanding the project structure is crucial for effective development:

frontend/
├── app/                  # Main application code
│   ├── app.css           # Global CSS
│   ├── root.tsx          # App root component
│   ├── routes.ts         # Route definitions
│   ├── clients/          # API clients
│   ├── components/       # Reusable UI components
│   ├── hooks/            # Custom React hooks
│   ├── layouts/          # Page layout components
│   ├── pages/            # Page components
│   └── state/            # Redux state management
├── public/               # Static assets
├── src/                  # Legacy code (being migrated)
├── build/                # Build output
└── locales/              # Internationalization files

Key Files and Directories

  • app/root.tsx: The entry point of the application, sets up providers
  • app/routes.ts: Route definitions for all pages
  • app/clients/api.ts: API client for communicating with the backend
  • app/components/: Reusable UI components
  • app/state/: Redux store configuration, reducers, and sagas
  • app/hooks/: Custom hooks for data fetching, authentication, etc.

Development Workflow

Creating a New Component

  1. Create a new file in the appropriate directory:

    touch app/components/my-new-component.tsx
  2. Use the following template for your component:

    import React from 'react';
    import styles from './my-new-component.module.css';
    
    interface MyNewComponentProps {
      // Define props here
    }
    
    export const MyNewComponent: React.FC<MyNewComponentProps> = (props) => {
      return (
        <div className={styles.container}>
          {/* Component content */}
        </div>
      );
    };
  3. Create a CSS module file if needed:

    touch app/components/my-new-component.module.css

Creating a New Page

  1. Create a new file in the pages directory:

    touch app/pages/my-new-page.tsx
  2. Add the route to app/routes.ts:

    // Add to the routes array
    {
      path: '/my-new-page',
      element: <PrivateLayout />,
      children: [
        {
          path: '',
          element: <MyNewPage />,
        },
      ],
    }
  3. Import your page component where needed

Working with State Management

The application uses Redux with Redux Saga for state management:

  1. Define a new slice in app/state/slices/:

    // myFeature.slice.ts
    import { createSlice, PayloadAction } from '@reduxjs/toolkit';
    
    interface MyFeatureState {
      // Define state shape
    }
    
    const initialState: MyFeatureState = {
      // Initial state
    };
    
    const myFeatureSlice = createSlice({
      name: 'myFeature',
      initialState,
      reducers: {
        // Define reducers
      },
    });
    
    export const { actions, reducer } = myFeatureSlice;
  2. Add your reducer to the root reducer in app/state/store.ts

  3. Create sagas for side effects in app/state/sagas/:

    // myFeature.saga.ts
    import { takeLatest, put, call } from 'redux-saga/effects';
    import { actions } from '../slices/myFeature.slice';
    
    function* handleMyFeatureAction(action) {
      try {
        // Perform side effect
        yield put(actions.success(result));
      } catch (error) {
        yield put(actions.failure(error));
      }
    }
    
    export function* myFeatureSaga() {
      yield takeLatest(actions.request.type, handleMyFeatureAction);
    }
  4. Add your saga to the root saga in app/state/sagas/index.ts

Using the Component Library

Autostrada uses Radix UI Themes combined with Tailwind CSS. Here's how to use them:

import { Card, Flex, Text, Button } from '@radix-ui/themes';

function MyComponent() {
  return (
    <Card className="p-4 max-w-md mx-auto">
      <Flex direction="column" gap="3">
        <Text size="5" weight="bold">Card Title</Text>
        <Text>Card content goes here</Text>
        <Button className="bg-brand hover:bg-brand-dark">
          Click Me
        </Button>
      </Flex>
    </Card>
  );
}

Testing

Running Tests

The project uses Jest and React Testing Library for testing:

# Run all tests
npm test

# Run tests in watch mode
npm test -- --watch

# Run tests with coverage
npm test -- --coverage

Writing Tests

Create test files with the .test.tsx extension next to the component:

// my-component.test.tsx
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MyComponent } from './my-component';

describe('MyComponent', () => {
  it('should render correctly', () => {
    render(<MyComponent />);
    expect(screen.getByText('Expected Text')).toBeInTheDocument();
  });
  
  it('should handle click events', async () => {
    const mockFn = jest.fn();
    render(<MyComponent onClick={mockFn} />);
    
    await userEvent.click(screen.getByRole('button'));
    expect(mockFn).toHaveBeenCalled();
  });
});

Building for Production

To create a production build:

npm run build

The output will be in the build/ directory.

To preview the production build locally:

npm run preview

Troubleshooting

Common Issues

Issue: API connection errors

  • Check that the backend service is running
  • Verify your .env configuration
  • Check for CORS issues in the browser console

Issue: Authentication failures

  • Ensure you're using the correct Cognito credentials
  • Check if your token has expired
  • Verify the Cognito configuration in .env

Issue: Build errors

  • Run npm clean-install to refresh dependencies
  • Check for TypeScript errors
  • Make sure all required environment variables are set

Getting Help

If you encounter issues not covered in this guide:

  1. Check the project wiki for more detailed documentation
  2. Ask in the #frontend-dev Slack channel
  3. Consult with the frontend team lead

Development Best Practices

  1. Code Style: Follow the project's ESLint and Prettier configuration
  2. Naming Conventions:
    • Components: PascalCase (e.g., MyComponent)
    • Files: kebab-case (e.g., my-component.tsx)
    • CSS modules: component-name.module.css
  3. State Management:
    • Use local state for UI-specific state
    • Use Redux for shared application state
    • Use Redux Saga for side effects
  4. Performance:
    • Memoize expensive calculations
    • Use virtualization for long lists
    • Lazy load components when appropriate
  5. Accessibility:
    • Ensure proper ARIA attributes
    • Test with keyboard navigation
    • Maintain sufficient color contrast

By following this guide, you should be able to set up and work effectively with the Autostrada frontend codebase.

⚠️ **GitHub.com Fallback** ⚠️