Skip to content
This repository was archived by the owner on May 6, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
f314538
AAAAaaaaaAAAAA
techpixel Oct 24, 2025
9d1a829
fix configmodule
techpixel Oct 24, 2025
70d4c7a
fix: change auth fetching
LeafdTK Oct 25, 2025
0a3447f
feat: working auth
techpixel Oct 25, 2025
5ba200f
feat: work on onboarding
techpixel Oct 25, 2025
e022c2f
fix: add first and last name endpoint
LeafdTK Oct 25, 2025
b32fd27
feat: work on onboarding
techpixel Oct 25, 2025
0f4ab1c
fix: update auth system
LeafdTK Oct 25, 2025
c972ab5
fix
LeafdTK Oct 25, 2025
4719f36
feat: onboarding & projects
techpixel Oct 25, 2025
4f108b4
feat: onboarding & projects 2
techpixel Oct 25, 2025
59070fc
fix: add datadog continous profiler
LeafdTK Oct 25, 2025
e3fa38a
chore(ci): modify images tag
LeafdTK Oct 27, 2025
9187356
fix: update migrations
LeafdTK Oct 27, 2025
7a7f175
fix: add datadog check
LeafdTK Oct 27, 2025
1b54dfb
feat: polish onboarding 1
techpixel Oct 27, 2025
9a1682a
polish projects page
techpixel Oct 27, 2025
906c143
fix: add hackatime project support
LeafdTK Oct 27, 2025
099bdad
feat: polish onboarding 2
techpixel Oct 28, 2025
9e7685d
feat: update hackatime account flow
techpixel Oct 28, 2025
038253f
add butler
techpixel Oct 29, 2025
d15d266
swap to user
techpixel Oct 29, 2025
6abcc13
hackatime project modal
techpixel Oct 29, 2025
e6a0dc6
fix: add checks to hackatime account link
LeafdTK Oct 29, 2025
3715c90
fix: add checks to hackatime projects
LeafdTK Oct 29, 2025
e5a7ff2
feat: more project types page (frontend)
techpixel Oct 30, 2025
da9156a
fix: improved error messaging
techpixel Oct 30, 2025
e50c5f9
fix: use datepicker
techpixel Oct 30, 2025
1a8fefd
fix: fix number
techpixel Oct 30, 2025
b1c2aee
fix: project card preview
techpixel Oct 30, 2025
b35b694
Merge branch 'leafd/launch' into manitej/app
LeafdTK Oct 31, 2025
5124293
fix: remove duplicate import
LeafdTK Oct 31, 2025
98b9662
fix: label
techpixel Oct 31, 2025
36ad005
fix: lock email input
techpixel Oct 31, 2025
b3a6090
feat: add sticker
techpixel Oct 31, 2025
9e8916c
fix: tutorial also available
techpixel Oct 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 15 additions & 14 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Build and Push Docker Images

on:
push:
branches: [ main, leafd/launch ]
branches: [ main, leafd/launch, manitej/app ]

jobs:
build:
Expand All @@ -24,24 +24,23 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/${{ github.repository }}/owl-api
ghcr.io/${{ github.repository }}/lark-ui
tags: |
type=ref,event=branch
type=sha,prefix={{branch}}-
type=raw,value=latest,enable={{is_default_branch}}
- name: Set tag prefix
id: tag-prefix
run: |
if [ "${{ github.ref_name }}" = "main" ]; then
echo "prefix=prod-" >> $GITHUB_OUTPUT
else
echo "prefix=staging-" >> $GITHUB_OUTPUT
fi

- name: Build and push owl-api
uses: docker/build-push-action@v5
with:
context: .
file: ./owl-api/Dockerfile
tags: ghcr.io/${{ github.repository }}/owl-api:latest,ghcr.io/${{ github.repository }}/owl-api:${{ github.sha }}
tags: |
ghcr.io/${{ github.repository }}/owl-api:latest
ghcr.io/${{ github.repository }}/owl-api:${{ steps.tag-prefix.outputs.prefix }}${{ github.sha }}
push: true
cache-from: type=gha
cache-to: type=gha,mode=max
Expand All @@ -51,7 +50,9 @@ jobs:
with:
context: .
file: ./lark-ui/Dockerfile
tags: ghcr.io/${{ github.repository }}/lark-ui:latest,ghcr.io/${{ github.repository }}/lark-ui:${{ github.sha }}
tags: |
ghcr.io/${{ github.repository }}/lark-ui:latest
ghcr.io/${{ github.repository }}/lark-ui:${{ steps.tag-prefix.outputs.prefix }}${{ github.sha }}
push: true
cache-from: type=gha
cache-to: type=gha,mode=max
Expand Down
13 changes: 13 additions & 0 deletions env.example
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ REDIS_DB=0
# Admin Configuration
ADMIN_EMAIL_WHITELIST=admin@example.com,admin2@example.com

