npm package: @fnd-platform/frontend
Description: Projen project class for generating Remix frontend packages in fnd-platform
Latest version: 1.0.0-alpha.16

# @fnd-platform/frontend

Projen project class for generating Remix frontend applications with Vite, Tailwind CSS, and shadcn/ui in fnd-platform monorepos.

## Installation

```bash
npm install -D @fnd-platform/frontend
# or
pnpm add -D @fnd-platform/frontend
```

## Quick Start

Add a frontend package to your monorepo in `.projenrc.ts`:

```typescript
import { FndMonorepoProject } from '@fnd-platform/core';
import { FndApiProject } from '@fnd-platform/api';
import { FndFrontendProject } from '@fnd-platform/frontend';

const monorepo = new FndMonorepoProject({
  name: 'my-app',
  defaultReleaseBranch: 'main',
});

const api = new FndApiProject({
  parent: monorepo,
  name: 'api',
  outdir: 'packages/api',
});

const frontend = new FndFrontendProject({
  parent: monorepo,
  name: 'frontend',
  outdir: 'packages/frontend',
  api: api, // Link to API for type-safe client
  auth: true,
  port: 3000,
  shadcnTheme: 'zinc',
});

monorepo.synth();
```

## Configuration Options

| Option        | Type                 | Default           | Description                                     |
| ------------- | -------------------- | ----------------- | ----------------------------------------------- |
| `parent`      | `FndMonorepoProject` | **required**      | Parent monorepo                                 |
| `name`        | `string`             | **required**      | Package name                                    |
| `api`         | `FndApiProject`      | **required**      | Linked API project                              |
| `outdir`      | `string`             | `packages/{name}` | Output directory                                |
| `auth`        | `boolean`            | `true`            | Enable Cognito authentication                   |
| `port`        | `number`             | `3000`            | Development server port                         |
| `shadcnTheme` | `ShadcnTheme`        | `'zinc'`          | Theme color (zinc, slate, stone, gray, neutral) |

## What Gets Generated

```
packages/frontend/
├── app/
│   ├── routes/
│   │   ├── _index.tsx              # Home page
│   │   ├── _auth.tsx               # Auth layout
│   │   ├── _auth.login.tsx         # Login page
│   │   ├── _auth.signup.tsx        # Signup page
│   │   └── dashboard.tsx           # Protected dashboard
│   ├── components/
│   │   ├── ui/                     # shadcn/ui components
│   │   └── layout/                 # Layout components
│   ├── lib/
│   │   ├── api.server.ts           # Server-side API client
│   │   ├── auth.server.ts          # Auth utilities
│   │   └── session.server.ts       # Session management
│   ├── styles/
│   │   └── globals.css             # Global styles
│   └── root.tsx                    # Root component
├── public/
│   └── favicon.ico
├── package.json
├── tailwind.config.js
├── components.json                  # shadcn/ui config
├── vite.config.ts
├── tsconfig.json
└── vitest.config.ts
```

## Examples

### Route with Data Loading

```typescript
// app/routes/blog.$slug.tsx
import { json, type LoaderFunctionArgs } from '@remix-run/node';
import { useLoaderData } from '@remix-run/react';
import { contentApi } from '~/lib/api.server';

export const loader = async ({ params }: LoaderFunctionArgs) => {
  const post = await contentApi.getBySlug(params.slug!);
  if (!post) {
    throw new Response('Not Found', { status: 404 });
  }
  return json({ post });
};

export default function BlogPost() {
  const { post } = useLoaderData<typeof loader>();

  return (
    <article className="prose max-w-none">
      <h1>{post.title}</h1>
      <div dangerouslySetInnerHTML={{ __html: post.content }} />
    </article>
  );
}
```

### Protected Route

```typescript
// app/routes/dashboard.tsx
import { json, type LoaderFunctionArgs } from '@remix-run/node';
import { useLoaderData } from '@remix-run/react';
import { requireAuth } from '~/lib/auth.server';

export const loader = async ({ request }: LoaderFunctionArgs) => {
  const user = await requireAuth(request);
  return json({ user });
};

export default function Dashboard() {
  const { user } = useLoaderData<typeof loader>();

  return (
    <div>
      <h1>Welcome, {user.name}</h1>
    </div>
  );
}
```

### Form with Action

```typescript
// app/routes/contact.tsx
import { json, redirect, type ActionFunctionArgs } from '@remix-run/node';
import { Form, useActionData } from '@remix-run/react';
import { Button } from '~/components/ui/button';
import { Input } from '~/components/ui/input';

export const action = async ({ request }: ActionFunctionArgs) => {
  const formData = await request.formData();
  const email = formData.get('email') as string;
  const message = formData.get('message') as string;

  // Validate and send
  if (!email || !message) {
    return json({ error: 'All fields required' }, { status: 400 });
  }

  await sendContactForm({ email, message });
  return redirect('/thank-you');
};

export default function Contact() {
  const actionData = useActionData<typeof action>();

  return (
    <Form method="post" className="space-y-4">
      {actionData?.error && (
        <p className="text-red-500">{actionData.error}</p>
      )}
      <Input name="email" type="email" placeholder="Email" />
      <Input name="message" placeholder="Message" />
      <Button type="submit">Send</Button>
    </Form>
  );
}
```

## Development

```bash
# Start development server
cd packages/frontend
pnpm dev

# Build for production
pnpm build

# Run tests
pnpm test

# Type check
pnpm typecheck
```

## Adding shadcn/ui Components

```bash
cd packages/frontend
npx shadcn@latest add button
npx shadcn@latest add card
npx shadcn@latest add dialog
npx shadcn@latest add dropdown-menu
```

## API Reference

See the [full API documentation](../../docs/api/modules/frontend_src.html) for detailed type definitions and examples.

### Project Class

- `FndFrontendProject` - Projen project class for frontend packages

### Types

```typescript
import type { FndFrontendProjectOptions, ShadcnTheme } from '@fnd-platform/frontend';

// ShadcnTheme = 'zinc' | 'slate' | 'stone' | 'gray' | 'neutral'
```

## Requirements

- Node.js 20+
- pnpm 8+
- @fnd-platform/core
- @fnd-platform/api (for API linking)

## Related

- [@fnd-platform/core](../core/README.md) - Core Projen project classes
- [@fnd-platform/api](../api/README.md) - API package for backend
- [@fnd-platform/cognito-auth](../cognito-auth/README.md) - Authentication utilities
- [shadcn/ui Documentation](https://ui.shadcn.com/docs)
- [Remix Documentation](https://remix.run/docs)

## License

MIT