A full-stack monorepo project designed with modern web technologies. RuamLem features a scalable layered backend powered by Bun and ElysiaJS, and a high-performance frontend built with Next.js (App Router) and Tailwind CSS. The data and authentication layers are handled by Supabase.
The repository is structured as a monorepo containing two main parts:
frontend/: The web application client.backend/: The REST API and services backend.
Both applications use TypeScript to ensure end-to-end type safety and smooth development context switching.
- Framework: Next.js 15 (App Router format for optimized server/client rendering)
- UI & Styling: React 19, Tailwind CSS 4
- State & Data Fetching: React Hooks, Axios
- Build Tool: Next.js Turbopack
- Analytics: Vercel Analytics
- Runtime: Bun
- Framework: ElysiaJS (Fast, type-safe web framework)
- Database & Auth: Supabase
- Documentation: Swagger/OpenAPI (via
@elysiajs/openapi) - Other libraries: bcrypt (hashing), jsdom
RuamLem/
├── backend/ # ElysiaJS Backend
│ ├── src/
│ │ ├── controllers/ # Request handlers & logic endpoints
│ │ ├── routes/ # API Route declarations
│ │ ├── services/ # Core business logic processing
│ │ ├── repositories/ # Data access layer (Supabase interaction)
│ │ └── utils/ # Shared utilities & middleware (logger, etc.)
│ └── tests/ # Test suites & unit tests
│
└── frontend/ # Next.js Frontend
├── src/
│ ├── app/ # App Router pages and layouts
│ ├── components/ # Reusable React components (Navbar, Posts, UI)
│ ├── hooks/ # Custom React Hooks (e.g., useAuth)
│ ├── lib/ # Client utilities and helpers (API instances)
│ ├── services/ # API integration services matching backend domain
│ └── types/ # TypeScript interfaces & domain types
└── docs/ # Documentation (Supabase Analytics info)
The backend uses a strict Layered Architecture to enforce separation of concerns:
- Routes (
/routes): Defines the Elysia endpoints and HTTP methods. Directs incoming requests to the appropriate controllers. - Controllers (
/controllers): Validates input data, extracts parameters, coordinates the business flow by calling services, and formats the HTTP responses. - Services (
/services): Contains the core business rules and logic. It calculates, processes, and decides how data should be transformed. - Repositories (
/repositories): Interacts directly with the database (Supabase). This is the only layer that executes queries and mutations against the persistent storage.
- Auth: Authentication and authorization processes.
- Admin: Administrative tools and moderation controls.
- Analytics & Stats: Data gathering, metrics evaluation, and system statistics.
- Posts: Creating, modifying, deleting, and fetching user posts.
- Profiles: User profile management and data visualization.
- Likes & Files: Interaction mechanisms and media/file uploading endpoints.
The data layer uses PostgreSQL (via Supabase) utilizing a relational approach. The database schema has evolved from its initial manual design to a more robust representation bridging application needs with Supabase's ecosystem.
The original database architecture was a conceptual draft manually mapped out using dbdiagram.io, serving as the starting layout for features encompassing users, posts, and tags.
The live schema expanded upon the initial draft, replacing generic identifiers with Supabase-native ones, accounting for engagement tracking, and optimizing specific entities.
erDiagram
auth_users ||--|| profiles : "1:1 configures"
profiles ||--o{ posts : "writes"
profiles ||--o{ comments : "posts"
profiles ||--o{ post_likes : "gives"
profiles ||--o{ post_views : "views (optional)"
posts ||--o{ comments : "receives"
posts ||--o{ files : "contains"
posts ||--o{ post_likes : "receives"
posts ||--o{ post_views : "receives"
posts ||--o{ post_tags : "categorized by"
files ||--o{ file_downloads: "receives"
profiles ||--o{ file_downloads: "downloads (optional)"
tags ||--o{ post_tags : "associates"
profiles {
uuid id PK
string first_name
string last_name
string avatar_url
}
posts {
int id PK
uuid user_id FK
string title
text body
}
files {
int id PK
int post_id FK
string file_name
string file_url
int file_size
}
comments {
int id PK
int post_id FK
uuid user_id FK
text content
}
post_likes {
int id PK
int post_id FK
uuid user_id FK
}
post_views {
int id PK
int post_id FK
uuid user_id FK "nullable"
}
file_downloads {
int id PK
int file_id FK
uuid user_id FK "nullable"
}
tags {
int id PK
string subject_name
}
post_tags {
int post_id FK
int tag_id FK
}
- profiles: Extends the basic
auth.usersmanaged by Supabase, storing application-specific details like first name, last name, and avatar configurations. - posts: The main content hub generated by users containing textual content and titles.
- files: Handles post attachments storing media/document metadata (URL, file size) pointing to the Supabase Storage Buckets.
- comments: Allows conversational data nested under individual post entities.
- tags / post_tags: A many-to-many relationship resolving categorization for the content. The frontend dynamically resolves the primary post "category" based on the first associated tag.
- post_likes, post_views, file_downloads: Junction tables explicitly tracking granular engagements—not just simple counters on the main table.
-
User Table Replaced by Profiles (Supabase Integration)
- Initial Design: Assumed a generic
userstable with an auto-incrementing integeridand a basicusernamefield. - Real Implementation: Delegates core authentication to Supabase's internal
auth.users. An application-levelprofilestable is now used, tracking auuidrepresenting the logged-in user, along with granular application-specific fields (first_name,last_name,avatar_url, andbio).
- Initial Design: Assumed a generic
-
Expanded Granular Engagement Tracking (Likes, Views, Downloads)
- Initial Design: Did not specify how users would like posts, view counts, or track engagements.
- Real Implementation: Instead of intrinsic integer counters on the
poststable, dedicatedpost_likes,post_views, andfile_downloadstables were introduced. This isolates analytics per exact user or anonymous session, offering much higher analytic fidelity.
-
Dynamic Frontend Categorization
- Initial Design: Focused purely on basic relational tables mapping posts.
- Real Implementation: Instead of relying purely on a hardcoded "category" string, the backend resolves arrayed entries in
tagsand exposes this for the frontend to compute category abstractions dynamically.
The frontend strictly follows Next.js App Router conventions:
- Routing (
src/app): Route segments organized into logical paths (/admin,/community,/profile,/signin,/signup,/post). Nested routing is used for features like[id](view post) and[id]/edit(edit post). - Component Design (
src/components): Reusable UI parts are decoupled from the routing. Contains layout shells,auth-guardfor protected routes, and interaction elements likepost-buttonorsearchbox. - API Services (
src/services): Strongly typed Axios wrappers abstracting backend API calls. - Authentication Flow: Supports a robust flow from standard Sign-up/Sign-in to email confirmation, password resets, and forgot-password routines.
- Bun installed locally (used for both frontend and backend).
- A Supabase project configured with proper tables and buckets.
cd backend
bun install
bun run devcd frontend
bun install
bun run devThis project is properly licensed. See the LICENSE files inside the backend/ and frontend/ directories for details.