# Hackatime Configuration
HACKATIME_ADMIN_API_URL=https://hackatime.hackclub.com/api/admin/v1
HACKATIME_API_KEY=your_hackatime_api_key_here

# Mail Service Configuration
MAIL_SERVICE_PORT=3003
MAIL_SERVICE_CORS_ORIGIN=http://localhost:3000
Expand All @@ -42,6 +46,15 @@ LARK_UI_PORT=5173
PUBLIC_API_URL=http://localhost:3000
VITE_API_URL=http://localhost:3002

# Datadog Configuration (optional)
DD_AGENT_HOST=localhost
DD_TRACE_AGENT_PORT=8126
DD_APM_ENABLED=true
DD_PROFILING_ENABLED=true
DD_SERVICE=owl-api
DD_ENV=production
DD_VERSION=1.0.0

# Production Settings (uncomment for production)
# USER_SERVICE_NODE_ENV=production
# CORS_ORIGIN=https://your-frontend-domain.com,https://your-api-domain.com
Expand Down
14 changes: 7 additions & 7 deletions gateway/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,23 @@ if (process.env.NODE_ENV !== 'production') {

const app = express();
const PORT = process.env.PORT || 3000;
const USER_SERVICE_URL = process.env.USER_SERVICE_URL || 'http://localhost:3002';
const MAIL_SERVICE_URL = process.env.MAIL_SERVICE_URL || 'http://localhost:3002';
const SERVICE_URL = process.env.SERVICE_URL || 'http://localhost:3002';
const UI_SERVICE_URL = process.env.UI_SERVICE_URL || 'http://localhost:5173';

app.use(cors());
app.use(express.json());

const createServiceProxy = (serviceName: string, targetUrl: string) => {
return createProxyMiddleware({
target: targetUrl,
changeOrigin: true,
logLevel: 'debug',
pathRewrite: (path, req) => {
return path.replace(`/api/${serviceName}`, '');
// Don't rewrite the path - keep the full API path for the unified service
return path;
},
onProxyReq: (proxyReq, req, res) => {
console.log(`[${serviceName.toUpperCase()} →] ${req.method} ${req.url} -> ${targetUrl}${req.url.replace(`/api/${serviceName}`, '')}`);
console.log(`[${serviceName.toUpperCase()} →] ${req.method} ${req.url} -> ${targetUrl}${req.url}`);

if (req.body && Object.keys(req.body).length > 0) {
const bodyData = JSON.stringify(req.body);
Expand Down Expand Up @@ -54,7 +55,7 @@ const createServiceProxy = (serviceName: string, targetUrl: string) => {
});
};

app.use('/api/user', express.json(), createServiceProxy('user', USER_SERVICE_URL));
app.use('/api', express.json(), createServiceProxy('unified', SERVICE_URL));

app.use('/', createProxyMiddleware({
target: UI_SERVICE_URL,
Expand All @@ -73,7 +74,6 @@ app.use('/', createProxyMiddleware({
app.listen(PORT, () => {
console.log(`🌙 Gateway ready at http://localhost:${PORT}`);
console.log(` / → UI (${UI_SERVICE_URL})`);
console.log(` /api/* → Unified Service (${USER_SERVICE_URL})`);
console.log(` Mail Service (${MAIL_SERVICE_URL}) - Internal only`);
console.log(` /api/* → Unified Service (${SERVICE_URL})`);
});

148 changes: 70 additions & 78 deletions lark-ui/src/lib/BottomNavigation.svelte
Original file line number Diff line number Diff line change
@@ -1,78 +1,67 @@
<script lang="ts">
import { goto } from '$app/navigation';

const { onboarding = true } = $props();

let activeTab = 'create';

function navigateTo(tab: string) {
activeTab = tab;
switch(tab) {
case 'create':
goto('/home');
goto('/app/projects');
break;
case 'explore':
goto('/explore');
goto('/app/explore');
break;
case 'shop':
goto('/shop');
break;
case 'login':
goto('/login');
goto('/app/shop');
break;
}
}
</script>

<svelte:head>
<style>
@font-face {
font-family: 'Moga';
src: url('/font/Moga.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
</style>
</svelte:head>

<div class="bottom-navigation">
<div class="create-container">
<img src="/createpop.svg" alt="Create dialogue bubble" class="create-bubble" />
<div class="nav-tabs">
<button
class="nav-item"
class:active={activeTab === 'create'}
on:click={() => navigateTo('create')}
onclick={() => navigateTo('create')}
role="tab"
aria-selected={activeTab === 'create'}
>
Create
</button>
<button
class="nav-item {onboarding ? 'disabled' : 'enabled'}"
class:active={activeTab === 'explore'}
onclick={() => navigateTo('explore')}
role="tab"
aria-selected={activeTab === 'explore'}
>
Explore
{#if onboarding}
<img class="lock" src="/icons/lock.svg" alt="Lock" />
{/if}
</button>
<button
class="nav-item {onboarding ? 'disabled' : 'enabled'}"
class:active={activeTab === 'shop'}
onclick={() => navigateTo('shop')}
role="tab"
aria-selected={activeTab === 'shop'}
>
Shop
{#if onboarding}
<img class="lock" src="/icons/lock.svg" alt="Lock" />
{/if}
</button>
</div>
<div class="tray">
{#if !onboarding}
<img src="/bell-icon.svg" alt="Notification" />
{/if}
</div>
<button
class="nav-item"
class:active={activeTab === 'explore'}
on:click={() => navigateTo('explore')}
role="tab"
aria-selected={activeTab === 'explore'}
>
Explore
</button>
<button
class="nav-item"
class:active={activeTab === 'shop'}
on:click={() => navigateTo('shop')}
role="tab"
aria-selected={activeTab === 'shop'}
>
Shop
</button>
<button
class="nav-item"
class:active={activeTab === 'login'}
on:click={() => navigateTo('login')}
role="tab"
aria-selected={activeTab === 'login'}
>
LOGIN
</button>
</div>

<style>
Expand All @@ -81,21 +70,27 @@
bottom: 0;
left: 0;
right: 0;
background: #453b61;
border-top: 4px solid #ffd3a8;
background: #2D273F;
height: 137px;
padding: 0 120px;
z-index: 100;

display: flex;
align-items: center;
justify-content: space-around;
padding: 0 2rem;
z-index: 100;
justify-content: space-between;
}

.nav-tabs {
display: flex;
gap: 60px;
}

.nav-item {
font-family: 'Moga', sans-serif;
font-size: 90px;
color: white;

text-align: center;
text-box-trim: trim-both;
cursor: pointer;
transition: color 0.3s ease;
letter-spacing: -0.99px;
Expand All @@ -104,6 +99,17 @@
border: none;
padding: 0;
margin: 0;

position: relative;
}

.enabled {
color: white;
}

.disabled {
color: #7C7C7C;
pointer-events: none;
}

.nav-item.active {
Expand All @@ -113,23 +119,19 @@
.nav-item:hover {
opacity: 0.8;
}

.create-container {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
}

.create-bubble {

.lock {
position: absolute;
bottom: 100%;

bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 208px;
height: 137px;
margin-bottom: -10px;
z-index: 1;
translate: -50% 0;

z-index: 20;

width: 24px;
height: 30px;
rotate: -10deg;
}

@media (max-width: 768px) {
Expand All @@ -141,11 +143,6 @@
height: 80px;
padding: 0 1rem;
}

.create-bubble {
width: 156px;
height: 103px;
}
}

@media (max-width: 480px) {
Expand All @@ -157,10 +154,5 @@
height: 60px;
padding: 0 0.5rem;
}

.create-bubble {
width: 104px;
height: 69px;
}
}
</style>
Loading