ns_react_app_template
v5.0.0
Published
NetSuite React App Template with Browser-Based OAuth and Vite
Readme
NetSuite React App Template
A production-ready template for building React applications in NetSuite with browser-based OAuth 1.0a authentication, TypeScript, and Vite. Build modern, responsive applications with real-time NetSuite data access—no proxy server needed!
📦 View on npm | 🚀 Get Started: npx create-netsuite-react-app@latest my-app
✨ What's New in v5.0
🎉 Complete Architecture Overhaul
- ✅ No Proxy Server - OAuth signing happens directly in the browser
- ✅ Single Server - Just run
npm run dev(no more managing 2 servers!) - ✅ Vite Proxy - Built-in proxy handles CORS seamlessly
- ✅ 5 Environment Variables - Down from 10+ (much simpler!)
- ✅ API Restlet - Purpose-built backend for clean API calls
- ✅ Full Feature Parity - Complete OAuth client with caching & error handling
🚀 Key Benefits
| Before (v4.x) | After (v5.0) | |---------------|--------------| | Run 2 servers (React + Proxy) | Run 1 server (Vite only) | | 10+ environment variables | 5 environment variables | | Complex proxy configuration | Zero proxy configuration | | Frequent port conflicts | No port management | | Node proxy server required | Browser-only solution |
🚀 Features
Core Features
- Browser-Based OAuth 1.0a - Secure authentication without a proxy server
- TypeScript + React 18 - Modern development with full type safety
- Vite Build System - Lightning-fast HMR and optimized builds
- SuiteCloud Ready - Pre-configured for immediate deployment
- Request Caching - Built-in axios-cache-interceptor support
Developer Experience
- Single Command Development - Just
npm run dev - Hot Module Replacement - Instant feedback on code changes
- Complete Script Library - Templates for all NetSuite script types
- Type-Safe APIs - Full TypeScript definitions included
📦 Quick Start
Create a New Project
npx create-netsuite-react-app@latest my-app-name
cd my-app-name
npm installConfigure NetSuite Credentials
Copy environment template:
cp env.template .env.localAdd your NetSuite credentials to
.env.local:VITE_NS_ACCOUNT_ID=1234567_SB1 VITE_NS_CONSUMER_KEY=your_consumer_key VITE_NS_CONSUMER_SECRET=your_consumer_secret VITE_NS_TOKEN_ID=your_token_id VITE_NS_TOKEN_SECRET=your_token_secretStart development:
npm run dev
That's it! Your app is now running at http://localhost:5173 🎉
🔧 NetSuite Setup
1. Create Integration Record
- Go to Setup → Integrations → Manage Integrations → New
- Configure:
- Name:
React App Integration - State: Enabled
- Token-Based Authentication: ✓ Checked
- Name:
- Save and copy the Consumer Key and Consumer Secret
2. Create Access Token
- Go to Setup → Users/Roles → Access Tokens → New
- Configure:
- Application: Select your integration
- User: Your NetSuite user
- Role: Administrator or Developer
- Save and copy the Token ID and Token Secret
3. Add to .env.local
Update your .env.local file with the credentials from steps 1 and 2.
💻 Development
Start Development Server
npm run devThis starts Vite dev server at http://localhost:5173 with:
- ✅ Hot module replacement (instant updates)
- ✅ OAuth signing in browser
- ✅ Vite proxy handling CORS
- ✅ Live NetSuite data
Available Scripts
| Command | Description |
|---------|-------------|
| npm run dev | Start development server |
| npm run build | Build for production |
| npm run deploy | Build and deploy to NetSuite |
| npm run type-check | TypeScript type checking |
🏗️ Project Structure
my-app/
├── reactApp/ # React application source
│ ├── src/
│ │ ├── lib/
│ │ │ └── netsuite/ # NetSuite OAuth client library
│ │ │ ├── index.ts # Public API
│ │ │ ├── oauth.ts # OAuth 1.0a implementation
│ │ │ ├── client.ts # REST client with caching
│ │ │ ├── config.ts # Configuration manager
│ │ │ └── types.ts # TypeScript definitions
│ │ ├── components/ # React components
│ │ ├── services/ # API services
│ │ ├── hooks/ # Custom React hooks
│ │ └── types/ # TypeScript definitions
│ ├── index.html
│ └── tsconfig.json
│
├── FileCabinet/
│ └── SuiteScripts/
│ └── [app-name]/
│ ├── react_app_handler.js # Suitelet (serves React app)
│ ├── frontend-app-build/ # Built React app (auto-generated)
│ ├── scripts/
│ │ ├── restlet/
│ │ │ └── api_restlet.js # API Restlet (backend)
│ │ ├── client/
│ │ ├── user_event/
│ │ ├── scheduled/
│ │ └── map_reduce/
│ ├── lib/ # Shared libraries
│ └── config/ # Configuration
│
├── Objects/ # NetSuite script definitions
│ ├── customscript_..._app.xml # Main Suitelet config
│ └── customscript_..._api.xml # API Restlet config
│
├── vite.config.ts # Vite configuration (with proxy)
├── package.json
├── .env.local # Your credentials (git-ignored)
└── env.template # Template for .env.local🔐 How Authentication Works
Architecture Overview
┌─────────────────────────────────────────────────────┐
│ React App (Browser) │
│ - User Interface │
│ - OAuth Client Library │
│ - Generates OAuth signatures in JavaScript │
└──────────────┬──────────────────────────────────────┘
│
│ Request to: /app/site/hosting/restlet.nl
│ + OAuth Authorization header
│ (signed with HMAC-SHA256)
▼
┌─────────────────────────────────────────────────────┐
│ Vite Dev Server (localhost:5173) │
│ - Intercepts API requests │
│ - Proxies to NetSuite URL │
│ - Adds CORS headers │
└──────────────┬──────────────────────────────────────┘
│
│ Proxies to: https://account.restlets.api.netsuite.com
│ + OAuth header (passed through)
▼
┌─────────────────────────────────────────────────────┐
│ NetSuite API Restlet │
│ - Validates OAuth signature │
│ - Processes request │
│ - Returns JSON response │
└─────────────────────────────────────────────────────┘Development vs Production
Development (localhost):
- OAuth signing happens in browser
- Vite proxy forwards requests to NetSuite
- No CORS issues (same-origin from browser's perspective)
Production (deployed to NetSuite):
- React app served from NetSuite FileCabinet
- Direct API calls (no proxy needed)
- No OAuth needed (internal NetSuite authentication)
📡 Using the NetSuite Client
Initialize in main.tsx
import { NetSuite } from './lib/netsuite';
NetSuite.initialize({
restlets: {
default: '/app/site/hosting/restlet.nl?script=customscript_api&deploy=1'
},
credentials: {
accountId: import.meta.env.VITE_NS_ACCOUNT_ID,
consumerKey: import.meta.env.VITE_NS_CONSUMER_KEY,
consumerSecret: import.meta.env.VITE_NS_CONSUMER_SECRET,
tokenId: import.meta.env.VITE_NS_TOKEN_ID,
tokenSecret: import.meta.env.VITE_NS_TOKEN_SECRET
},
isProduction: import.meta.env.PROD,
enableCache: true
});Make API Calls
// Simple POST request
const data = await NetSuite.REST.post({
action: 'getInventory',
data: { itemId: '123' }
});
// With error handling (never throws)
const { data, error } = await NetSuite.REST.post({
action: 'getInventory',
data: { itemId: '123' },
errorPolicy: 'all'
});
// With caching
const data = await NetSuite.REST.post({
action: 'getCustomer',
data: { customerId: '456' },
cacheOptions: { ttl: 5 * 60 * 1000 }, // 5 minutes
id: 'customer-456' // Cache key
});
// Using named restlets
const data = await NetSuite.REST.post({
action: 'processOrder',
data: { orderId: '789' },
restlet: 'orderProcessor' // Uses named restlet
});Client Features
- ✅ Error Policies:
'none'(throws) or'all'(returns{data, error}) - ✅ Request Caching: Built-in with localStorage
- ✅ Multiple Restlets: Named endpoints for different APIs
- ✅ TypeScript: Full type safety and IntelliSense
- ✅ Custom Config: Pass axios options per request
🚀 Deployment to NetSuite
Prerequisites
Install SuiteCloud CLI:
npm install -g @oracle/suitecloud-cliAuthenticate with NetSuite (one-time):
suitecloud account:setupDeploy
npm run deployThis will:
- ✅ Compile TypeScript
- ✅ Build production React bundle
- ✅ Deploy to NetSuite
After Deployment
- Go to Customization → Scripting → Scripts in NetSuite
- Verify these scripts are Active:
- NS React App Template (Suitelet) - Serves the React app
- NS React App Template - API (Restlet) - Handles API calls
- Access your app via the Suitelet URL
🔍 Troubleshooting
CORS Errors in Development
Problem: Access to XMLHttpRequest ... has been blocked by CORS policy
Solution: The Vite proxy should handle this automatically. If you see this error:
- Verify Vite dev server is running (
npm run dev) - Check
vite.config.tshas the proxy configuration - Ensure you're using relative URLs:
/app/site/hosting/restlet.nl
OAuth 401 Unauthorized
Problem: NetSuite returns 401 Unauthorized
Solution: Check your credentials:
- Verify all 5 environment variables are set in
.env.local - Account ID format: Use underscores (e.g.,
1234567_SB1) - Regenerate tokens if they're old
- Check token hasn't been revoked in NetSuite
TypeScript Errors
Problem: Type errors when importing NetSuite client
Solution: Run type checking:
npm run type-checkDeployment Failures
Problem: suitecloud command not found
Solution: Install globally:
npm install -g @oracle/suitecloud-cli🛡️ Security Best Practices
Development
- ✅ Never commit
.env.local- Already in.gitignore - ✅ Use environment-specific tokens - Different tokens for dev/prod
- ✅ Rotate tokens regularly - Revoke and regenerate periodically
- ✅ Limit token permissions - Use roles with minimum required permissions
Production
- ✅ Deploy to NetSuite FileCabinet - React app runs inside NetSuite
- ✅ No credentials in browser - Production mode doesn't use OAuth
- ✅ NetSuite authentication - Users must be logged in to access
- ✅ Role-based access - Control who can access the Suitelet
📚 Additional Resources
NetSuite Documentation
Related Tools
📄 License
ISC
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
🆘 Support
For issues or questions:
- Check the GitHub repository
- Review NetSuite execution logs
- Enable debug mode and check browser console
Built with ❤️ for NetSuite developers
