Przejdź do głównej treści

Generator Briefu Strony

Grafika Brief

Stwórz kompletny, profesjonalny brief w kilka minut

Tworzenie strony internetowej potrafi być czasochłonne — trzeba zebrać wymagania, ustalić cele, opisać funkcje, a potem ułożyć to w spójną dokumentację. Właśnie dlatego powstała ta aplikacja.

Generator Briefu Strony to proste, szybkie i wyjątkowo szczegółowe narzędzie, które pomaga uporządkować wszystkie kluczowe elementy projektu i wygenerować gotowy dokument w formacie Markdown.

Do czego służy aplikacja?

Aplikacja pozwala łatwo stworzyć:

  • profesjonalny brief dla projektanta, developera lub agencji,
  • dokumentację projektową dla zespołu IT,
  • specyfikację funkcjonalną i niefunkcjonalną strony internetowej,
  • plan projektu uwzględniający cele, grupy odbiorców, technologie i zasoby,
  • szablon, który można szybko powielać dla kolejnych realizacji.

Świetnie sprawdzi się zarówno przy małych stronach firmowych, landing page, jak i rozbudowanych serwisach czy portalach.

Jak działa?

  1. Wypełnij formularz — krok po kroku opisujesz wszystkie aspekty projektu: cele biznesowe, charakter strony, wymagania technologiczne, treści, funkcje, SEO, strukturę podstron i wiele więcej.
  2. Kliknij „Generuj brief” — aplikacja automatycznie tworzy spójny, czytelny dokument w formacie Markdown, który możesz:
    • skopiować,
    • pobrać jako plik .md,
    • wykorzystać w dowolnym narzędziu do dokumentacji lub jako podstawę umowy projektowej.
  3. Korzystaj wielokrotnie — wypełnij brief dla nowych projektów, zapisuj swoje szablony i buduj własną bibliotekę specyfikacji.

Dlaczego warto?

  • oszczędzasz czas,
  • niczego nie pominiesz — formularz uwzględnia nawet zaawansowane aspekty projektu,
  • dokument jest spójny i profesjonalny,
  • zero logowania — wszystko działa lokalnie w Twojej przeglądarce,
  • lekki, szybki i gotowy do użycia od razu.

Prywatność

Generator działa w pełni po stronie klienta — nic nie jest wysyłane na serwer.

Formularz briefu

Wypełnij pola i wygeneruj szczegółowy brief w formacie Markdown (.md).

Podstawowe

Użytkownicy i funkcje

Wymień persony lub grupy, po jednej na linię.
Jedna user story na linię.
Przykładowo: "Produkt: galeria, warianty, SKU, recenzje"

Design i treści

Technologie i wdrożenie

Jeśli brak preferencji, wpisz: brak. Można też wymienić opcje alternatywne.

E‑commerce (jeśli dotyczy)

Bezpieczeństwo, dostępność, prawo

Proces, terminy i budżet

Wynik (Markdown)

Kod po stronie przeglądarki

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/codemirror.min.css">
<link rel="stylesheet" href="http://www.dariuszrorat.ugu.pl/assets/css/codemirror/theme/universal.css">
<link rel="stylesheet" href="http://www.dariuszrorat.ugu.pl/assets/css/codemirror/themes.css">
<link type="text/css" href="http://www.dariuszrorat.ugu.pl/assets/css/bootstrap/wcag-outline.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script src="https://unpkg.com/docx@8.5.0/build/index.umd.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/codemirror.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/mode/clike/clike.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/mode/css/css.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/mode/javascript/javascript.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/mode/xml/xml.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/mode/htmlmixed/htmlmixed.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/mode/meta.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/addon/edit/matchtags.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/addon/fold/xml-fold.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/addon/edit/closetag.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/mode/markdown/markdown.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/addon/edit/matchbrackets.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/addon/edit/closebrackets.min.js"></script>
<style>
    body { padding: 1.25rem; }
    .form-section { border-radius: .5rem; padding: 1rem; box-shadow: 0 2px 6px rgba(0,0,0,.06); }
    pre.markdown-output { white-space: pre-wrap; word-wrap: break-word; }
    .small-input { font-size:.9rem; padding:.45rem .6rem }
