A fullstack admin panel application with SvelteKit 5 frontend and ElysiaJS backend.
elysian-realm/
├── client/ # SvelteKit 5 frontend
│ ├── src/
│ │ ├── lib/ # Shared components, utilities, and types
│ │ │ ├── assets/ # Static assets like images and icons
│ │ │ ├── components/ # Reusable UI components
│ │ │ ├── datasource/ # Data fetching utilities
│ │ │ ├── state/ # Application state management
│ │ │ ├── types/ # TypeScript types
│ │ │ └── utils/ # Utility functions
│ │ ├── routes/ # SvelteKit routes with file-based routing
│ │ ├── app.css # Global CSS with TailwindCSS
│ │ ├── app.html # HTML entry point
│ │ └── hooks/
│ ├── static/ # Static assets
│ ├── svelte.config.js # SvelteKit configuration
│ ├── vite.config.ts # Vite configuration
│ ├── tailwind.config.js # TailwindCSS configuration
│ └── package.json
├── src/ # Elysia backend
│ ├── routes/
│ ├── controllers/
│ ├── middleware/
│ ├── plugins/
│ ├── types/
│ ├── prisma/
│ ├── utils/
│ ├── config/
│ └── index.ts
├── prisma/ # Prisma schema
│ ├── schema.prisma
│ └── seed.ts
├── package.json
├── bun.lock
└── README.md
You can run this application in two ways: using Docker (recommended) or manually installing dependencies.
docker-compose up --build
This will start all services:
For development with hot reloading:
docker-compose -f docker-compose.dev.yml up --build
bun install
.env.example
file to .env
:cp .env.example .env
.env
file with your actual configurationelysian-realm
DATABASE_URL
in the .env
file with your database credentials:DATABASE_URL="postgresql://username:password@localhost:5432/elysian-realm?schema=public"
bunx prisma migrate dev --name init
bunx prisma db seed
bun run src/index.ts
cd client
bun install
bun run dev
bun run src/index.ts
- Start the development serverbun run test
- Run the test suitebunx prisma migrate dev
- Run database migrationsbunx prisma db seed
- Seed the databasebunx prisma studio
- Open Prisma Studiobun run dev
- Start the development serverbun run build
- Build for productionbun run preview
- Preview the production builddocker-compose up --build
- Start all services in production modedocker-compose -f docker-compose.dev.yml up --build
- Start all services in development mode with hot reloadingdocker-compose down
- Stop all servicesdocker-compose logs
- View logs from all servicesThis project uses Vitest for testing with the vi
test utilities. To run tests:
bun run test # Run all tests once
bun run test:watch # Run tests in watch mode
Note: Use bun run test
rather than bun test
to ensure compatibility with the Vitest test suite and vi
utilities used in the test files.
Create a .env
file in the root directory based on the .env.example
template:
cp .env.example .env
Then update the values in the .env
file with your actual configuration:
DATABASE_URL="postgresql://username:password@localhost:5432/elysian-realm?schema=public"
JWT_SECRET="your-super-secret-jwt-key"
PORT=3000
The application now uses a centralized configuration approach. Instead of directly accessing process.env
, configuration values are accessed through the config
object imported from src/config/config.ts
. This provides better type safety and default values.
After seeding the database, you can log in with:
[email protected]
password
(hashed in the seed file)/api/auth/login
- User login/api/auth/register
- User registration/api/admin/users
- List all users/api/admin/users/:id
- Get user details/api/admin/users/:id
- Update user/api/admin/users/:id
- Delete user/api/admin/roles
- List all roles/api/admin/roles
- Create new role/api/admin/roles/:id
- Update role/api/admin/roles/:id
- Delete role/api/admin/permissions
- List all permissions/api/admin/permissions
- Create new permissionThis project includes a complete Docker setup with four services:
The production Docker images are optimized for size and security:
This project includes full TypeScript type safety for:
The types are automatically generated from the Prisma schema and manually defined for:
This ensures proper type inference throughout the application, even when using the JWT plugin across different modules.
This project uses Data Transfer Objects (DTOs) for defining API response structures and validation schemas. The base DTOs are defined in src/dto/base.dto.ts
and provide common response formats and pagination structures.
All API responses follow a consistent structure with a meta
field containing status information and a data
field containing the actual response data:
{
meta: {
code: string, // Response status code (e.g., 'AUTH-200', 'ADMIN-404')
message: string, // Human-readable response message
errors?: Array<{ // Optional validation errors
field: string, // Field that caused the error
messages: string[] // Array of error messages for the field
}>
},
data: T // Generic data payload
}
Paginated responses follow a standard format with page information and an array of items:
{
page: number, // Current page number
limit: number, // Number of items per page
total: number, // Total number of items
pages: number, // Total number of pages
data: T[] // Array of items for the current page
}
Pagination can be controlled via query parameters:
page
: Page number to retrieve (default: 1)limit
: Number of items per page (default: 10)