Doop
Doop: 오픈소스 멀티플레이어 디자인 캔버스 및 AI 에이전트용 MCP
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기draw & design
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Pattern from a rule.
A drawing machine for folk art traditions. Every mark is generated from a number, so nothing in here is a stock asset — change the number and you get a hand that has never drawn before. Same seed, same drawing, forever.
Open index.html. No build step, no dependencies, no server required (a static
server is nicer — Google Fonts load over the network).
The thing this project is actually about: an art tradition is a set of rules, not a set of shapes. Warli and Gond draw many of the same subjects — a deer, a tree, a person, a border — and look nothing alike, because the rules underneath are opposite.
| Warli | Gond | Madhubani | Pattachitra | Kalamkari | Sketchbook | |
|---|---|---|---|---|---|---|
| Where | Maharashtra | Madhya Pradesh | Mithila, Bihar | Puri, Odisha | Srikalahasti, Andhra Pradesh | the original library |
| Ground | red-ochre earth wall | paper, or a saturated colour | handmade paper | chalk-primed cloth | unbleached cotton, or a dyed ground | white |
| Mark | solid white silhouette | clean outline + a signature fill | every contour double-lined, the channel hatched or filled | flat colour, heavy black contour, a bead row inside it | a pen line that swells and thins, dye stopping short of it | pen drawn twice |
| A person is | two triangles meeting at their tips | a flowing tube with joints | a profile face with one frontal fish eye | a tribhanga dancer in patterned cloth | rarely drawn; the tree of life is the subject | whatever you like |
| Wobble | almost none — it is painted with confidence | a little, brush on paper | a little, nib on paper | very little, a fine brush | almost none, a practised pen | plenty |
| Pieces | 139 | 133 | 136 | 87 | 85 | 524 |
Switching tradition in the Library dropdown swaps the whole discipline at once: its palettes, its ground, its texture, how the brush behaves, and which pieces are on offer. It is not a filter over one shared library.
Each pack is one file of generators, one of presets, one of templates, plus a
row in styles.js. Adding a seventh is the same four pieces — see
Adding a tradition.
The hand-drawn feeling isn't a style you can copy from a PNG. It's controlled imperfection: a straight line that bows slightly, a circle whose pen overshoots the join, a shape drawn twice with a small offset — or, for a tradition that paints with confidence, almost no imperfection at all and a rule about fill instead.
Clean geometry goes in, a seeded PRNG corrupts it, SVG comes out. Vector the whole way — prints, cuts on a vinyl cutter, scales to a billboard, stays a few kilobytes.
| File | What lives there |
|---|---|
engine.js | Hand — the pen. Seeded RNG plus line / curve / ellipse / rect / shape / dot, the fill engine, and fitDraw / stamp / ring / arcPts. |
icons.js | The interface icon set. 24px, stroke, currentColor. |
styles.js | The traditions: palettes, brush behaviour, ground, texture, categories. |
gens.js gens2.js gens3.js gens4.js | 118 sketchbook generators: marks, shapes, frames, nature, objects, characters, icons, ornament, patterns. |
presets*.js | 524 named sketchbook library entries — a generator locked to chosen params. |
templates.js templates2.js | 28 designed sketchbook documents, including 8 logo lockups. |
warli.js | 23 Warli generators, built on a joint-table figure skeleton. |
warli-presets.js / warli-templates.js | 139 Warli pieces · 8 Warli layouts. |
gond.js | 21 Gond generators, built on a swept-tube contour and a signature-fill system. |
gond-presets.js / gond-templates.js | 133 Gond pieces · 8 Gond layouts. |
madhubani.js | 21 Madhubani generators, built on a double-line contour with a patterned channel. Also exports the shared geometry (smooth, inset, tube, clipSeg, squeeze…) as SCRAWL.MADHUBANI, which the next two packs use. |
madhubani-presets.js / madhubani-templates.js | 136 Madhubani pieces · 8 Madhubani layouts. |
pattachitra.js | 14 Pattachitra generators, built on an enamel fill: flat colour, cloth pattern, black contour, bead row. |
pattachitra-presets.js / pattachitra-templates.js | 87 Pattachitra pieces · 8 Pattachitra layouts. |
kalamkari.js | 12 Kalamkari generators, built on a broad-nib ribbon line with the dye inset from it. |
209 generators · 1104 library pieces · 68 templates · 6 traditions.
Files is the home screen — your saved work and the template gallery, with live previews. Everything autosaves.
Library (left) opens on a tradition. Pick one from the dropdown at the top; the categories, the palette and the ground all change with it. Search it. Click to place. Right-click any tile for 60 live variants of the same generator.
Properties (right) is grouped and collapsible — position, content, colour, and The hand, which is where roughness, bend, stroke count, fill style and marker bleed live. Your open/closed choices are remembered.
Draw your own with the pen tool (P): click points, click the first point
to close.
Double-click any shape to edit its points. Handles appear on one stroke at a time — a sketchy drawing is a dozen overlapping paths, so showing every anchor at once is unusable. Click another part of the shape to switch stroke. A generated shape is frozen into plain editable paths the first time you do this — the look is identical, but the shape dials are baked in from then on. Undo puts them back. The raw SVG source is still available under right-click › Edit SVG code.
Text — press T and click, or double-click any text on the canvas to edit
it in place. A text box always hugs its own letters, so the selection matches
what you see; drag a handle to scale the type, or set the size directly.
Artboards. One file holds several boards at different sizes — design a logo once and see it on a card, a sign and a sticker. Add them from the Artboards panel; click a board's paper to make it active. Export crops to the active board.
Brand kit. Save the current palette and typefaces as your brand, lock it, and every new file and every Surprise inherits it instead of picking at random.
Groups Ctrl G · Repeat Ctrl R — radial, grid or along a line, as
real copies you can still edit. Align works between selected objects when
two or more are picked, and to the board when one is. Distribute needs three.
Text on a path — switch any text to Curve onto an arc for badges and seals; sweep and top/bottom reading are adjustable.
Print — Export › Print gives bleed, crop marks, and PDF/PNG/SVG at 150–600 dpi.
Snapping is on by default: drag something near another object's edge or
centre and it sticks, with red guides. Hold Ctrl/⌘ while dragging to ignore it.
Export is one button. It asks what you want — PNG at 1×/2×/4×, SVG, or the project file.
A generator draws into a 0–100 box, y down. Its params become the controls
in the Properties panel automatically.
def('sunface', 'Nature', 'Sun face', [
N('rays', 'Rays', 0, 30, 12), // number → slider
O('mood', 'Mood', ['calm','cross']), // option → dropdown
B('halo', 'Halo', true), // boolean → switch
], (h, p) => {
h.shape(h.ring(50, 50, 26, 26, 14), { closed: true });
for (let i = 0; i < p.rays; i++) {
const t = (i / p.rays) * Math.PI * 2;
h.line(50 + Math.cos(t) * 30, 50 + Math.sin(t) * 30,
50 + Math.cos(t) * 46, 50 + Math.sin(t) * 46);
}
if (p.halo) h.ellipse(50, 50, 48, 48, { role: 'accent' });
});
Then give it named presets so it appears in the library:
P('sunface', 'Calm sun', { rays: 12, mood: 0 }, 'weather sky');
P('sunface', 'Cross sun', { rays: 24, mood: 1, halo: 0 }, 'weather');
Roles, not colours. Draw with role: 'line' (default), 'accent' or
'fill'; fill with fill: 'fill' | 'accent' | 'line'. The app maps those to the
document palette, so every piece recolours itself when the palette changes.
fill: 'fill' resolves to the paper slot by default — use it for a hole, and
'line' for a solid dark mark.
Use h.shape() for anything fillable. It respects the user's fill style
(none / solid / hatch / cross / scribble / dots). h.curve() only outlines.
Aspect. Square-ish subjects get fitted into a square. Things meant to stretch
(frames, rules, patterns, bands) set aspect = 'free', and are then handed their
real width-over-height as p._ar so they can compensate. A free piece can also
declare place = { w, h } — the fraction of the board it wants to arrive at when
clicked out of the library, so a border is born long instead of square.
Clamp your index lookups. If you sample a polyline with
pts[Math.round(u * N)], clamp it — the variants browser feeds generators
out-of-range values on purpose.
Never step a loop by a raw parameter. for (t = 0; t < 100; t += p.gap)
hangs forever the moment gap reaches zero, and a saved file can carry any
number at all. Math.max(1, p.gap).
Watch the mark count. A generator that emits many small marks should budget
them and read h.detail (see below), or a library page of it will stall.
Four pieces. Working from gond.js is the shortest path, because it is the one
that had to invent a fill discipline from scratch.
1. mystyle.js — the generators. Same def() as above, but stamp the style
and give the pack its own key prefix:
function def(key, cat, label, params, draw) {
G[key] = { key, cat, label, params, draw, style: 'mystyle', aspect: 'square' };
}
Find the pack's one mechanism and build everything on it. Warli's is a joint
table: every pose is a list of joint positions in figure units, so a figure can
lean, scale, squeeze into a wide band or sit on a ring and still be the same
person. Gond's is a swept tube: a deer, a branch, an arm and a snake are all a
spine of [x, y, radius] pushed through one contour builder, so a body always
closes cleanly and a fill always has somewhere to live. Without that, a pack
becomes forty unrelated drawing functions and nothing in it looks related.
2. mystyle-presets.js — the library. Same P() as above, then the tail
that registers them:
const start = PRESETS.length;
NEW.forEach((e, i) => {
const g = GENS[e.gen], full = {};
g.params.forEach(pa => full[pa.k] = (e.params[pa.k] !== undefined ? e.params[pa.k] : pa.def));
e.params = full; e.cat = g.cat; e.style = g.style; e.id = 'm' + (start + i);
e.search = (e.name + ' ' + e.tags + ' ' + g.label + ' ' + g.cat).toLowerCase();
PRESETS.push(e);
});
Preset names only have to be unique within a tradition — Warli and Gond both
have a Dot border, and templates look up within their own style first.
3. mystyle-templates.js — the layouts. As below, with o.style stamped on
each one.
4. A row in styles.js:
mystyle: {
key: 'mystyle', name: 'My style', where: 'somewhere',
note: 'One sentence a user reads at the top of the library.',
palettes: [['Name', ground, pigment, accent, alt, alt2], …], // or null for the general list
hand: { rough: 0.45, bow: 0.5, passes: 1, weight: 2.2, fillMode: 'none' },
canvas: ['Post 4:5', 1080, 1350],
texture: 'grain', textureAmt: 0.12,
cats: ['Figures', 'Animals', 'Borders'],
slots: { fill: 2 }, // optional: default palette slots for new items
},
slots is optional. By default the 'fill' role paints in the paper colour,
which suits a tradition that carves light lines out of a dark ground. A
tradition with a third pigment sets slots: { fill: 2 } so every new item's
fill role uses palette slot 2 instead; Madhubani, Pattachitra and Kalamkari
all do.
Then add the three <script> tags to index.html — generators and presets
before styles.js, templates after templates2.js.
Coordinates are percentages of the canvas. p places a library preset by name,
t places text. A template's own w/h are honoured exactly — a free piece's
place hint does not override them.
add({
name: 'Flyer', desc: 'One image, one line', w: 794, h: 1123, pal: 3,
texture: 'grain', amt: 0.1,
items: [
{ p: 'Rocket', x: 30, y: 12, w: 40, h: 40 },
{ t: 'LIFT OFF', x: 8, y: 60, w: 84, h: 16, font: 'Anton', caps: 1 },
{ p: 'Dot divider', x: 40, y: 82, w: 20, h: 3, c: 1 },
]
});
Style shorthands on any item: c stroke, a accent, f fill (palette slots
0 ink, 1 accent, 2 alt, 3 alt2, 4 paper), fill fill style, op opacity,
rot rotation.
pal indexes the tradition's palette list, not the general one.
data.js, one row: ['Name', paper, ink, accent, alt, alt2]. A tradition's own
palettes go in its styles.js row instead, same shape.
Six details matter more than they look:
_sharpD emits one M per edge —
right for a drawn outline, useless as a fill or clip. _sharpContD emits the
same path as one continuous subpath._curveD runs
Catmull-Rom through the points, which turns a four-point diamond into a
circle and a forked tail into a paddle. Pushing the same point twice pulls the
curve tight against it. Gond's diamonds, stars and fish tails all rely on this.url(#tex) resolves to whichever
came first.h.detail is how big this drawing is about to be. 1 on the canvas, 0.3
for a library thumbnail. A generator that emits repeating small marks scales
its budget by it: a thousand-dot fill at 64 pixels is a grey smudge that costs
a thousand paths. Everything else can ignore it.Text stays real <text>, not outlines, so it remains editable. Export inlines
the webfont as base64 so the SVG renders anywhere.
Documents live in localStorage under scrawl.files.v2 and save automatically
(debounced). Browser storage is a few megabytes — use Export › Project file
for anything you care about. Imported SVGs over ~600KB are refused rather than
silently blowing the quota.
V select · H pan · T text · P pen · B pencil · double-click to edit points
Space+drag pan · scroll zoom · 0 fit · right-click for the context menu
Ctrl+Z / Ctrl+Shift+Z · Ctrl+D duplicate · Ctrl+A all · Ctrl+E export
Ctrl+G group · Ctrl+Shift+G ungroup · Ctrl+R repeat · Ctrl+Shift+C copy as SVG
Delete · R reroll the hand · [ ] layer order · arrows nudge
Alt+drag duplicate · Shift+resize keeps proportions · Ctrl+drag ignores snapping
It's static. Drop the folder on Netlify, Vercel, GitHub Pages, or any host. Nothing runs server-side and nothing leaves the browser.
site/ is Scrawl's marketing page, built as a painted desktop: an indigo
wall with windows outlined by hand. On a big screen the windows can be
dragged by their bars, rolled up, closed and reopened from the desktop icons
or the menus. Scrawl Paint is the main window, where the peacocks draw
themselves. On a phone, or before the script runs, the same windows stack
into one plain column.
It is plain HTML, one stylesheet, one small script and one self-hosted
variable font (Shantell Sans, SIL Open Font License, in site/fonts/).
Motion is CSS transforms and opacity only. It switches off on machines with
two cores or less (or with Save-Data on), and everything holds still for
visitors who ask for reduced motion.
Every picture is drawn by the editor's own generators, once, ahead of time.
site/build.js loads the engine and packs in Node (in the order the editor's
index.html lists them) and writes to site/art/:
draw-<tradition>.svg, a peacock in each tradition whose strokes draw
themselves on in Scrawl Paint;made-<name>.webp and thumb-<name>.webp, eight finished templates for
the Gallery;icon-<name>.webp and tool-<tradition>.webp, the desktop icons and
Paint's tools, each one a motif;wall.svg, the Warli ring painted on the desktop.The WebP files are rasterised with Playwright when it is installed. It also
fills the Rulebooks, Paint's tradition data and the library counts in
site/index.html. After adding or changing a tradition, run:
node site/build.js
and commit what it changes. A new tradition gets a rulebook and a Paint tool
with no other edit; its palette, peacock and one-line rule can be set in
TRAD at the top of build.js.
Scrawl Paint loads the real engine only when a visitor first changes a
palette, a template or the shuffle. Prices are written in the page and mirror
plan.js; when checkout pages exist, put them in CONFIG.checkout in
site/site.js and the Register button switches from the beta offer to
buying.
Serve the repository root (for GitHub Pages: deploy from the main branch,
root folder) and open /site/. Its "Open the editor" links point at ../index.html.
kalamkari-presets.js / kalamkari-templates.js | 85 Kalamkari pieces · 8 Kalamkari layouts. |
data.js | 40 general palettes, 18 canvas sizes, 32 typefaces, 9 textures, Surprise recipes. |
app.js | The editor. |
index.html | Shell and styling. |