</style>
<div id="app">
    <div class="d-flex align-items-center mb-3">
        <div>
            <h2 class="h4 mb-0">Formularz briefu</h2>
            <small class="text-muted">Wypełnij pola i wygeneruj szczegółowy brief w formacie Markdown (.md).</small>
        </div>
        <div class="ms-auto">
            <button id="loadExample" class="btn btn-outline-secondary btn-sm">Załaduj przykładowy brief</button>
        </div>
    </div>
    <div class="row g-3">
        <div class="col-lg-12">
            <div class="form-section">
                <form id="briefForm">
                    <h2 class="h6">Podstawowe</h2>
                    <div class="mb-3">
                        <label for="projectName" class="form-label">Nazwa projektu / strona</label>
                        <input type="text" id="projectName" class="form-control" placeholder="np. Sklep z rękodziełem" required>
                    </div>
                    <div class="mb-3 row">
                        <div class="col-6">
                            <label for="client" class="form-label">Klient / firma</label>
                            <input type="text" id="client" class="form-control small-input" placeholder="Nazwa firmy">
                        </div>
                        <div class="col-6">
                            <label for="contact" class="form-label">Kontakt (email / tel)</label>
                            <input type="text" id="contact" class="form-control small-input" placeholder="kontakt@firma.pl">
                        </div>
                    </div>
                    <div class="mb-3">
                        <label for="goal" class="form-label">Cel strony (krótko)</label>
                        <input type="text" id="goal" class="form-control" placeholder="np. Sprzedaż produktów, lead generation">
                    </div>
                    <div class="mb-3">
                        <label for="businessDesc" class="form-label">Krótki opis biznesowy</label>
                        <textarea id="businessDesc" class="form-control" rows="3" placeholder="Czym zajmuje się klient, co sprzedaje, wyróżniki"></textarea>
                    </div>
                    <h2 class="h6 mt-3">Użytkownicy i funkcje</h2>
                    <div class="mb-3">
                        <label for="audience" class="form-label">Grupa docelowa / persony</label>
                        <textarea id="audience" class="form-control" rows="3" placeholder="np. Persona A:...\nPersona B:..."></textarea>
                        <div class="small text-muted">Wymień persony lub grupy, po jednej na linię.</div>
                    </div>
                    <div class="mb-3">
                        <label for="userStories" class="form-label">User stories (najważniejsze)</label>
                        <textarea id="userStories" class="form-control" rows="4" placeholder="np. Jako użytkownik chcę móc dodać produkt do koszyka..."></textarea>
                        <div class="small text-muted">Jedna user story na linię.</div>
                    </div>
                    <div class="mb-3">
                        <label for="features" class="form-label">Zakres / kluczowe funkcje</label>
                        <textarea id="features" class="form-control" rows="4" placeholder="np. Sklep, blog, API integracje..."></textarea>
                    </div>
                    <div class="mb-3">
                        <label for="pages" class="form-label">Szczegółowy sitemap / podstrony</label>
                        <textarea id="pages" class="form-control" rows="3" placeholder="Jedna podstrona na linię: Home, Sklep > Produkt, Koszyk, Checkout, O nas, Kontakt"></textarea>
                    </div>
                    <div class="mb-3">
                        <label for="pageDetails" class="form-label">Szczegóły podstron (opcjonalnie)</label>
                        <textarea id="pageDetails" class="form-control" rows="3" placeholder="np. Strona Produkt: galeria, warianty, recenzje, cross-sell"></textarea>
                        <div class="small text-muted">Przykładowo: "Produkt: galeria, warianty, SKU, recenzje"</div>
                    </div>
                    <h2 class="h6 mt-3">Design i treści</h2>
                    <div class="mb-3">
                        <label for="tone" class="form-label">Ton komunikacji / styl</label>
                        <input type="text" id="tone" class="form-control" placeholder="Przyjazny, ekspercki...">
                    </div>
                    <div class="mb-3 row">
                        <div class="col-8">
                            <label for="colors" class="form-label">Paleta kolorów (hex)</label>
                            <input type="text" id="colors" class="form-control" placeholder="#0d6efd, #6c757d, #fff">
                        </div>
                        <div class="col-4">
                            <label for="typography" class="form-label">Typografika</label>
                            <input type="text" id="typography" class="form-control" placeholder="np. Inter, Roboto, sizes">
                        </div>
                    </div>
                    <div class="mb-3">
                        <label for="assets" class="form-label">Materiały / zasoby (logo, zdjęcia, copy)</label>
                        <textarea id="assets" class="form-control" rows="3" placeholder="np. Logo: logo.svg; Zdjęcia: folder /assets/photos/; Teksty: copy.docx"></textarea>
                    </div>
                    <h2 class="h6 mt-3">Technologie i wdrożenie</h2>
                    <div class="mb-3">
                        <label for="techStack" class="form-label">Preferowane technologie / stack</label>
                        <input type="text" id="techStack" class="form-control" placeholder="np. Next.js, React, Node.js, WP + WooCommerce, Laravel">
                        <div class="small text-muted">Jeśli brak preferencji, wpisz: brak. Można też wymienić opcje alternatywne.</div>
                    </div>
                    <div class="mb-3 row">
                        <div class="col-6">
                            <label for="cms" class="form-label">CMS / edycja treści</label>
                            <input type="text" id="cms" class="form-control" placeholder="np. WordPress, Strapi, headless">
                        </div>
                        <div class="col-6">
                            <label for="hosting" class="form-label">Hosting / środowiska</label>
                            <input type="text" id="hosting" class="form-control" placeholder="np. Vercel, AWS, DigitalOcean; staging + prod">
                        </div>
                    </div>
                    <div class="mb-3 row">
                        <div class="col-6">
                            <label for="backend" class="form-label">Baza danych / backend</label>
                            <input type="text" id="backend" class="form-control" placeholder="np. PostgreSQL, Firebase">
                        </div>
                        <div class="col-6">
                            <label for="integrations" class="form-label">Integracje / API</label>
                            <input type="text" id="integrations" class="form-control" placeholder="np. CRM, ERP, PayU, Stripe, Poczta Polska API">
                        </div>
                    </div>
                    <div class="mb-3">
                        <label for="analytics" class="form-label">Analityka i tracking</label>
                        <input type="text" id="analytics" class="form-control" placeholder="Google Analytics 4, Hotjar, Google Tag Manager">
                    </div>
                    <h2 class="h6 mt-3">E‑commerce (jeśli dotyczy)</h2>
                    <div class="mb-3 row">
                        <div class="col-6">
                            <label for="ecommercePlatform" class="form-label">Platforma sklepu</label>
                            <input type="text" id="ecommercePlatform" class="form-control" placeholder="WooCommerce, Shopify, custom">
                        </div>
                        <div class="col-6">
                            <label for="payments" class="form-label">Płatności i dostawy</label>
                            <input type="text" id="payments" class="form-control" placeholder="PayU, Przelewy24, Stripe; Kurier XYZ">
                        </div>
                    </div>
                    <div class="mb-3">
                        <label for="productMgmt" class="form-label">Zarządzanie produktami / warianty</label>
                        <input type="text" id="productMgmt" class="form-control" placeholder="SKU, warianty, stany magazynowe, integracja ERP">
                    </div>
                    <h2 class="h6 mt-3">Bezpieczeństwo, dostępność, prawo</h2>
                    <div class="mb-3">
                        <label for="security" class="form-label">Wymagania bezpieczeństwa</label>
                        <input type="text" id="security" class="form-control" placeholder="SSL, WAF, backupy, limit rate">
                    </div>
                    <div class="mb-3">
                        <label for="accessibility" class="form-label">Dostępność (WCAG)</label>
                        <input type="text" id="accessibility" class="form-control" placeholder="np. WCAG 2.1 AA">
                    </div>
                    <div class="mb-3">
                        <label for="legal" class="form-label">Wymagania prawne / RODO / cookies</label>
                        <input type="text" id="legal" class="form-control" placeholder="Polityka prywatności, regulamin, cookie banner">
                    </div>
                    <h2 class="h6 mt-3">Proces, terminy i budżet</h2>
                    <div class="mb-3 row">
                        <div class="col-6">
                            <label for="deadline" class="form-label">Termin (wstępny)</label>
                            <input type="date" id="deadline" class="form-control">
                        </div>
                        <div class="col-6">
                            <label for="budget" class="form-label">Budżet orientacyjny</label>
                            <input type="text" id="budget" class="form-control" placeholder="np. 12 000 PLN">
                        </div>
                    </div>
                    <div class="mb-3">
                        <label for="sla" class="form-label">Model współpracy / SLA</label>
                        <input type="text" id="sla" class="form-control" placeholder="np. 3 miesiące wsparcia, czas reakcji 24h">
                    </div>
                    <div class="mb-3">
                        <label for="testing" class="form-label">Kontrola jakości / testy</label>
                        <input type="text" id="testing" class="form-control" placeholder="Unit tests, E2E, manual QA, cross-browser">
                    </div>
                    <div class="mb-3">
                        <label for="team" class="form-label">Zespół i role</label>
                        <input type="text" id="team" class="form-control" placeholder="Project manager, dev, designer, copywriter">
                    </div>
                    <div class="mb-3">
                        <label for="migration" class="form-label">Migracja treści / produktów</label>
                        <input type="text" id="migration" class="form-control" placeholder="Ilość pozycji, format źródłowy, wymagania">
                    </div>
                    <div class="mb-3">
                        <label for="notes" class="form-label">Dodatkowe uwagi</label>
                        <textarea id="notes" class="form-control" rows="3" placeholder="Inne wymagania, ograniczenia lub priorytety"></textarea>
                    </div>
                    <div class="d-flex gap-2">
                        <button type="button" id="generateBtn" class="btn btn-primary">Generuj Markdown</button>
                        <button type="button" id="previewBtn" class="btn btn-outline-primary">Podgląd HTML</button>
                        <button type="button" id="clearBtn" class="btn btn-outline-danger">Wyczyść</button>
                    </div>
                </form>
            </div>
        </div>
        <div class="col-lg-12">
            <div class="form-section h-100 d-flex flex-column">
                <div class="d-flex mb-2">
                    <h2 class="h6 mb-0">Wynik (Markdown)</h2>
                    <div class="ms-auto btn-group" role="group">
                        <button id="downloadMdBtn" class="btn btn-sm btn-secondary"><i class="bi bi-filetype-md"></i> Pobierz .md</button>
                        <button id="downloadDocxBtn" class="btn btn-sm btn-secondary"><i class="bi bi-filetype-docx"></i> Pobierz .docx</button>
                        <button id="toggleRendered" class="btn btn-sm btn-outline-secondary">Pokaż/ukryj render</button>
                    </div>
                </div>
                <textarea id="markdownOutput" class="form-control flex-grow-1 markdown-output" placeholder="Tu pojawi się wygenerowany markdown..." aria-label="Wygenerowany markdown"></textarea>
                <div id="rendered" class="mt-3" style="display:none; overflow:auto; max-height:500px; padding: .75rem; border-radius: .5rem;"></div>
            </div>
        </div>
    </div>
