Welcome to Hallowed Rounds
Hallowed Rounds is your golf home. You can record the rounds you've played in words and pictures, dig deep into the architecture and evolution of courses, and connect with other golfers. Membership is by invitation.
To get started:
- Open the Full Database.
- Mark the courses you've played.
- Visit My Locker to see your golf history come to life.
- Add dates, notes, ratings and photos whenever you like.
Everything else can come later.
Nothing in Hallowed Rounds is ever shared unless you choose to share it. By default, your notes, photos, ratings, and golf history are private.
Hallowed Rounds is being built carefully with a small group of passionate golfers. Thank you for helping shape it.
Upload a photo of your government ID and your handicap index. An admin reviews it once — the photo is deleted from our systems immediately after that review, whether approved or not.
ALTER TABLE public.courses ADD COLUMN IF NOT EXISTS atlas_url text;
ALTER TABLE public.courses ADD COLUMN IF NOT EXISTS article_url text;
ALTER TABLE public.courses ADD COLUMN IF NOT EXISTS logo_url text;
CREATE TABLE IF NOT EXISTS public.trade_requests (
id text PRIMARY KEY,
from_user_id uuid REFERENCES public.profiles(id) ON DELETE CASCADE,
from_club_id integer,
to_club_id integer NOT NULL,
type text DEFAULT 'trade',
status text DEFAULT 'pending',
message text,
messages text,
last_message_at timestamptz,
last_message_from uuid,
created_at timestamptz DEFAULT now()
);
ALTER TABLE public.trade_requests ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Members can read trades they are party to" ON public.trade_requests
FOR SELECT USING (
from_user_id = auth.uid() OR
to_club_id IN (
SELECT course_id FROM public.locker
WHERE user_id = auth.uid() AND is_member = true AND trade_opt_in = true
)
);
CREATE POLICY "Authenticated users can insert trades" ON public.trade_requests
FOR INSERT WITH CHECK (from_user_id = auth.uid());
CREATE POLICY "Party members can update trade status" ON public.trade_requests
FOR UPDATE USING (
from_user_id = auth.uid() OR
to_club_id IN (
SELECT course_id FROM public.locker
WHERE user_id = auth.uid() AND is_member = true AND trade_opt_in = true
)
);
-- Drop old policies if re-running DROP POLICY IF EXISTS "Auth users read ballots" ON public.ballots; DROP POLICY IF EXISTS "Admins manage ballots" ON public.ballots; DROP POLICY IF EXISTS "Auth users read ballot_courses" ON public.ballot_courses; DROP POLICY IF EXISTS "Admins manage ballot_courses" ON public.ballot_courses; DROP POLICY IF EXISTS "Users manage own votes" ON public.ballot_votes; DROP POLICY IF EXISTS "Admins read all votes" ON public.ballot_votes; DROP POLICY IF EXISTS "Users manage own panelist row" ON public.ballot_panelists; DROP POLICY IF EXISTS "Admins read all panelists" ON public.ballot_panelists; DROP POLICY IF EXISTS "Panelists manage own suggestions" ON public.ballot_suggestions; DROP POLICY IF EXISTS "Admins read all suggestions" ON public.ballot_suggestions; CREATE TABLE IF NOT EXISTS public.ballots ( id serial PRIMARY KEY, name text NOT NULL, geography text, status text NOT NULL DEFAULT 'draft', created_by uuid, created_at timestamptz DEFAULT now() ); ALTER TABLE public.ballots ENABLE ROW LEVEL SECURITY; CREATE POLICY "Auth users read ballots" ON public.ballots FOR SELECT USING (auth.uid() IS NOT NULL); CREATE POLICY "Auth users write ballots" ON public.ballots FOR INSERT WITH CHECK (auth.uid() IS NOT NULL); CREATE POLICY "Auth users update ballots" ON public.ballots FOR UPDATE USING (auth.uid() IS NOT NULL); CREATE TABLE IF NOT EXISTS public.ballot_courses ( id serial PRIMARY KEY, ballot_id integer REFERENCES public.ballots(id) ON DELETE CASCADE, course_id integer REFERENCES public.courses(id), since_year integer, UNIQUE(ballot_id, course_id) ); ALTER TABLE public.ballot_courses ENABLE ROW LEVEL SECURITY; CREATE POLICY "Auth users read ballot_courses" ON public.ballot_courses FOR SELECT USING (auth.uid() IS NOT NULL); CREATE POLICY "Auth users write ballot_courses" ON public.ballot_courses FOR INSERT WITH CHECK (auth.uid() IS NOT NULL); CREATE POLICY "Auth users delete ballot_courses" ON public.ballot_courses FOR DELETE USING (auth.uid() IS NOT NULL); CREATE TABLE IF NOT EXISTS public.ballot_votes ( id serial PRIMARY KEY, ballot_id integer REFERENCES public.ballots(id) ON DELETE CASCADE, voter_id uuid, course_id integer REFERENCES public.courses(id), tier text, updated_at timestamptz DEFAULT now(), UNIQUE(ballot_id, voter_id, course_id) ); ALTER TABLE public.ballot_votes ENABLE ROW LEVEL SECURITY; CREATE POLICY "Users manage own votes" ON public.ballot_votes FOR ALL USING (voter_id = auth.uid()) WITH CHECK (voter_id = auth.uid()); CREATE POLICY "Auth users read all votes" ON public.ballot_votes FOR SELECT USING (auth.uid() IS NOT NULL); CREATE TABLE IF NOT EXISTS public.ballot_votes_prior ( id serial PRIMARY KEY, ballot_id integer REFERENCES public.ballots(id) ON DELETE CASCADE, voter_id uuid, course_id integer REFERENCES public.courses(id), tier text, UNIQUE(ballot_id, voter_id, course_id) ); ALTER TABLE public.ballot_votes_prior ENABLE ROW LEVEL SECURITY; CREATE POLICY "Users manage own prior votes" ON public.ballot_votes_prior FOR ALL USING (voter_id = auth.uid()) WITH CHECK (voter_id = auth.uid()); CREATE POLICY "Auth users read all prior votes" ON public.ballot_votes_prior FOR SELECT USING (auth.uid() IS NOT NULL); CREATE TABLE IF NOT EXISTS public.ballot_panelists ( ballot_id integer REFERENCES public.ballots(id) ON DELETE CASCADE, user_id uuid, submitted boolean DEFAULT false, submitted_at timestamptz, PRIMARY KEY(ballot_id, user_id) ); ALTER TABLE public.ballot_panelists ENABLE ROW LEVEL SECURITY; CREATE POLICY "Users manage own panelist row" ON public.ballot_panelists FOR ALL USING (user_id = auth.uid()) WITH CHECK (user_id = auth.uid()); CREATE POLICY "Auth users read all panelists" ON public.ballot_panelists FOR SELECT USING (auth.uid() IS NOT NULL); CREATE TABLE IF NOT EXISTS public.ballot_suggestions ( id serial PRIMARY KEY, ballot_id integer REFERENCES public.ballots(id) ON DELETE CASCADE, course_id integer REFERENCES public.courses(id), suggested_by uuid, suggested_by_name text, created_at timestamptz DEFAULT now(), UNIQUE(ballot_id, course_id, suggested_by) ); ALTER TABLE public.ballot_suggestions ENABLE ROW LEVEL SECURITY; CREATE POLICY "Users manage own suggestions" ON public.ballot_suggestions FOR ALL USING (suggested_by = auth.uid()) WITH CHECK (suggested_by = auth.uid()); CREATE POLICY "Auth users read all suggestions" ON public.ballot_suggestions FOR SELECT USING (auth.uid() IS NOT NULL); -- Panelist and ballot admin designation on profiles ALTER TABLE public.profiles ADD COLUMN IF NOT EXISTS is_panelist boolean DEFAULT false; ALTER TABLE public.profiles ADD COLUMN IF NOT EXISTS is_ballot_admin boolean DEFAULT false; -- Since-year on ballot courses (run if tables already exist) ALTER TABLE public.ballot_courses ADD COLUMN IF NOT EXISTS since_year integer;