Production-ready Next.js starter with Screaming Architecture, Server Actions, and zero-config Railway deployment.
๐ October 2025 Update: All Railway deployment issues resolved! Now fully compatible with Railway's Railpack builder. See CHANGELOG.md for details.
Most templates give you a framework. This gives you a foundation.
This isn't another bloated starter with every possible feature. It's a battle-tested architecture that:
- โ Screams what it does - Business logic organized by domain, not technical layers
- โ Uses modern patterns - Server Actions instead of API routes
- โ Deploys perfectly - Railway-native with health checks and graceful shutdown
- โ Validates everything - Runtime type safety with Zod
- โ Looks professional - Amber Minimal theme with shadcn/ui
- โ Ready for better-auth - Architecture designed for easy migration
# Clone the repository
git clone https://github.com/contourkde/railway_nextjs_with_shadcn
cd nextjs_best_practices
# Install dependencies
npm install
# Run development server
npm run devVisit http://localhost:3000 to see your app.
src/
โโโ app/ # Next.js App Router
โ โโโ (auth)/ # Auth pages (signup, login, etc.)
โ โโโ dashboard/ # Protected dashboard
โ โโโ api/
โ โ โโโ health/ # Railway health checks
โ โ โโโ system/ # System monitoring
โ โโโ layout.tsx # Root layout with theme
โ
โโโ features/ # Business logic by domain
โ โโโ auth/ # Authentication feature
โ โ โโโ actions/ # Server actions (NO API routes!)
โ โ โ โโโ signup.action.ts
โ โ โ โโโ login.action.ts
โ โ โ โโโ forgot-password.action.ts
โ โ โ โโโ reset-password.action.ts
โ โ โ โโโ validate-email.action.ts
โ โ โโโ components/ # Auth UI components
โ โ โโโ lib/ # Auth utilities (password hashing)
โ โ โโโ types/ # Zod schemas & TypeScript types
โ โ
โ โโโ dashboard/ # Dashboard feature
โ โโโ home/ # Homepage feature
โ โโโ health/ # Health check feature
โ
โโโ components/
โ โโโ ui/ # shadcn/ui components (Amber theme)
โ
โโโ core/ # Shared business rules
โ โโโ config/ # Environment validation
โ โโโ types/ # Shared types
โ
โโโ infrastructure/ # External services
โโโ logging/ # Logging utilities
Your folder structure tells you what the app does, not what framework it uses:
features/auth/- "This app has authentication"features/dashboard/- "This app has a dashboard"features/home/- "This app has a homepage"
No more hunting through components/, utils/, or lib/ folders.
Zero API routes for authentication. Everything uses Next.js 15 server actions:
// โ OLD WAY: API Routes
const response = await fetch('/api/auth/signup', {
method: 'POST',
body: JSON.stringify(data),
});
// โ
NEW WAY: Server Actions
import { signupAction } from '@/features/auth/actions';
const [state, formAction] = useFormState(signupAction, null);Benefits:
- Type-safe by default
- No network overhead
- Better performance
- Simpler code
- Progressive enhancement
Pre-configured with the Amber Minimal theme from tweakcn:
- Warm amber/orange primary color
- Professional light & dark modes
- All shadcn/ui components themed
- Consistent design system
All auth flows included with server actions:
- โ Signup - Email/password registration
- โ
Login - Secure authentication (demo:
demo@example.com/password123) - โ Forgot Password - Password reset flow
- โ Reset Password - Token-based password reset
- โ
Email Verification - Email validation (demo code:
123456)
Features:
- Client + server validation with Zod
- Password hashing with bcrypt
- Toast notifications
- Loading states
- Error handling
- Auto-redirects
Deploys perfectly on Railway with:
- โ
Health check endpoint (
/api/health) - โ
System monitoring (
/api/system) - โ Environment validation at startup
- โ Graceful shutdown (SIGTERM handling)
- โ Production logging
- โ Zero configuration needed
// Environment variables validated at startup
const config = loadAppConfig(); // Throws if invalid
// Forms validated on client AND server
const schema = signupSchema; // Single source of truth
// API responses are type-safe
const health: HealthCheckResponse = await HealthService.check();# Run all tests
npm test
# Watch mode
npm run test:watch
# Coverage report
npm run test:coverage- Setup Guide - Detailed setup instructions
- Quick Reference - Common commands and tasks
- Deployment Guide - Railway deployment guide
- Architecture Overview - Why it's structured this way
- Server Actions Guide - Complete server actions guide
- Server Actions Quick Start - Quick reference
- Architecture Update - Latest improvements
- API Routes Cleanup - API routes vs server actions
- Theme & Migration Summary - Complete migration summary
- Migration Checklist - Step-by-step guide
- Implementation Summary - Detailed implementation
| Technology | Purpose | Version |
|---|---|---|
| Next.js | React framework with App Router | 15.5.4 |
| React | UI library | 19.2.0 |
| TypeScript | Type safety | 5.9.3 |
| Tailwind CSS | Utility-first styling | 4.1.14 |
| shadcn/ui | Component library | Latest |
| Zod | Runtime validation | 4.1.11 |
| React Hook Form | Form validation | 7.64.0 |
| Server Actions | Data mutations | Built-in |
| bcryptjs | Password hashing | 3.0.2 |
| Sonner | Toast notifications | 2.0.7 |
| next-themes | Theme management | 0.4.6 |
All auth forms follow this pattern:
- Shared Schema - Single Zod schema for validation
- Server Action - Server-side logic with
'use server' - Client Form - React Hook Form + useFormState
- Toast Feedback - Success/error notifications
Example:
// 1. Schema (src/features/auth/types/auth.types.ts)
export const signupSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
confirmPassword: z.string(),
}).refine((data) => data.password === data.confirmPassword);
// 2. Server Action (src/features/auth/actions/signup.action.ts)
'use server';
export async function signupAction(
_prevState: SignupActionState | null,
formData: FormData
): Promise<SignupActionState> {
const result = signupSchema.safeParse({
email: formData.get('email'),
password: formData.get('password'),
confirmPassword: formData.get('confirmPassword'),
});
if (!result.success) {
return { success: false, message: 'Validation failed', errors: result.error };
}
// Hash password, create user, etc.
return { success: true, message: 'Account created!' };
}
// 3. Client Form (src/features/auth/components/SignupForm.tsx)
'use client';
export function SignupForm() {
const [state, formAction] = useFormState(signupAction, null);
const [isPending, startTransition] = useTransition();
const onSubmit = (data) => {
const formData = new FormData();
formData.append('email', data.email);
formData.append('password', data.password);
formData.append('confirmPassword', data.confirmPassword);
startTransition(() => formAction(formData));
};
return <form onSubmit={handleSubmit(onSubmit)}>...</form>;
}This architecture is designed for easy migration to better-auth:
- Pattern Alignment - Better-auth uses server-side logic (like our server actions)
- Reusable Schemas - Your Zod schemas work with better-auth
- Same Client Patterns - Form components stay mostly the same
- Easy Migration - Just swap server actions for better-auth actions
// Current (our server actions)
import { signupAction } from '@/features/auth/actions';
// Future (better-auth) - same pattern!
import { signUp } from '@/lib/auth-client';Estimated migration time: 2-4 hours
What you get:
- OAuth providers (Google, GitHub, etc.)
- Session management
- 2FA support
- Email verification (built-in)
- Password reset (built-in)
โ Fully Optimized for Railway Railpack Builder
This template is production-ready with all Railway deployment issues resolved:
- Click the deploy button above
- Set environment variables (if needed)
- Deploy!
Railway automatically:
- โ Uses Railpack builder (modern, optimized)
- โ Detects Next.js and installs dependencies
- โ Builds the app with static asset copying
- โ
Runs health checks on
/api/health - โ
Binds to
0.0.0.0for container networking - โ Handles zero-downtime deployments
Recent Fixes (October 2025):
- Fixed server path for Railpack builder
- Fixed health check failures with
HOSTNAME=0.0.0.0 - Fixed static files not being served (README showing instead of app)
See CHANGELOG.md for detailed fix information.
This template works on any platform that supports Next.js:
- Vercel - Native Next.js support
- Netlify - Next.js runtime
- AWS - Amplify or EC2
- Google Cloud - Cloud Run
- Azure - App Service
Contributions are welcome! Please read our Contributing Guide first.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run tests (
npm test) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License with Attribution - see the LICENSE file for details.
TL;DR: You can use this for anything (including commercial projects), but please give credit to the original project.
- Next.js Team - For the amazing framework
- shadcn - For the beautiful UI components
- Railway - For the best deployment platform
- tweakcn - For the Amber Minimal theme
- Community - For all the feedback and contributions
- Documentation - Check the docs folder
- Issues - GitHub Issues
- Discussions - GitHub Discussions
- Add database integration examples (Prisma, Drizzle)
- Better-auth integration guide
- OAuth provider examples
- 2FA implementation
- Email service integration
- Stripe payment integration example
- Admin dashboard example
- Multi-tenancy example
If this template helped you, please consider giving it a star! It helps others discover the project.
Built with โค๏ธ by the community