</div>
<script>
//CodeMirror for textarea
const myTextarea = document.getElementById('markdownOutput');
const editor = CodeMirror.fromTextArea(myTextarea, {
    lineNumbers: true,
    matchBrackets: true,
    autoCloseTags: true,
    autoCloseBrackets: true,
    mode: "text/markdown",
    indentUnit: 4,
    indentWithTabs: false,
    enterMode: "keep",
    tabMode: "shift",
    extraKeys: {
        Tab: false,
        "Shift-Tab": false
    }
});
editor.setSize(null, 600);
editor.getWrapperElement().style["font-size"] = "14px";
editor.refresh();

const { Document, Packer, Paragraph, HeadingLevel, TextRun } = window.docx;           
// References
const ids = ['projectName', 'client', 'contact', 'goal', 'businessDesc', 'audience', 'userStories', 'features', 'pages', 'pageDetails', 'tone', 'colors', 'typography', 'assets', 'techStack', 'cms', 'hosting', 'backend', 'integrations', 'analytics', 'ecommercePlatform', 'payments', 'productMgmt', 'security', 'accessibility', 'legal', 'deadline', 'budget', 'sla', 'testing', 'team', 'migration', 'notes'];
const refs = {};
ids.forEach(id => refs[id] = document.getElementById(id));

