- Node.js 16+ and npm
- Git
- Modern browser (Chrome, Firefox, Edge)
- Code editor (VS Code recommended)
# Clone repository
git clone https://github.com/tamaygz/promptArq.git
cd promptArq
# Install dependencies
npm install
# Set up environment variables
cp .env.example .env
# Edit .env with your values
# Start development server
npm run devThis starts:
- Vite dev server on port 5173 (or 5000)
- OAuth proxy server on port 3001
Create .env file:
# GitHub OAuth (for authentication features)
VITE_GITHUB_CLIENT_ID=your_client_id
VITE_GITHUB_CLIENT_SECRET=your_client_secret
VITE_GITHUB_REDIRECT_URI=http://localhost:5173/auth/callback
# OAuth Proxy Port
PROXY_PORT=3001GitHub OAuth App Setup:
- Go to GitHub Settings → Developer settings → OAuth Apps
- Create new OAuth app
- Homepage URL:
http://localhost:5173 - Callback URL:
http://localhost:5173/auth/callback - Copy Client ID and generate Client Secret
- Add to
.env
promptArq/
├── src/
│ ├── components/ # React components
│ │ ├── ui/ # Radix UI components
│ │ ├── PromptEditor.tsx
│ │ ├── PromptList.tsx
│ │ └── [other features]
│ ├── lib/ # Utilities and core logic
│ │ ├── types.ts # TypeScript types
│ │ ├── storage-adapter.ts # Persistence layer
│ │ ├── default-*.ts # Default data
│ │ └── utils.ts # Helper functions
│ ├── hooks/ # Custom React hooks
│ ├── assets/ # Images, icons
│ ├── styles/ # CSS files
│ ├── App.tsx # Main application
│ └── main.tsx # Entry point
├── server.js # OAuth proxy server
├── vite.config.ts # Vite configuration
├── tailwind.config.js # Tailwind configuration
├── package.json # Dependencies and scripts
└── docs/ # Documentation
- React 19 - UI library
- TypeScript - Type safety
- Vite - Build tool
- Tailwind CSS 4 - Styling
- Radix UI - Accessible primitives
- Framer Motion - Animations
- Phosphor Icons - Icon library
- Sonner - Toast notifications
- React useState
- Custom useStorage hook
- Local/Spark KV storage
- Express - OAuth proxy
- CORS - Cross-origin handling
The app uses a dual-mode storage system:
// src/lib/storage-adapter.ts
export interface StorageAdapter {
keys(): Promise<string[]>;
get<T>(key: string): Promise<T | undefined>;
set<T>(key: string, value: T): Promise<void>;
delete(key: string): Promise<void>;
}Adapters:
SparkKVAdapter- GitHub Spark deploymentLocalStorageAdapter- Local development
Auto-detection:
isSparkEnvironment()
├─> localhost → false (use localStorage)
├─> github.app domain → true (use Spark KV)
└─> Default → false (safe fallback)Custom hook for persistent state:
const [prompts, setPrompts] = useStorage<Prompt[]>('prompts', []);Features:
- Automatic persistence
- Type-safe
- Initial value support
- Works with both storage adapters
Layout Components:
- App.tsx - Main layout
- Sidebar with project/tag navigation
- Content area with editor
Feature Components:
- Modular, self-contained
- Props-based communication
- Event callbacks for actions
UI Components:
- Radix primitives wrapped with Tailwind
- Consistent styling
- Accessible by default
# Development mode (hot reload)
npm run dev
# Build for production
npm run build
# Preview production build
npm run preview
# Lint code
npm run lintpackage.json scripts:
dev- Runs client + server concurrentlyclient- Vite dev server onlyserver- OAuth proxy onlybuild- TypeScript compile + Vite buildkill- Kill process on port 5000 (Windows)
- Add TypeScript type (
src/lib/types.ts)
export type MyEntity = {
id: string
name: string
// ...
}- Add to App state
const [myEntities, setMyEntities] = useStorage<MyEntity[]>('my-entities', []);-
Create component (
src/components/MyEntityDialog.tsx) -
Wire up in App.tsx
- Create component file
- Import in App.tsx
- Add to UI
- Connect state/callbacks
Just use with useStorage:
const [data, setData] = useStorage<T>('new-key', defaultValue);Automatically works with both storage adapters.
Tailwind CSS:
- Utility-first approach
- Configure in
tailwind.config.js - Custom theme in
src/styles/theme.css
Component Styling:
<div className="flex items-center gap-2 p-4 rounded-lg bg-secondary">
{/* content */}
</div>Dark Mode:
App uses dark theme by default. Light mode support via next-themes if needed.
Local State:
const [value, setValue] = useState(initialValue);Persistent State:
const [value, setValue] = useStorage('key', initialValue);Prop Drilling: Pass callbacks down for child components to trigger parent actions.
Future: Consider Zustand or Redux if state gets complex.
Currently no automated tests. Contributions welcome!
Manual Testing:
- Test all features in both Spark and local mode
- Test with/without authentication
- Test mobile responsive design
- Test keyboard shortcuts
- Test error handling
- Push to GitHub
- Spark automatically deploys
- KV store automatically available
- HTTPS automatically configured
# Build production bundle
npm run build
# Output in dist/
dist/
├── index.html
├── assets/
│ ├── index-[hash].js
│ └── index-[hash].css
└── [other assets]Deploy dist/ folder to:
- Vercel
- Netlify
- AWS S3 + CloudFront
- Any static hosting
Requirements:
- HTTPS (for OAuth)
- OAuth proxy server running
- Environment variables configured
Deploy server.js separately:
# Example: Deploy to Heroku
git push heroku main
# Or run on VPS
node server.jsUpdate .env with production OAuth URLs.
Console:
window.spark- Check Spark availability- Storage adapter logs
Network:
- API requests to OAuth proxy
- GitHub OAuth flow
- Storage operations
React DevTools:
- Component hierarchy
- Props/state inspection
- Performance profiling
OAuth not working:
- Check client ID/secret
- Verify redirect URI matches exactly
- Check CORS settings on proxy
- Try incognito mode
Storage not persisting:
- Check localStorage quota
- Verify Spark KV in production
- Check storage adapter detection
Build errors:
- Clear node_modules:
npm run clean && npm install - Check TypeScript errors:
npm run build - Update dependencies
- Follow existing code style
- Write meaningful commit messages
- Test thoroughly before PR
- Update documentation
- Add types for new code
- Use TypeScript
- 2-space indentation
- Semicolons required
- Single quotes for strings
- Trailing commas in multiline
- Fork repository
- Create feature branch:
git checkout -b feature/my-feature - Make changes
- Test thoroughly
- Commit:
git commit -m "Add my feature" - Push:
git push origin feature/my-feature - Create Pull Request
- Address review comments
See Architecture.md for detailed technical architecture including:
- Component structure
- Data flow
- Storage system
- Authentication flow
- MCP integration
- User Guide - End-user documentation
- MCP Guide - MCP integration setup
- Windows App - Desktop application
- GitHub Issues - Bug reports & features