소스 정보
- 저장소
- SkeneTechnologies/skene
- 최근 소스 활동
- 2026년 4월 11일 18:36
- 감지된 SKILL.md 언어
- 영어
- 스타
- 121
- 포크
- 13
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/SkeneTechnologies/skene --skill forms명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
Backend skills for Supabase — CRM, billing, support, and more
Run comprehensive PLG analysis on a codebase to detect tech stack, existing growth features, and revenue opportunities. Use when the user says "analyze", "scan", "audit codebase", or "find growth opportunities".
Generate context-aware implementation prompts for a selected growth loop. Use when the user says "build", "implement", "generate code", "create prompt", or "how do I build this".
SOC 직업 분류 기준
SKILL.md 표시 중
| name | forms |
| description | Form definitions, fields, submissions, and file uploads with RLS |
Configurable forms with ordered fields, submission tracking, and file uploads -- all scoped by organization with row-level security. Depends on the identity skill for organizations and users.
| Column | Type | Description |
|---|---|---|
| id | uuid | Primary key |
| org_id | uuid | FK to organizations |
| creator_id | uuid | FK to users. The user who created the form. NULL if creator was deleted |
| name | text | Human-readable form name |
| slug | text | URL-safe identifier, unique per org |
| description | text | Optional description shown to respondents |
| status | form_status | Lifecycle state: draft, active, or archived |
| submit_message | text | Confirmation message shown after submission |
| redirect_url | text | Optional URL to redirect to after submission |
| created_at | timestamptz | Row creation timestamp |
| updated_at | timestamptz | Last update timestamp (auto-set by trigger) |
| metadata | jsonb | Arbitrary JSON for form-level settings |
Unique constraint on (org_id, slug).
| Column | Type | Description |
|---|---|---|
| id | uuid | Primary key |
| org_id | uuid | FK to organizations |
| form_id | uuid | FK to form_definitions |
| label | text | Display label shown to the respondent |
| field_key | text | Machine-readable key stored in submission data JSON |
| field_type | form_field_type | Input type: text, email, number, select, multiselect, checkbox, textarea, date, or file |
| position | integer | Display order within the form. Lower values appear first |
| is_required | boolean | Whether the field must be filled before submission |
| options | jsonb | Option objects for select/multiselect fields |
| validation | jsonb | Validation rules, e.g. {"min_length": 3, "max_length": 500} |
| created_at | timestamptz | Row creation timestamp |
| updated_at | timestamptz | Last update timestamp (auto-set by trigger) |
| metadata | jsonb | Arbitrary JSON |
Unique constraint on (form_id, field_key).
| Column | Type | Description |
|---|---|---|
| id | uuid | Primary key |
| org_id | uuid | FK to organizations |
| form_id | uuid | FK to form_definitions |
| contact_id | uuid | Optional reference to a CRM contact (not enforced as FK) |
| data | jsonb | JSON object mapping field_key to submitted value |
| submitted_at | timestamptz | When the respondent submitted the form |
| ip_address | inet | IP address of the respondent |
| user_agent | text | Browser user agent string |
| created_at | timestamptz | Row creation timestamp |
| updated_at | timestamptz | Last update timestamp (auto-set by trigger) |
| metadata | jsonb | Arbitrary JSON |
| Column | Type | Description |
|---|---|---|
| id | uuid | Primary key |
| org_id | uuid | FK to organizations |
| submission_id | uuid | FK to form_submissions |
| field_id | uuid | FK to form_fields. NULL if originating field was deleted |
| file_name | text | Original file name |
| file_size | bigint | File size in bytes |
| mime_type | text | MIME type of the uploaded file |
| storage_path | text | Path within Supabase Storage |
| created_at | timestamptz | Row creation timestamp |
| updated_at | timestamptz | Last update timestamp (auto-set by trigger) |
| metadata | jsonb | Arbitrary JSON |
| Value | Description |
|---|---|
| draft | Not yet accepting submissions |
| active | Accepting submissions |
| archived | No longer accepting submissions, kept for reference |
| Value | Description |
|---|---|
| text | Single-line text input |
| Email address input | |
| number | Numeric input |
| select | Single-choice dropdown |
| multiselect | Multi-choice dropdown |
| checkbox | Boolean checkbox |
| textarea | Multi-line text input |
| date | Date picker |
| file | File upload |
All tables have RLS enabled and are scoped to the current user's organization via get_user_org_id().
List all active forms in the current organization:
SELECT fd.id, fd.name, fd.slug, fd.status,
count(fs.id) AS submission_count
FROM form_definitions fd
LEFT JOIN form_submissions fs ON fs.form_id = fd.id
WHERE fd.org_id = get_user_org_id()
AND fd.status = 'active'
GROUP BY fd.id
ORDER BY fd.name;
Get a form with its fields in display order:
SELECT fd.name AS form_name,
ff.label, ff.field_key, ff.field_type, ff.is_required, ff.position
FROM form_definitions fd
JOIN form_fields ff ON ff.form_id = fd.id
WHERE fd.slug = 'contact-us'
AND fd.org_id = get_user_org_id()
ORDER BY ff.position;
Retrieve submissions for a form with submitted values:
SELECT fs.id, fs.submitted_at, fs.data, fs.ip_address
FROM form_submissions fs
WHERE fs.form_id = '<form_id>'
AND fs.org_id = get_user_org_id()
ORDER BY fs.submitted_at DESC
LIMIT 50;
Count submissions per form grouped by day:
SELECT fd.name,
date_trunc('day', fs.submitted_at) AS day,
count(*) AS submissions
FROM form_submissions fs
JOIN form_definitions fd ON fd.id = fs.form_id
WHERE fs.org_id = get_user_org_id()
GROUP BY fd.name, day
ORDER BY day DESC;
List all uploads for a given submission:
SELECT fu.file_name, fu.file_size, fu.mime_type, fu.storage_path,
ff.label AS field_label
FROM form_uploads fu
LEFT JOIN form_fields ff ON ff.id = fu.field_id
WHERE fu.submission_id = '<submission_id>'
AND fu.org_id = get_user_org_id()
ORDER BY fu.created_at;
Calculate NPS score from survey submissions:
SELECT
count(*) FILTER (WHERE (data->>'score')::int >= 9) AS promoters,
count(*) FILTER (WHERE (data->>'score')::int BETWEEN 7 AND 8) AS passives,
count(*) FILTER (WHERE (data->>'score')::int <= 6) AS detractors,
round(
100.0 * (
count(*) FILTER (WHERE (data->>'score')::int >= 9)
- count(*) FILTER (WHERE (data->>'score')::int <= 6)
) ((), ),
) nps
form_submissions
form_id
org_id get_user_org_id();