const generateBtn = document.getElementById('generateBtn');
const previewBtn = document.getElementById('previewBtn');
const clearBtn = document.getElementById('clearBtn');
const downloadMdBtn = document.getElementById('downloadMdBtn');
const downloadDocxBtn = document.getElementById('downloadDocxBtn');
const markdownOutput = document.getElementById('markdownOutput');
const rendered = document.getElementById('rendered');
const toggleRendered = document.getElementById('toggleRendered');
const loadExample = document.getElementById('loadExample');

function linesToList(text) {
    if (!text) return '';
    return text.split(/\r?\n|;/).map(s => s.trim()).filter(Boolean).map(i => `- ${i}`).join('\n');
}

function commaToList(text) {
    if (!text) return '';
    return text.split(/,|\r?\n/).map(s => s.trim()).filter(Boolean).map(i => `- ${i}`).join('\n');
}

function safe(s) {
    return (s || '').trim();
}

function generateMarkdown() {
    const md = [];
    md.push(`# ${safe(refs.projectName.value) || 'Nazwa projektu'}\n`);
    md.push(`**Klient:** ${safe(refs.client.value) || '-'}  `);
    md.push(`**Kontakt:** ${safe(refs.contact.value) || '-'}  \n`);

    if (refs.goal.value) md.push(`**Cel:** ${refs.goal.value}  \n`);
    if (refs.businessDesc.value) md.push(`**Opis biznesowy:** ${refs.businessDesc.value}  \n`);

    // Users
    md.push('## Użytkownicy i persony\n');
    md.push(linesToList(refs.audience.value) || '- Brak szczegółów');
    md.push('\n');

    md.push('## User stories\n');
    md.push(linesToList(refs.userStories.value) || '- Brak');
    md.push('\n');

    md.push('## Zakres / funkcje\n');
    md.push(linesToList(refs.features.value) || '- Brak');
    md.push('\n');

    md.push('## Sitemap / Podstrony\n');
    md.push(linesToList(refs.pages.value) || '- Brak');
    md.push('\n');

    if (refs.pageDetails.value) {
        md.push('## Szczegóły podstron\n');
        md.push(refs.pageDetails.value + '\n');
    }

    md.push('## Design i treści\n');
    if (refs.tone.value) md.push(`- Ton komunikacji: ${refs.tone.value}`);
    if (refs.colors.value) md.push(`- Paleta kolorów:\n${commaToList(refs.colors.value)}`);
    if (refs.typography.value) md.push(`- Typografika: ${refs.typography.value}`);
    if (refs.assets.value) md.push(`- Materiały i zasoby:\n${refs.assets.value}`);
    md.push('\n');

    md.push('## Technologie i wdrożenie\n');
    if (refs.techStack.value) md.push(`- Preferowany stack: ${refs.techStack.value}`);
    if (refs.cms.value) md.push(`- CMS: ${refs.cms.value}`);
    if (refs.hosting.value) md.push(`- Hosting / środowiska: ${refs.hosting.value}`);
    if (refs.backend.value) md.push(`- Backend / DB: ${refs.backend.value}`);
    if (refs.integrations.value) md.push(`- Integracje / API:\n${refs.integrations.value}`);
    if (refs.analytics.value) md.push(`- Analityka / tracking: ${refs.analytics.value}`);
    md.push('\n');

    if (refs.ecommercePlatform.value || refs.payments.value || refs.productMgmt.value) {
        md.push('## E‑commerce (szczegóły)\n');
        if (refs.ecommercePlatform.value) md.push(`- Platforma sklepu: ${refs.ecommercePlatform.value}`);
        if (refs.payments.value) md.push(`- Płatności / dostawy: ${refs.payments.value}`);
        if (refs.productMgmt.value) md.push(`- Zarządzanie produktami: ${refs.productMgmt.value}`);
        md.push('\n');
    }

    md.push('## Bezpieczeństwo, dostępność i prawo\n');
    if (refs.security.value) md.push(`- Wymagania bezpieczeństwa: ${refs.security.value}`);
    if (refs.accessibility.value) md.push(`- Dostępność: ${refs.accessibility.value}`);
    if (refs.legal.value) md.push(`- Wymagania prawne: ${refs.legal.value}`);
    md.push('\n');

    md.push('## Proces, terminy i budżet\n');
    if (refs.deadline.value) md.push(`- Termin: ${refs.deadline.value}`);
    if (refs.budget.value) md.push(`- Budżet: ${refs.budget.value}`);
    if (refs.sla.value) md.push(`- Model współpracy / SLA: ${refs.sla.value}`);
    if (refs.testing.value) md.push(`- Testy / QA: ${refs.testing.value}`);
    md.push('\n');

    md.push('## Zespół, migracja i utrzymanie\n');
    if (refs.team.value) md.push(`- Zespół: ${refs.team.value}`);
    if (refs.migration.value) md.push(`- Migracja treści: ${refs.migration.value}`);
    if (refs.notes.value) md.push(`- Dodatkowe uwagi: ${refs.notes.value}`);
    md.push('\n');

    md.push(`*Wygenerowano: ${new Date().toLocaleString()}*`);

    return md.join('\n');
}

