npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fhi-itdev/next-fhi-cli

v1.0.1

Published

Fullerton Health Indonesia - Next.js Project Scaffolding CLI

Readme

Next FHI CLI

CLI tool untuk scaffolding Next.js project dengan tech stack standar Fullerton Health Indonesia.

🚀 Tech Stack

  • Framework: Next.js 14 (App Router)
  • Auth: NextAuth.js
  • Form Management: React Hook Form + Zod
  • State Management: Zustand
  • UI Framework: shadcn/ui
  • Styling: Tailwind CSS
  • ORM: Prisma
  • Testing: Vitest (unit) + Playwright (e2e)
  • Linting: ESLint + Prettier
  • Git Hooks: Husky + lint-staged

📦 Installation

pnpm add -g @fhi-itdev/next-fhi-cli

Atau install dari source:

git clone <repository-url>
cd next-fhi-cli
pnpm install
pnpm run build
pnpm link --global

🎯 Usage

Membuat Project Baru

next-fhi init my-project

Atau tanpa argumen (akan menanyakan nama project):

next-fhi init

Struktur Project yang Dihasilkan

my-project/
├── src/
│   ├── app/
│   │   ├── api/
│   │   │   └── auth/
│   │   │       └── [...nextauth]/
│   │   │           └── route.ts
│   │   ├── layout.tsx
│   │   └── page.tsx
│   ├── components/
│   │   ├── ui/              # shadcn/ui components
│   │   ├── forms/           # Form components
│   │   └── layouts/         # Layout components
│   ├── lib/
│   │   ├── actions/         # Server actions
│   │   ├── api/             # API utilities
│   │   ├── utils/           # Utility functions
│   │   ├── validations/     # Zod schemas
│   │   ├── hooks/           # Custom hooks
│   │   └── db.ts            # Prisma client
│   ├── store/               # Zustand stores
│   │   └── user-store.ts
│   └── types/               # TypeScript types
├── prisma/
│   └── schema.prisma
├── __tests__/
│   ├── unit/
│   ├── e2e/
│   └── setup.ts
├── public/
│   ├── images/
│   └── icons/
├── .husky/
│   ├── pre-commit
│   └── validate-naming.js
├── components.json
├── vitest.config.ts
├── playwright.config.ts
├── .prettierrc
└── package.json

🔒 Naming Convention Enforcement

Project ini menggunakan Husky untuk memvalidasi naming convention secara otomatis:

Aturan Naming:

| Tipe | Convention | Contoh Benar | Contoh Salah | |------|-----------|--------------|--------------| | React Components (.tsx/.jsx) | PascalCase | UserProfile.tsxLoginForm.tsxButtonPrimary.tsx | userProfile.tsxlogin-form.tsx | | Non-Component Files | kebab-case | user-service.tsauth-utils.tsapi-config.ts | userService.tsAuthUtils.ts | | Folders | kebab-case | user-profile/auth-forms/admin-dashboard/ | UserProfile/authForms/ | | Next.js Special Files | lowercase | page.tsxlayout.tsxroute.tsloading.tsx | - |

Cara Kerja:

Git commit akan otomatis dibatalkan jika ada pelanggaran naming convention. Anda akan melihat error message yang jelas tentang file mana yang bermasalah.

Contoh Error Message:

❌ Error: Component "src/components/userProfile.tsx" harus menggunakan PascalCase!
   Contoh yang benar: UserProfile.tsx, LoginForm.tsx, ButtonPrimary.tsx

❌ Error: File "src/lib/authService.ts" harus menggunakan kebab-case!
   Contoh yang benar: auth-service.ts, user-utils.ts

❌ Commit dibatalkan! Perbaiki naming convention terlebih dahulu.

📝 Available Scripts

Setelah project dibuat, Anda bisa menjalankan:

# Development
pnpm run dev

# Build
pnpm run build

