A minimal web app for finding and copying Ghanaian worship lyrics for church projection software.
- 🔍 Smart Search - Fuzzy search that handles Twi characters (ɛ→e, ɔ→o, ŋ→n)
- 📋 Copy for Projection - One-click copy formatted for FreeShow/EasyWorship
- 📐 Slide Formats - Choose 2-line, 4-line, or full-verse per slide
- 📥 OpenLyrics Export - Download as standard XML format
- 📱 QR Code Share - Scan to open song on phone
- 🖨️ Print View - Clean printable lyric sheets
- 🌓 Dark Mode - Light and dark themes
- Framework: Next.js 16 (App Router)
- Styling: Tailwind CSS
- Database: Supabase (PostgreSQL)
- Fonts: Outfit + Inter
git clone https://github.com/yourusername/1co18.git
cd 1co18npm installCreate a .env.local file:
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
Run this SQL in your Supabase SQL Editor:
create table songs (
id bigint generated by default as identity primary key,
title text not null,
artist text,
lyrics text not null,
language text default 'Twi',
search_text text,
is_verified boolean default false,
created_at timestamp with time zone default now()
);
-- Normalize Twi characters for search
create or replace function normalize_twi(input text)
returns text as $$
begin
return lower(
replace(replace(replace(replace(replace(replace(
input, 'ɛ', 'e'), 'Ɛ', 'e'),
'ɔ', 'o'), 'Ɔ', 'o'),
'ŋ', 'n'), 'Ŋ', 'n')
);
end;
$$ language plpgsql immutable;
create or replace function update_search_text()
returns trigger as $$
begin
new.search_text := normalize_twi(new.title || ' ' || coalesce(new.artist, '') || ' ' || new.lyrics);
return new;
end;
$$ language plpgsql;
create trigger songs_search_text_trigger
before insert or update on songs
for each row execute function update_search_text();
alter table songs enable row level security;
create policy "Anyone can read songs" on songs for select using (true);
create policy "Anyone can insert songs" on songs for insert with check (true);npm run dev- Push your code to GitHub
- Go to vercel.com and import your repository
- Add environment variables:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEY
- Deploy!
src/
├── app/
│ ├── page.tsx # Homepage
│ ├── add/page.tsx # Add song form
│ ├── search/page.tsx # Search results
│ └── song/[id]/page.tsx # Song detail
├── components/
│ ├── SearchBar.tsx # Live search with suggestions
│ ├── CopyButton.tsx # Smart copy with format options
│ ├── DownloadButton.tsx # OpenLyrics XML download
│ ├── QRShareButton.tsx # QR code modal
│ └── PrintButton.tsx # Print-friendly view
├── lib/
│ ├── supabase.ts # Supabase client
│ └── songs.ts # Database operations
└── utils/
└── formatLyrics.ts # Lyrics formatting utilities
MIT