generateBtn.addEventListener('click', () => {
    const md = generateMarkdown();
    editor.setValue(md);
    if (rendered.style.display !== 'none') rendered.innerHTML = marked.parse(md);
});

previewBtn.addEventListener('click', () => {
    const md = markdownOutput.value || generateMarkdown();
    rendered.style.display = rendered.style.display === 'none' ? 'block' : 'none';
    rendered.innerHTML = marked.parse(md);
    if (rendered.style.display !== 'none') rendered.scrollIntoView({
        behavior: 'smooth'
    });
});

toggleRendered.addEventListener('click', () => {
    if (rendered.style.display === 'none') {
        rendered.style.display = 'block';
        rendered.innerHTML = marked.parse(editor.getValue() || generateMarkdown());
    } else {
        rendered.style.display = 'none';
    }
});

function markdownToDocx(md) {
    const tokens = marked.lexer(md);
    const elements = [];

    tokens.forEach(token => {

        if (token.type === "heading") {
            elements.push(
                new Paragraph({
                    text: token.text,
                    heading: token.depth === 1
                        ? HeadingLevel.HEADING_1
                        : HeadingLevel.HEADING_2
                })
            );
        }

        else if (token.type === "paragraph") {
            elements.push(
                new Paragraph(token.text)
            );
        }

        else if (token.type === "list") {
            token.items.forEach(item => {
                elements.push(
                    new Paragraph({
                        text: item.text,
                        bullet: { level: 0 }
                    })
                );
            });
        }

        else if (token.type === "hr") {
            elements.push(
                new Paragraph({
                    children: [new TextRun("------------------------")]
                })
            );
        }
    });

    return elements;
}
    
