Files
scan-wave/.github/copilot-instructions.md
2025-07-12 21:25:04 +02:00

6.5 KiB
Raw Blame History

GitHub Copilot Instructions for This Repository

Basics: These you need to really follow!

  • If you have any questions, always ask me first!
  • Use Svelte 5 runes exclusively
  • Declare reactive state with $state(); derive values with $derived(); run side-effect logic with $effect() etc.
  • When doing client-side loading, always implement placeholders and loaders, so the UI remains responsive and layout shifts are minimized.
    • Don't use placeholders and loaders for static data like heading etc.
  • Never use supabse-js. I am using supabse-ssr and supabase client is located in:
    • client: $props.data.supabse
    • server: $locals.supabase

Do not fall back to the legacy $: label syntax or Svelte 3/4 stores! This is important!

Enforce a clean component structure

<script> comes first, followed by markup and then an optional <style> (rarely needed—prefer Tailwind). Export component props with export let … (still valid in Svelte 5). Keep each component focused on one visual/behavioural concern; split larger UIs into children. Tailwind-only styling conventions Base container: rounded-lg border border-gray-300 (or rounded-md on small items). Absolutely no shadow-* classes. Use p-4 or p-6 for internal padding, and gap-* utilities (not margin hacks) for spacing between children. Prefer neutral greys (gray-50gray-800) and a single accent palette defined in tailwind.config.js. HTML & accessibility Generate semantic elements (, , ,
, , etc.). Every interactive element must have an accessible name (aria-label, visible text, or title). Do not generate tabindex gymnastics; rely on natural DOM order. Type safety & tooling Default to <script lang="ts"> unless the file is explicitly plain JS. Always import types from @types/svelte or svelte where needed. File / folder conventions Component names are PascalCase.svelte. Collocate tests as ComponentName.test.ts beside the component. Put shared util functions in src/lib. Example pattern (reference only) svelte Copy Edit <script lang="ts"> let count = $state(0); let doubled = $derived(count * 2); $effect(() => console.log(`count is ${count}`)); </script>
count++} aria-label="Increment counter" > {count}

{doubled}

What not to do

No inline style="" attributes.

No external CSS files unless Tailwind cannot express the rule.

No class names that imply design debt (.box, .wrapper, .container-1, etc.).

Avoid non-reactive variables; if a value affects the UI, use a rune.

NEVER $: label syntax; use $state(), $derived(), and $effect().

If you want to use supabse client in the browser, it is stored in the data variable obtained from let { data } = $props();

Using on:click to listen to the click event is deprecated. Use the event attribute onclick instead

onsubmit|preventDefault={handleSubmit} is depracated, do not use it!

Loading session using page.server.ts is not needed as the session is already available in the locals object.

Do not use import { page } from '$app/stores'; as it is deprecated! Use instead: import { page } from '$app/state';

IMPORTANT: Always make sure that the client-side module are not importing secrets or are running any sensritive code that could expose secrets to the client. If any requests are needed to check sensitive infomration, create an api route and fetch data from there instead of directly in the client-side module.

The database schema in supabase is as follows: -- WARNING: This schema is for context only and is not meant to be run. -- Table order and constraints may not be valid for execution. -- WARNING: This schema is for context only and is not meant to be run. -- Table order and constraints may not be valid for execution.

CREATE TABLE public.events ( id uuid NOT NULL DEFAULT gen_random_uuid(), created_at timestamp with time zone NOT NULL DEFAULT now(), created_by uuid DEFAULT auth.uid(), name text, date date, section_id uuid, email_subject text, email_body text, sheet_id text, name_column numeric, surname_column numeric, email_column numeric, confirmation_column numeric, CONSTRAINT events_pkey PRIMARY KEY (id), CONSTRAINT events_created_by_fkey FOREIGN KEY (created_by) REFERENCES auth.users(id), CONSTRAINT events_section_id_fkey FOREIGN KEY (section_id) REFERENCES public.sections(id) ); CREATE TABLE public.events_archived ( id uuid NOT NULL DEFAULT gen_random_uuid(), created_at timestamp with time zone NOT NULL DEFAULT now(), date date, name text NOT NULL, total_participants numeric, scanned_participants numeric, section_id uuid, CONSTRAINT events_archived_pkey PRIMARY KEY (id), CONSTRAINT events_archived_section_id_fkey FOREIGN KEY (section_id) REFERENCES public.sections(id) ); CREATE TABLE public.participants ( id uuid NOT NULL DEFAULT gen_random_uuid(), created_at timestamp with time zone NOT NULL DEFAULT now(), created_by uuid DEFAULT auth.uid(), event uuid, name text, surname text, email text, scanned boolean DEFAULT false, scanned_at timestamp with time zone, scanned_by uuid, section_id uuid, email_sent boolean DEFAULT false, CONSTRAINT participants_pkey PRIMARY KEY (id), CONSTRAINT participants_created_by_fkey FOREIGN KEY (created_by) REFERENCES auth.users(id), CONSTRAINT participants_event_fkey FOREIGN KEY (event) REFERENCES public.events(id), CONSTRAINT participants_scanned_by_fkey FOREIGN KEY (scanned_by) REFERENCES public.profiles(id), CONSTRAINT qrcodes_scanned_by_fkey FOREIGN KEY (scanned_by) REFERENCES auth.users(id), CONSTRAINT qrcodes_section_id_fkey FOREIGN KEY (section_id) REFERENCES public.sections(id) ); CREATE TABLE public.profiles ( id uuid NOT NULL, display_name text, created_at timestamp with time zone DEFAULT now(), updated_at timestamp with time zone DEFAULT now(), section_id uuid, section_position USER-DEFINED NOT NULL DEFAULT 'member'::section_posititon, CONSTRAINT profiles_pkey PRIMARY KEY (id), CONSTRAINT profiles_id_fkey FOREIGN KEY (id) REFERENCES auth.users(id), CONSTRAINT profiles_section_id_fkey FOREIGN KEY (section_id) REFERENCES public.sections(id) ); CREATE TABLE public.sections ( id uuid NOT NULL DEFAULT gen_random_uuid(), created_at timestamp with time zone NOT NULL DEFAULT now(), name text NOT NULL UNIQUE, CONSTRAINT sections_pkey PRIMARY KEY (id) );