This document provides a comprehensive guide for AI composers working on this project, focusing on the current structure and technical decisions.
IMPORTANT: This document should be automatically maintained by AI composers. As the AI composer working on this project, you are responsible for:
- Updating this document whenever you make changes to the codebase or architecture
- Keeping the "Known Issues" section current when resolving or discovering issues
- Maintaining the "Current Tasks and Roadmap" section in sync with project progress
- Adding new API endpoints to the documentation as they are implemented
- Updating file paths and code examples when the codebase structure changes
- Expanding technical explanations based on new implementations
You should proactively update this document without waiting for explicit instructions to do so. The goal is to keep this documentation continuously accurate as the project evolves.
TERMINAL USAGE: Do not start any terminal processes or run commands. The project maintainer will handle running the necessary commands and starting development servers.
DOCUMENTATION GUIDELINES:
- When a task is completed, remove it entirely from the tasks list
- When a bug or issue is fixed, remove it entirely from the tasks list or known issues
- When adding new components or features, ensure they're properly documented with file paths and descriptions
- Keep the roadmap updated based on current priorities
- Use consistent formatting throughout the document
DEX Creator is a platform that lets users create their own perpetual decentralized exchanges (DEXs) using Orderly Networks infrastructure. The platform simplifies DEX creation and deployment through an intuitive UI and automated processes.
The project uses Husky for Git hooks to ensure code quality standards are maintained.
- Husky: Used for managing Git hooks (v9+)
- Prettier Hook: Custom implementation in
.husky/prettier-hook.mjs
for running Prettier on staged files - Lint Staged: Configured to run hooks on staged files before commits
- Commitlint: Ensures commit messages follow conventional commit format
The project uses a hybrid approach to JavaScript modules:
-
Package Configuration: The root
package.json
specifies"type": "module"
which means:.js
files are treated as ES Modules by default- Import/export syntax is used instead of require/module.exports
- Node.js native ES Modules features are leveraged
-
File Extensions:
- Use
.cjs
extension for files that must be CommonJS (like configuration files used by older tools) - Use
.mjs
extension for files that must be ES Modules within a CommonJS context - Follow the module system specified by the containing package's
"type"
field
- Use
This is a monorepo managed with Yarn Workspaces:
dex-creator/
├── app/ # Remix-based frontend (SPA)
│ ├── app/ # Application source code
│ │ ├── components/ # React components
│ │ ├── context/ # React contexts
│ │ ├── utils/ # Utility functions
│ │ └── styles/ # Source styles (including global.css)
│ └── public/ # Public assets
├── api/ # Node.js API server (Hono)
│ ├── src/ # API source code
│ │ ├── models/ # Data models
│ │ └── routes/ # API routes
│ └── prisma/ # Prisma ORM configuration
│ └── schema.prisma # Database schema
├── .github/ # GitHub configuration
│ └── workflows/ # GitHub Actions workflows
├── tsconfig.base.json # Shared TypeScript configuration
└── package.json # Root package with workspaces
- Frontend: Remix (SPA mode), React 19, TypeScript, Wagmi, TanStack React Query
- Styling: UnoCSS, a utility-first CSS framework with atomic CSS capabilities
- Icons: Iconify with @iconify/react for SVG icons
- Notifications: React-Toastify for toast messages
- Backend: Node.js v22+, Hono, TypeScript, Ethers.js
- Database: PostgreSQL with Prisma ORM
- Deployment: GitHub Pages (automated through CI)
- Package Management: Yarn Workspaces
- CI/CD: GitHub Actions
- Authentication: EVM Wallet (Ethereum) signature-based authentication
The DEX Creator platform includes a comprehensive admin system that allows privileged users to manage DEX instances across the platform.
- Role-Based Access Control: Users can be assigned admin privileges through a database flag
- Admin Dashboard: A secure interface for performing administrative actions
- DEX Management: Ability to delete DEXes associated with specific wallet addresses
- Security: Multi-layered authentication and authorization checks
The admin functionality is built upon a isAdmin
boolean field in the User model:
model User {
id String @id @default(uuid())
address String @unique
nonce String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
isAdmin Boolean @default(false)
// other fields...
}
The admin model provides core functions for admin management:
isUserAdmin(userId: string)
: Checks if a user has admin privilegesgetAllAdmins()
: Retrieves all admin users from the database
These functions use raw SQL queries to avoid TypeScript issues with the Prisma schema, providing a pragmatic approach to handling the admin functionality.
Secure API endpoints for admin operations:
GET /api/admin/users
: List all admin users (admin only)GET /api/admin/check
: Check if the current user is an admin
The admin routes implementation uses function declarations with explicit type annotations rather than arrow functions with implicit types. This approach improves code reliability and maintainability.
Note: Admin privileges are set directly in the database, not through API endpoints.
The admin system implements middleware functions to secure admin routes:
checkAdminUser
: Verifies that a user has admin privileges before allowing access to protected endpoints
Admin functionality for managing DEXes:
DELETE /api/dex/admin/delete
: Allows admins to delete a DEX by wallet address
The admin interface provides:
- Admin status checking on page load
- Proper authorization flow with clear user feedback
- Interface for deleting DEXes by wallet address
- Comprehensive error handling and result display
The admin functionality integrates with the existing authentication system:
- Admin status is checked on page load through the Auth context
- The API client handles authentication headers for admin requests
-
Multiple Authorization Layers:
- Bearer token authentication
- Admin role verification
- Raw SQL queries for admin checks to ensure database-level security
-
Error Handling:
- Consistent error responses
- Limited error information exposure
- Comprehensive logging
-
Access Control:
- Strict middleware checks
- Clear separation between admin and regular user routes
In our server-side code, we prioritize explicit typing and standard patterns:
- Function Declarations: Use standard function declarations with explicit parameter types rather than arrow functions with implicit types
- Context Typing: Use Hono's built-in Context type rather than creating custom context types
- Type Assertions: Minimize use of type assertions and prefer proper type definitions
This approach improves code clarity, helps catch errors during development, and makes the codebase more maintainable.
The frontend is a Remix-based Single Page Application (SPA) for DEX creation and management.
Key files:
app/vite.config.ts
: Configuration for Vite with Node.js polyfillsapp/remix.config.js
: Remix configuration with SPA mode enabledapp/app/entry.client.tsx
: Client entry pointapp/app/root.tsx
: Root component with Wagmi and Auth providersapp/app/routes/_index.tsx
: Home page componentapp/app/styles/global.css
: Stylesheets directly imported in componentsapp/app/components/WalletConnect.tsx
: Component for wallet connection and authenticationapp/app/components/LoginModal.tsx
: Modal explaining the wallet signing processapp/app/context/AuthContext.tsx
: Authentication context for wallet auth state managementapp/app/utils/wagmiConfig.ts
: Configuration for Wagmi web3 providerapp/uno.config.ts
: UnoCSS configuration file defining themes, colors, and shortcuts
The application uses SVG Spinners via Iconify and UnoCSS for beautiful and consistent loading animations:
- Package:
@iconify-json/svg-spinners
provides high-quality animated SVG loaders - Integration: UnoCSS's
presetIcons
enables direct use in className strings - Usage Example:
i-svg-spinners:pulse-rings-multiple
class renders the spinner
This approach provides a consistent, visually appealing loading experience throughout the application without additional JavaScript or animation libraries.
The backend is a Node.js API server built with Hono for storing user DEX configurations and handling authentication.
Key files:
api/src/index.ts
: Main server entry pointapi/src/routes/dex.ts
: API routes for DEX operationsapi/src/routes/auth.ts
: API routes for wallet authenticationapi/src/routes/admin.ts
: API routes for admin operationsapi/src/models/dex.ts
: Data models and storage for DEXesapi/src/models/user.ts
: User model for authenticationapi/src/models/admin.ts
: Admin model for admin managementapi/src/lib/prisma.ts
: Prisma client configurationapi/prisma/schema.prisma
: Database schema definition
The application uses PostgreSQL as the database with Prisma ORM for database operations:
- Schema Definition: Located at
api/prisma/schema.prisma
- Models:
User
: Stores user information and authentication detailsToken
: Manages authentication tokens with expiration
- Database Connection: Managed through the Prisma client in
api/src/lib/prisma.ts
- Migrations: Automatically generated in
api/prisma/migrations/
folder
The database is configured with proper indexes and relations to ensure efficient queries and data integrity:
- The
User
model has an index on theaddress
field for quick lookups - The
Token
model has indexes on bothtoken
anduserId
fields - Cascading deletes ensure that when a user is deleted, their tokens are automatically removed
The platform uses EVM wallet authentication with token validation:
- User connects their wallet (e.g., MetaMask) using Wagmi
- A login explainer modal appears automatically to guide users through signing
- Backend generates a random nonce for the user's address
- User signs a message containing the nonce
- Backend verifies the signature using ethers.js
- Upon verification, a token is issued with a 24-hour expiration and the user is authenticated
- On page refresh or application restart, the token is validated with the server
- Expired or invalid tokens trigger automatic logout with notification
- Background validation occurs every 15 minutes to ensure token freshness
- Toast notifications provide feedback throughout the process
The project uses GitHub Actions for continuous integration:
.github/workflows/ci.yml
: Main CI workflow that runs on pushes to main and pull requests- Linting with ESLint
- Format checking with Prettier
- Type checking with TypeScript
- Building both the frontend and API
-
TypeScript Usage:
- Prefer type inference over manual type definitions
- Only add explicit type annotations when necessary
- Use interfaces for object shapes that will be implemented or extended
- Use type aliases for unions, intersections, and simpler object types
-
Naming Conventions:
- Use camelCase for variables, functions, and methods
- Use PascalCase for classes, interfaces, types, and React components
- Use UPPER_CASE for constants
-
Node.js Imports:
- Always use the
node:
prefix for built-in Node.js modules (e.g.,import fs from "node:fs"
) - This ensures you're using the Node.js implementation rather than potentially conflicting with NPM packages
- Example: Use
import path from "node:path"
instead ofimport path from "path"
- Always use the
-
CSS Strategy:
- IMPORTANT: Always prefer UnoCSS utility classes over manual CSS
- UnoCSS configuration in
app/uno.config.ts
defines shortcuts, themes, and colors - For complex components, use composition of UnoCSS utility classes instead of writing custom CSS
- Only use global.css for base styles and overrides that cannot be achieved with UnoCSS
- When using icons, prefer Iconify with the @iconify/react package
-
Comment Philosophy:
- IMPORTANT: Avoid redundant comments that simply restate what the code does
- Do not add comments like "// Get the user's address" or "// Create the DEX in the database"
- Only add comments for complex logic that isn't immediately obvious
- Use function/variable names that make the code self-documenting
- Remove redundant comments during refactoring
- JSDoc comments should be reserved for public APIs or complex functions
-
UI Components:
- Use pill-shaped designs for interactive elements (rounded-full)
- Maintain consistent padding and font sizes across similar components
- Use subtle background colors with transparency (background-light/30)
- Prefer subtle borders to define component boundaries
- Follow the Orderly color palette defined in UnoCSS config
-
Responsive Design:
- Use mobile-first approach with responsive utility classes (e.g.,
md:px-4
) - Reduce paddings, margins, and font sizes on mobile screens
- Hide non-essential UI elements on small screens using
hidden md:block
- Scale down icon sizes and interactive elements for better mobile ergonomics
- Test all UI components on multiple device sizes during development
- Use mobile-first approach with responsive utility classes (e.g.,
-
Error Handling:
- Use toast notifications for error feedback instead of inline error messages
- Log errors to console for debugging
- Provide clear user feedback for all interactions
-
Code Quality:
- All code must pass ESLint rules
- All code must be properly formatted with Prettier
- All TypeScript code must type check without errors
- CI pipeline ensures these standards are maintained
-
Authentication and Security:
- Always validate tokens on application load
- Include token expiration checks
- Handle expired tokens gracefully with user feedback
- Do not store sensitive information in localStorage
- Implement periodic token validation for long-lived sessions
- Database Operations:
- Use Prisma's type-safe operations for all database interactions
- Keep transactions atomic when performing related operations
- Include proper error handling for database operations
- Use async/await for all database operations (Prisma methods return Promises)
- Implement periodic cleanup for expired tokens
The DEX Creator follows a consistent design system with utility-first CSS using UnoCSS.
- Mobile-first approach with responsive breakpoints (sm, md, lg, xl)
- Dark theme with vibrant accents for interactive elements
- Card-based layout with consistent padding and rounded corners
- Pill-shaped buttons with gradient backgrounds and subtle hover effects
- Utility-first implementation directly in component JSX using UnoCSS
primary: {
DEFAULT: "rgb(89, 91, 255)", /* Main action color */
light: "rgb(125, 125, 255)", /* Hover and accent color */
},
secondary: {
DEFAULT: "rgb(157, 78, 221)", /* Secondary actions */
light: "rgb(187, 118, 242)", /* Secondary hover state */
}
success: "rgb(48, 208, 88)", /* Green for success states */
warning: "rgb(242, 153, 74)", /* Amber for warnings */
error: "rgb(242, 78, 78)", /* Red for errors */
These colors should be used instead of direct color utilities:
- Use
text-success
instead oftext-green-*
- Use
bg-success/10
instead ofbg-green-*/10
- Use
text-error
instead oftext-red-*
Subtle animations provide feedback and improve perceived performance:
.slide-fade-in {
animation: slideFadeIn 0.3s ease forwards;
transform-origin: top center;
}
.slide-fade-in-delayed {
animation: slideFadeIn 0.3s ease 0.1s forwards;
opacity: 0;
}
.staggered-item:nth-child(1) { animation: slideFadeIn 0.25s ease 0.05s forwards; }
.staggered-item:nth-child(2) { animation: slideFadeIn 0.25s ease 0.1s forwards; }
For lists with staggered animations:
<div className="list">
{items.map(item => (
<div key={item.id} className="staggered-item">
{item.name}
</div>
))}
</div>
For custom animation timing:
<div>
{items.map((item, index) => (
<div
key={item.id}
style={{
animation: `slideFadeIn 0.25s ease ${0.1 + index * 0.05}s forwards`,
opacity: 0,
transform: "translateY(-10px)"
}}
>
{item.content}
</div>
))}
</div>
- Use animations sparingly for user feedback and transitions
- Apply primarily to elements that appear/update based on user actions
- Keep animations short (0.2-0.3s) and subtle
- Prefer class-based animations over inline styles
Button styles use consistent shortcuts defined in UnoCSS config:
<Button variant="primary">Connect Wallet</Button>
<Button variant="secondary">Cancel</Button>
<Button variant="danger">Delete</Button>
The DEX Creator provides a dedicated image paste system allowing users to customize branding:
-
Multiple methods for user convenience:
- Dedicated "Paste Image" button that requests clipboard access
- Traditional paste area supporting keyboard shortcuts (Ctrl+V / ⌘+V)
- Visual focus states to indicate which paste area is active
-
Advanced crop and resize functionality:
- Interactive crop preview with visual overlay
- Pixel-perfect control via numeric inputs
- Primary logo supports free-form aspect ratios
- Secondary logo and favicon maintain square aspect ratios automatically
- Automatic centering of initial crop area
- Real-time preview of final output dimensions
-
Technical implementation:
- Client-side processing with JSQuash library for WebP conversion and resizing
- Default sizes:
- Primary Logo: 200x42px (horizontal logo for headers)
- Secondary Logo: 40x40px (square icon for UI elements)
- Favicon: 32x32px (browser tab icon)
- Canvas-based cropping with controlled dimensions
- Clipboard API with fallback to ClipboardEvent for cross-browser compatibility
- Logo files stored as WebP images in the repository:
- Primary logo:
public/logo.webp
- Secondary logo:
public/logo-secondary.webp
- Favicon:
public/favicon.webp
- Primary logo:
- Environment flags (VITE_HAS_PRIMARY_LOGO, VITE_HAS_SECONDARY_LOGO) indicate if logos have been set
- No more base64 encoding in environment variables for better repository size management
-
User feedback:
- Loading indicator during image processing
- Preview of pasted image with option to replace
- Toast notifications for success/error states
- Clear visual affordances for all interactions
Example usage:
<ImagePaste
id="primaryLogo"
label="Primary Logo"
value={primaryLogo}
onChange={handleLogoChange}
imageType="primaryLogo"
helpText="This will appear in the header"
/>
The DEX Creator includes a preview feature showing users how their DEX will look with current configuration:
-
Implementation Highlights:
- Inline iframe-based preview system
- Custom React hook for localStorage configuration management
- Zod schema validation for configuration data
- Support for custom logos and branding
-
Key Components:
DexPreview
: Core component rendering the DEX UIPreviewButton
: Manages preview interactionusePreviewConfig
: Hook for configuration management- Preview route handling configuration parsing
The application uses these responsive breakpoints with UnoCSS:
sm
: 640px (small tablets and large phones)md
: 768px (tablets and small laptops)lg
: 1024px (laptops and desktops)xl
: 1280px (large desktops)2xl
: 1536px (extra large screens)
Default (no prefix) styles apply to mobile first, with larger screen adjustments using prefixes:
<div className="text-xs md:text-sm lg:text-base">
Responsive text that scales with screen size
</div>
The project uses Iconify for SVG icons:
@iconify/react
package provides React components- Icons are loaded dynamically from various icon sets
- UnoCSS integration allows for utility-class based icons
- Usage patterns:
{/* Component approach */} <Icon icon="heroicons:check-circle" width={16} /> {/* UnoCSS utility approach */} <div className="i-mdi:check-circle text-success w-5 h-5"></div>
Currently, there are no known issues in the project.
The DEX Creator implements GitHub repository forking to create customized DEX repositories for users. This process is integrated with the DEX creation flow.
-
Immediate Forking:
- When a user creates a new DEX, the system automatically attempts to fork the template repository
- Repository names use a simplified dash-case version of the broker name with a minimal suffix for uniqueness
- The naming approach prioritizes shorter URLs for GitHub Pages deployment (e.g.,
broker-name-1234
) - Repository forking happens in parallel with DEX database entry creation
-
Error Handling:
- If repository forking fails, the DEX is still created in the database without a repository URL
- Users can retry the forking process from the UI using a dedicated "Retry Repository Creation" button
- Detailed error information is logged for debugging purposes
-
Repository Creation Process:
- The system creates a new empty repository under the authenticated GitHub user
- Contents from the template repository are copied recursively to the new repository
- Directories and files are processed with proper error handling for individual files
- User-specific configuration (like broker name) is applied to the repository
-
Logo and Branding Assets:
- Logo files are stored as webp image files in the public folder:
- Primary logo:
public/logo.webp
(horizontal logo for headers) - Secondary logo:
public/logo-secondary.webp
(square icon for UI elements) - Favicon:
public/favicon.webp
(browser tab icon)
- Primary logo:
- Environment variables indicate if logos have been set:
VITE_HAS_PRIMARY_LOGO=true
when primary logo has been setVITE_HAS_SECONDARY_LOGO=true
when secondary logo has been set
- This allows the frontend to use fallback logos when custom logos aren't available
- Binary image data is handled efficiently without base64 encoding in environment variables
- Logo files are stored as webp image files in the public folder:
-
GitHub Pages Deployment:
- A GitHub Pages deployment token is automatically added as a secret to each forked repository
- This token (
TEMPLATE_PAT
) enables GitHub Actions to deploy the DEX to GitHub Pages and allows updating the repository - The token is securely encrypted using libsodium before being added as a repository secret
- If the token is not found in environment variables, a warning is logged but the fork process continues
- GitHub Actions are automatically enabled on forked repositories (addressing GitHub's default security policy)
- The system makes appropriate API calls to enable workflows despite GitHub's default restriction on forked repos
-
Security Considerations:
- GitHub API tokens are stored securely and never exposed to clients
- Only necessary repository permissions are requested
- Rate limiting and error handling prevent abuse
This approach provides a reliable way to create user-specific DEX instances while maintaining a graceful degradation path when GitHub API issues occur.
We use a single-commit approach for all GitHub repository updates:
- What: All repository changes (config files, workflows, themes, logos) are batched into a single Git commit
- Why:
- Reduces GitHub API rate limit usage
- Creates cleaner commit history
- Prevents multiple CI/CD workflow triggers
- Ensures atomic updates (all changes succeed or fail together)
- Simplifies rollback scenarios
This approach replaces the previous implementation that created individual commits for each file change, resulting in more efficient repository management and better reliability.
The project requires Node.js v22 or later for improved ES module support, performance, and modern JavaScript features.
The project uses PostgreSQL with Prisma ORM:
-
Setup with Docker:
# Start a PostgreSQL container docker run --name dex-creator-postgres \ -e POSTGRES_PASSWORD=postgres \ -e POSTGRES_USER=postgres \ -e POSTGRES_DB=dex_creator \ -p 5432:5432 \ -d postgres:16
-
Connection String: The database connection string is configured in the
.env
file:DATABASE_URL="postgresql://postgres:postgres@localhost:5432/dex_creator?schema=public"
-
Prisma Commands:
yarn db:migrate:dev
: Create and apply development migrationsyarn db:migrate:deploy
: Apply migrations in productionyarn db:generate
: Generate Prisma client after schema changesyarn db:studio
: Open Prisma Studio to browse and edit datayarn db:push
: Push schema changes directly to the database (dev only)
-
Schema Location: The Prisma schema is defined in
api/prisma/schema.prisma
The API can be deployed using Docker with a simple approach:
Dockerfile
: Multi-stage build that handles TypeScript compilation with tsup and Prisma generationdocker-entrypoint.sh
: Handles database migrations and application startup- Environment Variables:
MIGRATE_DB=true
: Enables automatic database migrations on startupDATABASE_URL
: PostgreSQL connection stringGITHUB_TOKEN
: For repository forkingTEMPLATE_PAT
: For GitHub Pages deployments and updating the repositoryCEREBRAS_API_KEY
: API key for Cerebras AI theme generationCEREBRAS_API_URL
: Cerebras API endpoint (default: "https://api.cerebras.ai/v1")
# Build the image
docker build -t dex-creator-api .
# Run the container with host networking (recommended on Linux)
docker run -d \
--name dex-creator-api \
-e DATABASE_URL=postgresql://postgres:postgres@localhost:5432/dex_creator?schema=public \
-e GITHUB_TOKEN=your-github-token \
-e TEMPLATE_PAT=your-github-pages-token \
-e CEREBRAS_API_KEY=your-cerebras-api-key \
-e CEREBRAS_API_URL=https://api.cerebras.ai/v1 \
-e MIGRATE_DB=true \
dex-creator-api
The project uses a shared base TypeScript configuration (tsconfig.base.json
) with:
- Target set to ES2023
- Module resolution set to "bundler"
- Strict type-checking enabled
The project uses UnoCSS for styling with a configuration file at app/uno.config.ts
:
- Custom color palette aligned with the Orderly design system
- Presets including UnoCSS default and web fonts
- Custom shortcuts for common UI patterns (buttons, cards, etc.)
- Responsive design utilities
The DEX Creator application follows a utility-first CSS approach with clear priorities for styling implementation:
-
UnoCSS Utility Classes (First Priority):
- Use utility classes directly in component JSX whenever possible
- Leverage UnoCSS shortcuts for common patterns (defined in
app/uno.config.ts
) - Compose complex styles directly in the markup rather than creating custom CSS
- Example:
<div className="flex flex-col gap-2 mt-4 text-sm text-gray-300 rounded-lg p-4 bg-background-card"></div>
-
Component-Specific Styling with clsx (Second Priority):
- Use the
clsx
library to conditionally apply classes - Build variant styles as objects in component files
- Example from Button component:
const variantClasses = { primary: 'btn-connect', secondary: 'btn-secondary', danger: 'bg-red-500 text-white hover:bg-red-600', };
- Use the
-
Global Styles (Use Sparingly):
- Global styles should be limited to:
- Reset styles (already provided by UnoCSS)
- Base HTML element styles
- CSS variables (colors, transitions, etc.)
- Third-party library overrides (like Toastify)
- Located in
app/app/styles/global.css
- Should never override or duplicate utility classes
- Global styles should be limited to:
-
When to Use Global Styles:
- Styling third-party components that can't be styled with classes (React-Toastify, Reown AppKit)
- Defining CSS variables for theme consistency
- Applying base styles to HTML elements
- Custom animations or complex CSS that can't be expressed with utility classes
-
Examples:
- Preferred (UnoCSS):
<button className="btn btn-connect glow-effect">Button</button>
- Acceptable (clsx):
<button className={clsx( 'btn', variantClasses[variant], glowClass )}>Button</button>
- Only When Necessary (global CSS):
/* In global.css - for third-party components */ .Toastify__toast--error { border-left: 4px solid #ff5252 !important; }
- Preferred (UnoCSS):
By prioritizing utility classes, we achieve consistent styling, reduce CSS bloat, and make component styling self-contained and explicit.
The application uses the following responsive breakpoints with UnoCSS:
sm
: 640px (small tablets and large phones)md
: 768px (tablets and small laptops)lg
: 1024px (laptops and desktops)xl
: 1280px (large desktops)2xl
: 1536px (extra large screens)
Default (no prefix) styles apply to mobile first, with larger screen adjustments using prefixes.
The project uses Iconify for SVG icons:
- @iconify/react package provides React components for icons
- Icons can be loaded dynamically from various icon sets
- Heroicons is the primary icon set used for UI elements
- Usage pattern:
<Icon icon="heroicons:icon-name" width={14} className="md:w-4" />
The project uses GitHub Actions for continuous integration:
- Runs on pushes to the main branch and on pull requests
- Uses Node.js v22
- Caches Yarn dependencies for faster builds
- Separates code quality checks from build steps
To run the project locally:
- Install dependencies:
yarn install
- Set up PostgreSQL using Docker (see Database Configuration section)
- Initialize the database:
cd api yarn db:generate yarn db:migrate:dev --name initial_migration
- Start both frontend and backend with auto-reloading:
yarn dev
- This uses concurrently to run both servers in parallel
- The frontend runs on http://localhost:3000 with hot module replacement
- The backend runs on http://localhost:3001 with auto-reloading
Alternative individual commands:
- Start only the frontend:
yarn dev:app
- Start only the backend:
yarn dev:api
- Build the frontend:
yarn build:app
- Build the backend:
yarn build:api
Method | Endpoint | Description | Status |
---|---|---|---|
GET | /api/dex | List all DEXes | Planned |
GET | /api/dex/:id | Get a specific DEX | Planned |
POST | /api/dex | Create a new DEX | Planned |
PUT | /api/dex/:id | Update a DEX | Planned |
DELETE | /api/dex/:id | Delete a DEX | Planned |
POST | /api/auth/nonce | Get a nonce for authentication | Implemented |
POST | /api/auth/verify | Verify signature and authenticate | Implemented |
POST | /api/auth/validate | Validate authentication token | Implemented |
POST | /api/auth/cleanup-tokens | Clean up expired tokens | Implemented |
POST | /api/theme/modify | Generate theme based on AI | Implemented |
Request:
{
"address": "0x1234567890123456789012345678901234567890"
}
Response (200):
{
"message": "Sign this message to authenticate with DEX Creator: 123456",
"nonce": "123456"
}
Request:
{
"address": "0x1234567890123456789012345678901234567890",
"signature": "0xabcdef123456789...signature-data"
}
Response (200):
{
"user": {
"id": "user-uuid",
"address": "0x1234567890123456789012345678901234567890"
},
"token": "auth-token"
}
Request:
{
"address": "0x1234567890123456789012345678901234567890",
"token": "auth-token"
}
Response (200):
{
"valid": true,
"user": {
"id": "user-uuid",
"address": "0x1234567890123456789012345678901234567890"
}
}
Error Response (401):
{
"valid": false,
"error": "Token invalid or expired"
}
Response (200):
{
"success": true,
"message": "Cleaned up 5 expired tokens"
}
Request:
{
"prompt": "A dark blue theme with orange accents"
}
Response (200):
{
"theme": ":root { /* Modified CSS theme content */ }"
}
Error Response (500):
{
"error": "Failed to generate theme"
}
Implementation Note: This endpoint requires environment variables
CEREBRAS_API_KEY
andCEREBRAS_API_URL
to be properly configured for the AI-powered theme generation to work.
- Hono for API: Lightweight, fast, TypeScript-friendly API framework with middleware support
- Remix for Frontend: Excellent DX, built-in SPA mode, React 19 compatibility
- UnoCSS: Atomic CSS framework for efficient, maintainable styling with excellent performance
- Iconify: Comprehensive icon solution with thousands of icons and no bundle size impact
- React-Toastify: Flexible, customizable toast notification system
- Zod for Validation: Type-safe schema validation with TypeScript integration
- Prisma ORM: Type-safe database access with excellent TypeScript integration and auto-generated client
- PostgreSQL: Robust, reliable relational database with excellent JSON support
- Yarn Workspaces: Efficient dependency management for monorepo structure
- GitHub Actions: Automated CI/CD pipeline for quality control and deployment
- Wagmi: Modern React hooks library for Ethereum
- ethers.js: Complete Ethereum library for signature verification
- vite-plugin-node-polyfills: Provides Node.js polyfills for web3 libraries in the browser
- Concurrently: Tool for running multiple commands simultaneously with organized output
- TSX: TypeScript execution and watch mode for Node.js applications
- libsodium-wrappers: Used for encrypting GitHub secrets during repository forking
- CSS Strategy: UnoCSS utility classes for styling, with direct composition in JSX
- Mobile-First Approach: Base styles for mobile with responsive modifiers for larger screens
- TypeScript Strategy: Emphasis on type inference over explicit annotations
- Database Strategy: Type-safe operations with Prisma, organized schema with proper indexing
- Development Tools: tsx for running TypeScript, ESLint and Prettier for code quality
- Quality Assurance: Automated checks through CI pipeline ensure consistent code quality
- Authentication: EVM wallet-based authentication with message signing for security
- Error Handling: Toast notifications for user feedback, console logging for debugging
- Auto-Reloading: Concurrent dev environment with automatic reloading for seamless development
- Frontend uses Vite's hot module replacement for instantaneous updates without page refresh
- Backend uses tsx watch mode to automatically restart the server on file changes
- Concurrently package runs both servers with organized, color-coded output
We've implemented CSS-based animations similar to Svelte's "slide" transitions to provide smooth UI feedback when elements appear or change in the interface.
The following animation classes are available in app/styles/global.css
:
.slide-fade-in {
animation: slideFadeIn 0.3s ease forwards;
transform-origin: top center;
}
.slide-fade-in-delayed {
animation: slideFadeIn 0.3s ease 0.1s forwards;
opacity: 0;
transform: translateY(-10px);
transform-origin: top center;
}
.item-slide-in {
animation: slideFadeIn 0.25s ease forwards;
transform-origin: top center;
}
@keyframes slideFadeIn {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Staggered animation for lists */
.staggered-item {
opacity: 0;
transform: translateY(-10px);
}
.staggered-item:nth-child(1) { animation: slideFadeIn 0.25s ease 0.05s forwards; }
.staggered-item:nth-child(2) { animation: slideFadeIn 0.25s ease 0.1s forwards; }
.staggered-item:nth-child(3) { animation: slideFadeIn 0.25s ease 0.15s forwards; }
.staggered-item:nth-child(4) { animation: slideFadeIn 0.25s ease 0.2s forwards; }
.staggered-item:nth-child(5) { animation: slideFadeIn 0.25s ease 0.25s forwards; }
Apply the slide-fade-in
class to elements that should animate when they first appear:
<Card className="slide-fade-in">
<h3>Content that slides in</h3>
</Card>
Use slide-fade-in-delayed
for elements that should animate slightly after their parent elements:
<div className="slide-fade-in">
<h3>This appears first</h3>
<p className="slide-fade-in-delayed">This appears with a slight delay</p>
</div>
For lists where each item should appear one after another:
<div className="list">
{items.map(item => (
<div key={item.id} className="staggered-item">
{item.name}
</div>
))}
</div>
For more control, you can use inline styles to set custom animation delays:
<div>
{items.map((item, index) => (
<div
key={item.id}
style={{
animation: `slideFadeIn 0.25s ease ${0.1 + index * 0.05}s forwards`,
opacity: 0,
transform: "translateY(-10px)"
}}
>
{item.content}
</div>
))}
</div>
These animations are currently implemented in:
-
The WorkflowStatus component:
- Main card uses
slide-fade-in
- Workflow runs use
staggered-item
for sequential animation - Run details use
slide-fade-in
when selected - Job details use
slide-fade-in-delayed
and dynamic delays
- Main card uses
-
The DEX deployment URL section:
- Uses
slide-fade-in
when it appears after successful deployment
- Uses
- Use animations sparingly to avoid overwhelming the user
- Apply animations primarily to elements that:
- Appear as a result of user action
- Represent new or updated information
- Need to draw user attention
- Prefer class-based animations for consistency
- Use inline style animations only for complex/dynamic scenarios
- Keep animations short (0.2-0.3s) and subtle
For questions or clarifications about this project:
- Project Maintainer: Mario Reder [email protected]
- Repository: [email protected]:OrderlyNetworkDexCreator/dex-creator.git
When you're first assigned to this project, follow these steps:
- Review this entire document to understand the project structure and standards
- Examine the key files mentioned in the Key Components section
- Run the project locally following the Development Instructions
- Review current Known Issues
- When making changes, ensure you update this documentation as specified in the For AI Composers section
This document will be continuously updated as the project evolves.