downloadMdBtn.addEventListener('click', () => {
    const md = editor.getValue() || generateMarkdown();
    const blob = new Blob([md], {
        type: 'text/markdown;charset=utf-8'
    });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    const safeName = (refs.projectName.value || 'brief').trim().replace(/[^a-z0-9-_]/gi, '_').toLowerCase();
    a.download = `${safeName || 'brief'}.md`;
    document.body.appendChild(a);
    a.click();
    a.remove();
    URL.revokeObjectURL(url);
});

downloadDocxBtn.addEventListener('click', () => {
    const markdown = editor.getValue() || generateMarkdown();
    const safeName = (refs.projectName.value || 'brief').trim().replace(/[^a-z0-9-_]/gi, '_').toLowerCase();
    
    const doc = new Document({
        sections: [{
            children: markdownToDocx(markdown)
        }]
    });

    Packer.toBlob(doc).then(blob => {
        const link = document.createElement("a");
        link.href = URL.createObjectURL(blob);
        link.download = `${safeName || 'brief'}.docx`;
        link.click();
    });
    
});
    
clearBtn.addEventListener('click', () => {
    if (!confirm('Wyczyścić wszystkie pola?')) return;
    document.getElementById('briefForm').reset();
    editor.setValue('');
    rendered.innerHTML = '';
    rendered.style.display = 'none';
});

