Intermediate3 min read

Creating Components

Learn how to create new React components following SaaSStinger Lite architecture patterns.

Creating Components

This guide explains how to create new components in SaaSStinger Lite.

The goal is to keep components:

  • Reusable
  • Maintainable
  • Type-safe
  • Consistent with the application architecture

Before Creating a Component

Ask:

  1. Is this component reusable?
  2. Does it belong to an existing feature?
  3. Does it require client-side interaction?
  4. Does it need data from the server?

These answers determine where the component belongs.


Component Locations

Shared UI Components

Location:

src/components/ui/

Use for:

  • Buttons
  • Inputs
  • Cards
  • Dialogs
  • Tables
  • Form elements

Example:

Button

Card

DropdownMenu

Feature Components

Location:

src/components/{feature}/

Examples:

src/components/projects/

src/components/members/

src/components/invites/

Use for:

  • Business features
  • Feature-specific interfaces
  • Workflow components

Component Naming

Use descriptive names.

Good:

WorkspaceSwitcher.tsx

MemberActions.tsx

ProjectCard.tsx

Avoid:

Component.tsx

Widget.tsx

Helper.tsx

unless the purpose is clear.


Basic Component Example

Example:

interface CardProps {
  title: string;
}

export function ExampleCard({
  title,
}: CardProps) {
  return (
    <div>
      {title}
    </div>
  );
}

TypeScript Guidelines

Always define component props.

Example:

interface UserCardProps {
  name: string;
  email: string;
}

Avoid:

function UserCard(props: any)

Server Components

Use server components by default.

Suitable for:

  • Displaying data
  • Static content
  • Server-rendered pages

Example:

export default async function Page() {

}

Client Components

Use client components only when required.

Required for:

  • useState
  • useEffect
  • Browser APIs
  • Event handlers

Example:

"use client";

export function DialogButton() {

}

Component Data Access

Components should not directly access Firestore.

Avoid:

Component

 ↓

Firestore

Use:

Component

 ↓

Hook

 ↓

Server Action

 ↓

Service

 ↓

Repository

 ↓

Firestore

Using Hooks

Hooks provide reusable client-side logic.

Location:

src/hooks/

Examples:

useMembers.ts

useWorkspace.ts

useProject.ts

Example:

const {
  members
} = useMembers();

Using UI Components

Reuse existing UI primitives.

Example:

import { Button } 
from "@/components/ui/button";

Use:

<Button>
Save
</Button>

instead of creating duplicate buttons.


Adding a Dialog

Recommended structure:

FeatureDialog.tsx

Pattern:

Open Dialog

      ↓

Collect Input

      ↓

Call Server Action

      ↓

Show Result

Adding a Table

Recommended structure:

FeatureTable.tsx

FeatureRow.tsx

FeatureActions.tsx

Example:

MembersTable

 ├── MemberRow

 └── MemberActions

Handling Loading States

Always consider:

  • Initial loading
  • Empty state
  • Error state
  • Success state

Use:

components/ui/skeleton.tsx

for loading placeholders.


Handling Errors

Display user-friendly errors.

Avoid exposing:

  • Database errors
  • Internal stack traces
  • Security information

Example:

Unable to save changes.
Please try again.

Adding a New Feature

For larger features, create:

components/

actions/

services/

server/

types/

Example:

src/components/reports/

src/actions/reports.ts

src/services/reports/

src/server/reports.server.ts

src/types/reports.ts

Testing New Components

Before completing:

Run:

pnpm tsc --noEmit

Then:

pnpm lint

Then:

pnpm build

Component Checklist

Before merging:

  • Component has clear responsibility
  • Props are typed
  • Existing UI components are reused
  • No direct Firestore access
  • Server/client boundary is correct
  • Loading states handled
  • Error states handled

Related Documentation

  • Components Overview
  • UI System
  • Feature Components
  • Adding Components
  • Server Actions
  • Working With Services

Related Articles