secgames.app
← 홈으로

개발자 가이드

AI 코딩 프롬프트 →

게임을 만들고, 점수 SDK를 연동한 뒤 링크를 제출하면 됩니다. 나머지는 저희가 처리해드려요.

등록 프로세스

1

폼 제출

3sec.games/submit 에서 작성

2

URL 자동 검사

접속 가능 여부 + 중복 확인

3

검수

게임 직접 플레이, 1~3일

4

포털 등록

게임 상세 페이지 오픈

Step 1 — 점수 SDK 연동

아래 파일 중 하나를 프로젝트에 복사하고, 게임이 끝나는 시점에 submitScore()를 호출하세요.

TypeScript / React / Next.js

// src/lib/3sec-score.ts
const PORTAL_API = 'https://3sec.games/api/leaderboard';
const NAME_KEY = '3sec-player-name';
const PID_KEY = '3sec-player-id';

function getOrCreatePlayerId(): string {
  try {
    const url = new URL(window.location.href);
    const pid = url.searchParams.get('pid');
    if (pid) { localStorage.setItem(PID_KEY, pid); return pid; }
  } catch {}
  const stored = localStorage.getItem(PID_KEY);
  if (stored) return stored;
  const id = crypto.randomUUID();
  localStorage.setItem(PID_KEY, id);
  return id;
}

export async function submitScore(
  gameId: string,
  score: number
): Promise<{ personalBest: number | null }> {
  const name = localStorage.getItem(NAME_KEY) || 'Player';
  const playerId = getOrCreatePlayerId();
  const res = await fetch(PORTAL_API, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ gameId, name, score, playerId }),
  });
  if (!res.ok) {
    if (res.status === 429) throw new Error('cooldown');
    throw new Error('Submit failed');
  }
  const data = await res.json();
  return { personalBest: data.personalBest ?? null };
}

export function getPlayerName(): string {
  return localStorage.getItem(NAME_KEY) || '';
}

export function setPlayerName(name: string): void {
  localStorage.setItem(NAME_KEY, name.slice(0, 8));
}

Vanilla JavaScript

// 3sec-score.js  (Vanilla JS — type 제거 버전)
const PORTAL_API = 'https://3sec.games/api/leaderboard';
const NAME_KEY = '3sec-player-name';
const PID_KEY = '3sec-player-id';

function getOrCreatePlayerId() {
  try {
    const url = new URL(window.location.href);
    const pid = url.searchParams.get('pid');
    if (pid) { localStorage.setItem(PID_KEY, pid); return pid; }
  } catch {}
  const stored = localStorage.getItem(PID_KEY);
  if (stored) return stored;
  const id = crypto.randomUUID();
  localStorage.setItem(PID_KEY, id);
  return id;
}

async function submitScore(gameId, score) {
  const name = localStorage.getItem(NAME_KEY) || 'Player';
  const playerId = getOrCreatePlayerId();
  const res = await fetch(PORTAL_API, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ gameId, name, score, playerId }),
  });
  if (!res.ok) {
    if (res.status === 429) throw new Error('cooldown');
    throw new Error('Submit failed');
  }
  return await res.json();
}

function getPlayerName() { return localStorage.getItem(NAME_KEY) || ''; }
function setPlayerName(name) { localStorage.setItem(NAME_KEY, name.slice(0, 8)); }

사용 예시

import { submitScore, getPlayerName, setPlayerName } from '@/lib/3sec-score';

// 게임 오버 시점에 호출
async function onGameOver(finalScore: number) {
  try {
    const { personalBest } = await submitScore('your-game-id', finalScore);
    if (personalBest !== null) {
      showMessage(`최고 기록: ${personalBest}`);
    }
  } catch (e) {
    if ((e as Error).message === 'cooldown') {
      // 30초 쿨다운 — 조용히 무시하거나 안내 메시지
    }
    // 그 외 오류: 게임 진행에 영향 없게 무시
  }
}

// 플레이어 이름 (선택)
setPlayerName('Cyrus');  // 최대 8자, 리더보드 표시명
getPlayerName();          // 현재 이름 조회

Step 2 — ?pid= 파라미터

포털에서 게임을 열 때 URL에 ?pid= 가 자동으로 붙습니다. SDK가 이를 자동으로 처리하므로 별도 작업이 필요 없습니다.

단, SPA 라우터가 query param을 제거하는 경우 window.location.href에서 읽을 수 있도록 SDK 초기화 시점을 확인하세요.

Step 3 — 제출 시 필요한 정보

제출 폼에서 아래 항목을 입력합니다. AI 프롬프트로 자동 작성 →

게임 URLHTTPS로 배포된 공개 URLhttps://my-game.vercel.app
게임 이름포털에 표시될 제목Space Cleaner
한 줄 소개게임 카드 훅 문장 (최대 50자)탭 한 번으로 우주 쓰레기 청소!
게임 설명루프·목표·특징 (최대 200자)우주선을 조종해...
장르 태그최대 3개액션, 캐주얼
플랫폼해당하는 것 선택모바일, 데스크톱
한 판 소요 시간드롭다운 7개 중 선택1~3분
조작법한두 문장탭/클릭으로 발사
점수 단위숫자 뒤에 붙는 텍스트점, 층, m, Act
점수 최솟값/최댓값리더보드 유효 범위0 / 99999
브랜드 컬러게임 카드 배경 hex#1a237e
썸네일400×400 SVG/PNG URL(선택)
개발자 연락처이메일 또는 Discorddev@example.com

기술 요구사항

HTTPSHTTP는 브라우저에서 차단됨
공개 URL로그인·결제 없이 즉시 접근 가능
모바일 지원대부분의 플레이어가 모바일 사용 (강력 권장)
전체화면 강제 금지플레이어가 포털로 돌아올 수 있어야 함
오디오 자동 재생 금지첫 사용자 상호작용 후 재생 시작