# Testing
pnpm run test              # Run unit tests
pnpm run test:ui           # Run unit tests with UI
pnpm run test:e2e          # Run e2e tests
pnpm run test:e2e:ui       # Run e2e tests with UI

# Linting & Formatting
pnpm run lint
pnpm run lint:fix
pnpm run format

# Database
pnpm exec prisma generate
pnpm exec prisma migrate dev
pnpm exec prisma studio

⚙️ Setup Awal

  1. Copy .env.example ke .env:

    cp .env.example .env
  2. Update environment variables di .env:

    # MSSQL Connection String
    DATABASE_URL="sqlserver://localhost:1433;database=mydb;user=sa;password=YourPassword123;encrypt=true;trustServerCertificate=true"
       
    NEXTAUTH_URL="http://localhost:3000"
    NEXTAUTH_SECRET="your-secret-here"

    Format Connection String MSSQL:

    sqlserver://HOST:PORT;database=DB_NAME;user=USERNAME;password=PASSWORD;encrypt=true;trustServerCertificate=true

    Contoh untuk berbagai environment:

    Local Development:

    DATABASE_URL="sqlserver://localhost:1433;database=myapp_dev;user=sa;password=DevPassword123;encrypt=true;trustServerCertificate=true"

    Azure SQL Database:

    DATABASE_URL="sqlserver://myserver.database.windows.net:1433;database=myapp_prod;user=myadmin@myserver;password=ProdPassword123;encrypt=true"

    Named Instance:

    DATABASE_URL="sqlserver://localhost\\SQLEXPRESS:1433;database=mydb;user=sa;password=Password123;encrypt=true;trustServerCertificate=true"
  3. Generate NEXTAUTH_SECRET:

    openssl rand -base64 32
  4. Generate Prisma client:

    pnpm exec prisma generate
  5. Run migrations:

    pnpm exec prisma migrate dev
  6. Start development server:

    pnpm run dev

🎨 shadcn/ui Components

Project sudah include shadcn/ui. Untuk menambah component baru:

pnpm dlx shadcn@latest add [component-name]

Contoh:

pnpm dlx shadcn@latest add card
pnpm dlx shadcn@latest add dialog
pnpm dlx shadcn@latest add form

📚 Example Usage

Form dengan React Hook Form + Zod

// src/lib/validations/auth.ts
import { z } from 'zod';

export const loginSchema = z.object({
  email: z.string().email('Email tidak valid'),
  password: z.string().min(6, 'Password minimal 6 karakter'),
});

export type LoginInput = z.infer<typeof loginSchema>;
// src/components/forms/login-form.tsx
'use client';

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { loginSchema, type LoginInput } from '@/lib/validations/auth';

export function LoginForm() {
  const { register, handleSubmit, formState: { errors } } = useForm<LoginInput>({
    resolver: zodResolver(loginSchema),
  });

  const onSubmit = (data: LoginInput) => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('email')} />
      {errors.email && <span>{errors.email.message}</span>}
      
      <input type="password" {...register('password')} />
      {errors.password && <span>{errors.password.message}</span>}
      
      <button type="submit">Login</button>
    </form>
  );
}

State Management dengan Zustand

// src/store/user-store.ts
import { create } from 'zustand';

interface UserStore {
  user: any | null;
  setUser: (user: any) => void;
  clearUser: () => void;
}

export const useUserStore = create<UserStore>((set) => ({
  user: null,
  setUser: (user) => set({ user }),
  clearUser: () => set({ user: null }),
}));
// Usage in component
'use client';

import { useUserStore } from '@/store/user-store';

export function UserProfile() {
  const { user, setUser } = useUserStore();
  
  return <div>{user?.name}</div>;
}

🛠️ Development

Untuk development CLI ini:

# Clone repository
git clone <repository-url>
cd next-fhi-cli

# Install dependencies
pnpm install

# Build
pnpm run build

# Link globally untuk testing
pnpm link --global

# Test CLI
next-fhi init test-project

📄 License

MIT

👥 Author

Fullerton Health Indonesia