loadExample.addEventListener('click', () => {
    refs.projectName.value = 'Sklep z rękodziełem "RękaDzieło"';
    refs.client.value = 'RękaDzieło Sp. z o.o.';
    refs.contact.value = 'kontakt@rekadzieło.pl';
    refs.goal.value = 'Sprzedaż unikatowych produktów ręcznie robionych oraz budowanie społeczności klientów.';
    refs.businessDesc.value = 'Firma sprzedaje rękodzieło wykonane lokalnie. USP: eco materiały, limitowane serie.';
    refs.audience.value = 'Kobieta 25-45; Miłośnik rękodzieła; Klient premium';
    refs.userStories.value = 'Jako klient chcę znaleźć produkt szybko\nJako admin chcę mieć prosty panel do dodawania produktów';
    refs.features.value = 'Sklep online; Blog; Integracja newsletter; Panel klienta; Automatyczne powiadomienia e-mail';
    refs.pages.value = 'Home\nSklep\nKategoria\nProdukt\nKoszyk\nCheckout\nO nas\nBlog\nKontakt';
    refs.pageDetails.value = 'Produkt: galeria, warianty (rozmiar, kolor), opis SEO, recenzje\nCheckout: adres, płatność, VAT, polityka zwrotów';
    refs.tone.value = 'Ciepły, lifestylowy';
    refs.colors.value = '#A66F4A, #F6F1EB, #2B2B2B';
    refs.typography.value = 'Inter (nagłówki), Roboto (body)';
    refs.assets.value = 'Logo: logo.svg; Zdjęcia: /assets/photos/; Teksty: copy_v1.docx';
    refs.techStack.value = 'Next.js + React (front), Node.js (API), PostgreSQL';
    refs.cms.value = 'Headless CMS (Strapi)';
    refs.hosting.value = 'Vercel (frontend), DigitalOcean (backend), staging+prod';
    refs.backend.value = 'Node.js + PostgreSQL';
    refs.integrations.value = 'Stripe (płatności), API kuriera, CRM: HubSpot';
    refs.analytics.value = 'GA4, GTM, Hotjar';
    refs.ecommercePlatform.value = 'Custom (headless)';
    refs.payments.value = 'Stripe, PayPal; Kurier: DPD, InPost';
    refs.productMgmt.value = 'SKU, warianty, stany magazynowe przez ERP';
    refs.security.value = 'SSL, backup 24h, monitoring, WAF';
    refs.accessibility.value = 'WCAG 2.1 AA';
    refs.legal.value = 'Polityka prywatności, Regulamin sklepu, Cookie banner (zgoda)';
    refs.deadline.value = '';
    refs.budget.value = '20 000 PLN';
    refs.sla.value = '3 miesiące wsparcia, reakcja 48h';
    refs.testing.value = 'Manual QA, E2E tests (Cypress)';
    refs.team.value = 'PM, 2 dev, 1 designer, copywriter';
    refs.migration.value = 'Migracja 500 produktów z CSV';
    refs.notes.value = 'Priorytet: mobile-first; SEO podstawowe; integracja z ERP.';

    const md = generateMarkdown();
    editor.setValue(md);
    rendered.innerHTML = marked.parse(md);
    rendered.style.display = 'block';
});

// auto-generate basic markdown on blur from last textarea
refs.notes.addEventListener('blur', () => {
    editor.setValue(generateMarkdown());
});
</script>

Kod po stronie serwera

Brak kodu serwera

Ta aplikacja działa wyłącznie w przeglądarce i nie korzysta z kodu po stronie serwera.

Licencja

## BSD-3-Clause License Agreement
BSD-3-Clause
Сopyright (c) 2026 Dariusz Rorat

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
   contributors may be used to endorse or promote products derived from
   this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11 grudnia 2025 4

Kategorie

Technologie

Dziękujemy!
()

Informacja o cookies

Moja strona internetowa wykorzystuje wyłącznie niezbędne pliki cookies, które są wymagane do jej prawidłowego działania. Nie używam ciasteczek w celach marketingowych ani analitycznych. Korzystając z mojej strony, wyrażasz zgodę na stosowanie tych plików. Możesz dowiedzieć się więcej w mojej polityce prywatności.