Huephonics - Audio visualization powered by mood color (Astro, TypeScript, Drizzle, SCSS, Vercel AI SDK).
- Node.js >= 18.0.0
- Neon PostgreSQL account (database)
- API keys for OpenAI, ElevenLabs, and UploadThing
# Install dependencies
npm install
# Copy environment template
cp .env.example .env
# Configure your .env file with your credentialsCreate a .env file with the following variables:
# Neon PostgreSQL (database)
DATABASE_URL="postgresql://user:password@host/database"
# OpenAI (for Vercel AI SDK)
OPENAI_API_KEY="sk-..."
# ElevenLabs (music generation)
ELEVENLABS_API_KEY="sk_..."
# UploadThing (file storage)
UPLOADTHING_TOKEN="..."
# Optional
VITE_APP_URL="http://localhost:5173"# Start dev server
npm run devVisit http://localhost:4321
npm run dev- Start development servernpm run build- Build for productionnpm run preview- Preview production buildnpm run astro- Run Astro CLI commandsnpm run test- Run E2E tests
src/
βββ components/ # Reusable Astro components
βββ db/ # Database client and types
β βββ initialize.ts # Drizzle client with Neon HTTP
β βββ schema.ts # Drizzle table definitions
β βββ helpers.ts # Database query helpers
β βββ validations.ts # Zod schemas
βββ layouts/ # Page layouts
β βββ Layout.astro
βββ lib/ # Utility libraries
β βββ config.ts # App configuration
β βββ content-converter.ts # Markdown/HTML conversion
β βββ dom-utils.ts # DOM manipulation
βββ pages/ # Routes and pages
β βββ api/ # API endpoints
β βββ index.astro # Home page
βββ styles/ # SCSS stylesheets
βββ variables/ # SCSS variables and mixins
βββ components/ # Component styles
βββ pages/ # Page styles
βββ reset.scss # CSS reset
βββ global.scss # Global styles
This app uses a strict SCSS architecture:
- No inline
<style>tags in.astrofiles - All styles in external SCSS files for better maintainability
- Data attributes for modifiers (preferred over BEM)
- Semantic class names (no utility classes)
Example:
---
import '@/styles/components/button.scss';
---
<button class="btn" data-variant="primary" data-size="lg">
Click Me
</button>Database is handled by Drizzle ORM with Neon PostgreSQL. Define your schema in src/db/schema.ts:
import { pgTable, text, integer, timestamp } from 'drizzle-orm/pg-core';
export const music = pgTable('music', {
id: text('id').primaryKey(),
title: text('title'),
duration: integer('duration'),
createdAt: timestamp('created_at').defaultNow(),
});Query and mutate data using helpers in src/db/helpers.ts.
Chat and text generation powered by Vercel AI SDK.
ElevenLabs API for music generation.
UploadThing for reliable file uploads and storage.
# Install Vercel CLI
npm i -g vercel
# Deploy
vercelMake sure to set these environment variables in your Vercel project settings:
DATABASE_URLOPENAI_API_KEYELEVENLABS_API_KEYUPLOADTHING_TOKEN
import { htmlToMarkdown, markdownToHtml } from '@/lib/content-converter';
const markdown = htmlToMarkdown('<h1>Hello</h1>');
const html = markdownToHtml('# Hello');import { createRecording, getRecording, updateRecording } from '@/db/helpers';
const music = await createRecording(data);
const existing = await getRecording(id);
await updateRecording(id, updates);MIT