Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
34 changes: 28 additions & 6 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,13 +1,35 @@
NODE_ENV=development
NEXT_PUBLIC_NODE_ENV=development

NEXT_PUBLIC_SUPABASE_BUCKET_NAME=
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
# MySQL database
DATABASE_URL=mysql://user:password@localhost:3306/devpulse

# NextAuth
NEXTAUTH_SECRET=
NEXTAUTH_URL=http://localhost:3000

# OAuth providers (optional)
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=
AZURE_AD_CLIENT_ID=
AZURE_AD_CLIENT_SECRET=
AZURE_AD_TENANT_ID=

# Email (for password reset)
EMAIL_SERVER=smtp://user:pass@smtp.example.com:587
EMAIL_FROM=noreply@example.com

# Global chat conversation ID (seed with a cuid, e.g. from `npx cuid`)
GLOBAL_CONVERSATION_ID=
NEXT_PUBLIC_GLOBAL_CONVERSATION_ID=

# Cron job secret (protects POST /api/cron/cleanup-messages)
CRON_SECRET=

# hCaptcha
NEXT_PUBLIC_HCAPTCHA_SITE_KEY=

# Norton Safe Web
NEXT_PUBLIC_NORTON_SAFEWEB_SITE_VERIFICATION=

SUPABASE_ACCESS_TOKEN=
SUPABASE_PROJECT_ID=vswabkwgipyweqsabzwv
60 changes: 0 additions & 60 deletions .github/workflows/build.yml

This file was deleted.

2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,5 @@ supabase/*

yarn.lock
pnpm-lock.yaml

/app/generated/prisma
101 changes: 7 additions & 94 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,26 @@
<img src="public/images/devpulse.cover.png" alt="Screenshot of the floating console extension in action" width="600">
<img src="public/images/devpulse.cover.png" alt="Devpulse" width="600">

# devpulse

Measure and share your coding productivity with personalized leaderboards. Compare your progress with peers while keeping full control over privacy and leaderboard settings with project management features.

## Getting Started

Install the dependencies:

npm install
```

## Supabase

First by creating a supabase cloud project:

- go to [Supabase Dashboard](https://app.supabase.com)
- click `New Project`
- choose:
- Organization → (create one if needed)
- Project Name → e.g. devpulse
- Database Password → choose a secure one
- Region → pick the nearest location
- Click Create new project
- Wait a few moments for the database to be provisioned.
````

## Setup Environment

Copy the .env.example to .env

```bash
cp .env.example .env
````

# Open .env and fill in the values for:
# NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
# NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
```
and fill in the values for the environment variables.

## Development

Expand All @@ -46,80 +32,6 @@ npm run dev

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

## Database Migrations

For a brand-new Supabase project, use this flow from the repo root.

This repository now uses a squashed baseline migration for fresh installs:

- Active baseline: `supabase/migrations/20260407120000_baseline_fresh_setup.sql`

- Historical migrations archive: `supabase/migrations_archive/`

1. Login to Supabase CLI:

```bash
npx supabase login
```

2. Initialize local Supabase config (only if missing):

```bash
npx supabase init
```

3. Link this repo to your cloud project:

```bash
npx supabase link
```

You can select from the project list, or run `npx supabase link --project-ref <project-ref>`.

4. Push all migrations to the new project:

```bash
npx supabase db push
```

On a fresh project this applies only the single baseline migration.

5. (Optional) Pull remote schema changes into migrations:

```bash
npx supabase db pull
```

6. Regenerate Supabase TypeScript types after schema changes:

```bash
npx supabase gen types typescript --project-id <project-id> --schema public > app/supabase-types.ts
```

If you want to re-run the full migration chain on local development:

```bash
npx supabase db reset
```

If you need to inspect migration history, use the files in `supabase/migrations_archive/`.


## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy this Next.js app is to use the [Vercel Platform](https://vercel.com/new/clone?repository-url=https://github.com/mrepol742/devpulse) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

## Contribution Guidelines

Contributions to devpulse are welcome! Please follow these guidelines:
Expand All @@ -135,4 +47,5 @@ Contributions to devpulse are welcome! Please follow these guidelines:
Help us keep the codebase ("Devpulse") clean, stable, and maintainable.

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
50 changes: 19 additions & 31 deletions app/(public)/flex/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { timeAgo } from "@/app/utils/time";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faExternalLink } from "@fortawesome/free-solid-svg-icons";
import { Metadata } from "next/types";
import { createPublicClient } from "@/app/lib/supabase/public";
import { prisma } from "@/app/lib/prisma";

export const metadata: Metadata = {
title: "Flexes - Devpulse",
Expand Down Expand Up @@ -57,15 +57,10 @@ export const metadata: Metadata = {
};

export default async function Flexs() {
const supabase = createPublicClient();
const { data, error } = await supabase
.from("user_flexes")
.select("*")
.order("created_at", { ascending: false });

if (error) {
console.error("Error fetching flexes:", error);
}
const flexes = await prisma.userFlex.findMany({
where: { expiresAt: { gt: new Date() } },
orderBy: { createdAt: "desc" },
});

return (
<div className="min-h-screen bg-[#0a0a1a] text-white grid-bg relative">
Expand All @@ -77,16 +72,7 @@ export default async function Flexs() {
<h1 className="text-3xl font-bold text-white">Devpulse Flexes</h1>
</div>

{error && (
<div className="max-w-5xl mx-auto p-6 md:p-10 relative z-10">
<h2 className="text-2xl font-bold mb-4">Error Loading Flexes</h2>
<p className="text-gray-400 mb-6">
There was an error fetching the flexes. Please try again later.
</p>
</div>
)}

{data?.length === 0 && (
{flexes.length === 0 && (
<div className="max-w-5xl mx-auto p-6 md:p-10 relative z-10">
<h2 className="text-2xl font-bold mb-4">No Flexes Yet</h2>
<p className="text-gray-400 mb-6">
Expand All @@ -96,47 +82,49 @@ export default async function Flexs() {
</div>
)}

{data && data.length > 0 && (
{flexes.length > 0 && (
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{data.map((flex) => (
{flexes.map((flex) => (
<div
key={flex.id}
className="glass-card p-6 rounded-xl border border-white/5"
>
<div className="flex items-center justify-between">
<h3 className="text-lg font-semibold mb-2">
{flex.project_name}
{flex.projectName}
</h3>
<span className="text-sm">{timeAgo(flex.created_at)}</span>
<span className="text-sm">
{timeAgo(flex.createdAt.toISOString())}
</span>
</div>
<div className="text-sm text-gray-500 mb-4">
{flex.project_time}
{flex.projectTime}
</div>
<span className="font-bold text-xs text-gray-400">
Description:
</span>
<p className="text-gray-400 mb-2">{flex.project_description}</p>
{flex.is_open_source && (
<p className="text-gray-400 mb-2">{flex.projectDescription}</p>
{flex.isOpenSource && (
<>
<span className="font-bold text-xs text-gray-400">
Open Source:
</span>
<a
href={flex.open_source_url}
href={flex.openSourceUrl}
target="_blank"
rel="noopener noreferrer"
className="text-sm block underline hover:text-green-300 transition mb-2 truncate"
>
{flex.open_source_url}
{flex.openSourceUrl}
</a>
</>
)}
<div className="flex items-center justify-between mt-4">
<p className="text-sm text-gray-500">
Posted by {flex.user_email.split("@")[0]}
Posted by {flex.userEmail.split("@")[0]}
</p>
<a
href={flex.project_url}
href={flex.projectUrl}
target="_blank"
rel="noopener noreferrer"
>
Expand Down
Loading
Loading