CoLearnSpace
A modern web application built with
SvelteKit, Supabase, and a modular feature-first architecture. This app is designed to scale, with a strong focus on shared logic, clean data handling, and good developer experienceπ
π.
Features
- Challenges: Create/host a tech challenge, have users battle it out to showcase their skills as they solve a problem you createdπI'm kidding... but for real
- Courses: Create courses using videos under 50mb or use your youtube videos, can be embedded into your modules easily, just copy and paste the video link
- Not sure if its a featureβ οΈ But you don't have to create an account to use the features here, "ghost" has got your backπ
just don't abuse himπ₯Ίhe's already working overtime.
What to expect as a Dev?
- Feature-based folder structure (/challenges, /courses, etc.)
- Shared business logic in /lib/server/[feature]/
- API routes in /routes/api/
- SSR-powered data fetching using +page.server.ts
- Supabase for authentication, storage, and database
- Supports both authenticated and anonymous users
ποΈ Project Structure
/
βββ lib/
β βββ server/
β βββ challenges/
β βββ core.ts # Main logic: fetching challenges, etc.
β βββ submissions.ts # Submission logic
β βββ community.ts # Community topics logic
β
βββ routes/
β βββ challenge/
β β βββ \[slug]/
β β βββ +page.svelte
β β βββ +page.server.ts # Uses logic from lib/server/challenges
β β βββ community/
β β βββ submissions/
β βββ api/
β βββ challenge/
β βββ +server.ts # POST: Create challenge
β βββ \[slug]/
β βββ +server.ts # GET: Fetch specific challenge
β βββ submissions/
β βββ +server.ts # GET: Submissions for a challenge
β
βββ README.md
π§ Data Layer Philosophy
We use shared logic in lib/server to prevent code duplication. If a feature needs data fetching, validation, or transformation:
- Create a folder for it in lib/server/[feature]
- Place all logic functions in meaningful files (core.ts, submissions.ts, etc.)
- Reuse these functions in both:
- +page.server.ts (for SSR)
-
-
π‘ Example: How to Fetch Challenge Submissions
// lib/server/challenges/submissions.ts
export async function getSubmissionsForChallenge(slug: string) {
// Supabase logic here
}
// routes/api/challenge/[slug]/submissions/+server.ts
import { getSubmissionsForChallenge } from '$lib/server/challenges/submissions';
export async function GET({ params }) {
const submissions = await getSubmissionsForChallenge(params.slug);
return json(submissions);
}
Running Locally
Lets get into business now
You just have to...
npm install
npm run dev
To spin up your backend, make sure you have Docker installed and running
Run the following command
npx supabase start
It will download the supabase docker image for you to use locally When its done running, you will have to copy the supabase url and the anon key and create a .env file in the root of your project
Then set up your .env with Supabase keys, for example:
PUBLIC_SUPABASE_URL=...
PUBLIC_SUPABASE_ANON_KEY=...
π± Contributing
If you're adding a new feature:
- Create a new folder in lib/server/[feature]
- Add functions for handling server logic there
- Use those in +server.ts or +page.server.ts as needed
- Keep your files short and single-responsibility
- We use camelCase in our code, and snake_case in our database to define entities and attributes
π Security Notes
We support both authenticated and anonymous access. For anonymous users, progress tracking is done using the client IP address (non-invasive, limited use). Avoid storing any sensitive data.
π¦ Tech Stack
- SvelteKit
- Docker
- Supabase (PostgreSQL, Storage, Auth)
- TypeScript
- Lucide Icons (via lucide-svelte)
- TailwindCSS