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
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Database
# Example: postgresql://user:password@localhost:5432/producify
DATABASE_URL="postgresql://user:password@localhost:5432/producify"
16 changes: 12 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
# dependencies
/node_modules
/.pnp
.pnp.js
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# testing
/coverage
Expand All @@ -23,14 +28,17 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env*.local
.env
# env files (can opt-in for committing if needed)
.env*
!.env.example

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts

/app/generated/prisma
105 changes: 104 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,105 @@
# producify
# Producify
An experimental, futuristic suite of music tools.

## Features

### Beat Machine Module
An 8-step beat sequencer with AI orchestration capabilities.

**Features:**
- 8-step grid sequencer
- 11 tracks: 7 immediately playable + 4 AI-orchestrated
- Real-time playback with visual step indicator
- Tempo control (60-200 BPM)
- Metronome functionality
- 6 color themes (black, gray, white, violet, purple, blue)
- AI orchestration via "Producify" button
- Export beats as JSON
- Pure Web Audio API synthesis (no external audio files)

**Tracks:**
1. Kick - Bass drum
2. Snare - Snare drum
3. Hi-Hat - Hi-hat cymbal
4. Crash - Crash cymbal
5. Piano - Piano note
6. Heavy Synth - Bass synthesizer
7. String - String pad
8. X String ✨ - AI-generated
9. XX String ✨ - AI-generated
10. Tom ✨ - AI-generated
11. Sax ✨ - AI-generated

## Getting Started

### Prerequisites
- Node.js 20+
- PostgreSQL database (optional - for future persistence features)

### Installation

1. Clone the repository:
```bash
git clone https://github.com/bensultan1985/producify.git
cd producify
```

2. Install dependencies:
```bash
npm install
```

3. (Optional) Set up database:
```bash
cp .env.example .env
# Edit .env with your DATABASE_URL
npx prisma generate
npx prisma migrate dev
```

4. Run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

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

## Usage

1. **Create a beat pattern** - Click on the grid cells to activate steps
2. **Press Play** - Start the sequencer loop
3. **Adjust tempo** - Use the slider to change BPM
4. **Toggle metronome** - Enable click track for timing
5. **Click Producify** - AI generates patterns for tracks 8-11
6. **Edit AI tracks** - Modify the AI-generated patterns
7. **Export** - Save your beat as JSON

## Technology Stack

- **Next.js 16** - React framework with App Router
- **TypeScript** - Type-safe development
- **Tailwind CSS** - Utility-first styling
- **Prisma** - Database ORM (PostgreSQL)
- **Web Audio API** - Browser-native audio synthesis

## Learn More

To learn more about the technologies used:

- [Next.js Documentation](https://nextjs.org/docs)
- [TypeScript Documentation](https://www.typescriptlang.org/docs/)
- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
- [Prisma Documentation](https://www.prisma.io/docs)
- [Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API)

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) 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.
94 changes: 94 additions & 0 deletions app/api/orchestrate/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { NextRequest, NextResponse } from 'next/server';

// This is a mock AI orchestration endpoint
// In production, this would call an actual AI service (OpenAI, etc.)
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const { tempo, tracks } = body;

// Simulate AI processing delay
await new Promise(resolve => setTimeout(resolve, 2000));

// Generate orchestral arrangements for tracks 8-11
// This is a simple pattern generator - in production, this would use AI
const orchestratedTracks = [
{
name: 'X String',
steps: generateComplementaryPattern(tracks, 'melodic'),
},
{
name: 'XX String',
steps: generateComplementaryPattern(tracks, 'harmony'),
},
{
name: 'Tom',
steps: generateComplementaryPattern(tracks, 'rhythmic'),
},
{
name: 'Sax',
steps: generateComplementaryPattern(tracks, 'lead'),
},
];

return NextResponse.json({
success: true,
tracks: orchestratedTracks,
message: 'Orchestration complete',
});
} catch (error) {
console.error('Orchestration error:', error);
return NextResponse.json(
{ success: false, error: 'Failed to orchestrate' },
{ status: 500 }
);
}
}

// Helper function to generate complementary patterns
function generateComplementaryPattern(
existingTracks: any[],
type: 'melodic' | 'harmony' | 'rhythmic' | 'lead'
): boolean[] {
const steps = Array(8).fill(false);

// Analyze existing patterns
const kickPattern = existingTracks.find(t => t.name === 'Kick')?.steps || [];
const snarePattern = existingTracks.find(t => t.name === 'Snare')?.steps || [];

switch (type) {
case 'melodic':
// Play on off-beats
for (let i = 0; i < 8; i += 2) {
if (!kickPattern[i]) {
steps[i] = Math.random() > 0.3;
}
}
break;

case 'harmony':
// Play complementary to melodic
for (let i = 1; i < 8; i += 2) {
steps[i] = Math.random() > 0.4;
}
break;

case 'rhythmic':
// Fill in gaps in rhythm
for (let i = 0; i < 8; i++) {
if (!kickPattern[i] && !snarePattern[i]) {
steps[i] = Math.random() > 0.6;
}
}
break;

case 'lead':
// Sparse melodic lead
steps[0] = true;
steps[4] = true;
if (Math.random() > 0.5) steps[6] = true;
break;
}

return steps;
}
Loading