A modern, type-safe React application for managing business notifications and reminders. Built with scalability, developer experience, and user experience in mind.
- Overview
- Features
- Tech Stack
- Requirements
- Getting Started
- Development
- Testing
- Building
- Project Structure
- Important Notes
Notifycal is a comprehensive notification management platform that helps businesses set up automated reminders and notifications. The frontend provides a seamless onboarding experience, calendar integration, and business profile management.
- Multi-step Onboarding Flow - Guided setup for new businesses
- Google OAuth Integration - Secure authentication via Google
- Calendar Integration - Google Calendar connectivity for scheduling
- Business Profile Management - Multi-industry business setup and configuration
- Reminder System - Core notification and reminder functionality
- Internationalization - Full i18n support (English/Spanish)
- Phone Number Validation - International phone number support with country codes
- Feedback System - User feedback collection and management
- Type-safe API Layer - Full TypeScript integration with API mocking
- File-based Routing - TanStack Router with automatic route generation
- Comprehensive Error Handling - Error boundaries and fallback components
- Animation Support - Smooth animations via Motion library
- Responsive Design - Mobile-first approach with Tailwind CSS
- Mock Service Worker - API mocking for development and testing
- React - Modern React with latest features
- TypeScript - Type safety throughout the application
- Vite - Fast build tool and development server
- Mantine - Comprehensive React components library
- Tailwind CSS - Utility-first CSS framework
- Tabler Icons - Beautiful SVG icons
- Motion - Animation library for React
- TanStack Router - Type-safe routing with file-based routes
- TanStack Query - Server state management
- TanStack Table - Headless table component
- Zustand - Simple state management
- React Hook Form - Performant forms with validation
- Zod - TypeScript-first schema validation
- @hookform/resolvers - Form validation resolvers
- react-i18next - React internationalization
- i18next - Internationalization framework
- i18next-browser-languagedetector - Language detection
- i18next-http-backend - Backend plugin for loading translations
- Vitest - Unit testing framework
- React Testing Library - Component testing utilities
- Faker - Generate massive amounts of fake (but realistic) data for testing and development
- Storybook - Component development and documentation
- ESLint - Comprehensive linting with 8 configurations
- Prettier - Code formatting
- Radash - Modern utility library
- Luxon - Date and time handling
- Day.js - Lightweight date manipulation
- Clsx - Conditional CSS classes
- Deepmerge-ts - Type-safe object merging
- ts-reset - Improvements for TypeScript's built-in typings
- Node.js 18+ - Required for development
- npm - Package manager (comes with Node.js)
- Clone the repository:
git clone git@github.com:Notifycal/frontend.git
cd frontend- Install dependencies:
npm install- Start development server:
# Ensure your AWS_PROFILE environment variable is set, and that the chosen environment is deployed and has an API Gateway working
API_ENV=<environment-name> npm run dev:remote- Open your browser:
Navigate to
http://localhost:5173
npm run dev- Start development server with local configurationnpm run dev:remote- Start with remote API configuration (requires API_ENV environment variable)npm run build- Build for productionnpm run preview- Preview production buildnpm run test- Run tests (watch mode disabled)npm run test:watch- Run tests in watch modenpm run test:ui- Run tests with UInpm run test:coverage- Run tests with coveragenpm run lint- Run ESLintnpm run lint:fix- Fix ESLint issuesnpm run prettier- Check code formattingnpm run prettier:fix- Fix code formattingnpm run types- Run TypeScript checknpm run check- Run all checks (types, lint, prettier, test)npm run storybook- Start Storybook development servernpm run storybook:build- Build Storybook
All devtools are automatically excluded from production builds. The project includes comprehensive development tools:
Documentation is, at the time of writing this, non-existent. Having said that, usage is similar to the other TanStack devtools. A utility component restricting the devtools to development builds has been provided. The difference in comparison to the other TanStack devtools is the lack of floating mode. Instead, the Devtools are rendered as a component within the actual TanStack Table you define. An additional caveat being that the DevTools component (built-in and provided utility alike) require a table prop from the useReactTable() hook. In other words, if you have multiple tables, each table must have its own Devtools component. Check the simplified code below.
function Table(): JSX.Element {
/* some code */
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
});
return (
<>
{/* table code */}
<TanStackTableDevelopmentTools table={table} />
</>
)
}
The icon can be recognized in the top right corner of the page by the pink React Hook Form clipboard logo. A utility component has also provided. Like the TanStack Table Devtools component above, a prop must be passed from a specific hook. In this case, it is the control prop from the useForm() hook. Similar to TanStack Table, use of React Hook Form DevTools requires the component be added to each unique form. More information can be found in the React Hook Form DevTools documentation.
To reiterate, if you wish to restrict the Devtools to development builds use the provided components found at src/components/utils/development-tools instead of the built-in components from their respective modules.
The project uses Vitest and React Testing Library for comprehensive testing:
# Run all tests
npm run test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage
npm run test:coverage
# Run tests with UI
npm run test:ui- Framework: Vitest with jsdom environment
- Testing Library: React Testing Library with jest-dom matchers
- Mocking: MSW for API mocking
- Coverage: V8 coverage provider
npm run buildThe project includes Terraform configuration for infrastructure deployment. See tf/ directory for infrastructure setup.
src/
├── components/ # Reusable UI components
│ ├── ui/ # Pure UI components (Spinner, Error, etc.)
│ ├── onboarding/ # Onboarding flow components
│ ├── layout/ # Layout components
│ └── utils/ # Utility components and dev tools
├── pages/ # Main page components
├── routes/ # TanStack Router file-based routing
├── api/ # API layer with mocking support
├── hooks/ # Custom React hooks and providers
├── assets/ # Static assets and i18n translations
├── store/ # State management (Zustand stores)
├── testing/ # Testing utilities and helpers
└── styles/ # Global CSS and styling
Faker is included for development and testing. Due to bundle size concerns, always use localized imports:
TO BE CONFIGURED
// ❌ Avoid - imports entire library (~2MB)
import { faker } from '@faker-js/faker';
// ✅ Prefer - localized import (~600KB)
import { faker } from '@faker-js/faker/locale/en';Important: Faker should NOT be used in production builds.
This project uses both Tailwind CSS and Mantine. While they work well together, be aware of potential conflicts. The project is configured to handle this properly, but custom styling may require attention to specificity.
https://shenyien.hashnode.dev/using-mantine-with-tailwind
The project depends on @notifycal/shared for common types and utilities. Ensure this package is properly configured in your development environment.
The project uses a custom configuration system:
config/config.local.js- Local development configurationconfig/config.skel.js- Configuration template- Build process automatically handles environment-specific configs
MSW (Mock Service Worker) is configured for API mocking during development and testing. This allows for a consistent and predictable development experience by intercepting network requests. Mock handlers are defined in the src/api/mocks/handlers directory. The handler needs to be added to src/api/mocks/handlers.ts.
When running the development server locally, MSW intercepts requests made to the apiUrl defined in config/config.local.js. For this to work correctly, apiUrl must be set to the same URL as the frontend application, typically http://localhost:5173.
Alternatively, you can also mock external requests (to URLs that don't belong to the project, for example Google's). To mock an external URL, you define a handler with the full URL string.
Example: Mocking the Google GSI client script in src/api/mocks/handlers/googleGsi.ts:
import { http, HttpResponse } from 'msw';
export const getGoogleGSIHandler = (): Array<HttpHandler> => [
http.get('https://accounts.google.com/gsi/client', () => {
// Return a mock script or an empty response
return HttpResponse.text('// Mocked Google GSI Client Script', {
headers: {
'Content-Type': 'text/javascript',
},
});
})
];
This handler will intercept any request to `https://accounts.google.com/gsi/client` and return a mock JavaScript response, preventing the actual script from being loaded during development or testing.