1
0
Fork 0

chore: Port FreeSewing.dev to docusaurus

The replaces the NextJS site powering FreeSewing.dev with a Docusaurus
setup. It's part of my efforts to simplify FreeSewing's setup so we can
focus on our core value proposition.
This commit is contained in:
Joost De Cock 2024-09-28 13:13:48 +02:00
parent 497633d1d3
commit ab3204f9f1
692 changed files with 11037 additions and 20674 deletions

View file

@ -1,18 +0,0 @@
---
title: Contribute
---
Looking to contribute to FreeSewing? That's wonderful.
## Ways to contribute
There are many ways to contribute, here's some examples:
<ReadMore root='howtos/ways-to-contribute' />
## Code of Conduct
All FreeSewing contributors must respect and uphold our Code of Conduct:
<ReadMore root='guides/code-of-conduct' />

View file

@ -1,101 +0,0 @@
---
title: Design
---
If you are looking to use FreeSewing to design parametric sewing patterns,
below are the most relevant materials on this site for you:
## Before you start
Outlines the minimal prerequisites you should understand before you dive in, including:
- <DocsLink slug="guides/prerequisites" />
<ReadMore root="guides/prerequisites" />
## Pattern design best practices
In design as in code, there's often many different ways to accomplish the same
result. We have a list of best practices that we recommend you follow. Even if
in the end you make your own choices, we recommend you at least ready through
them once. They include:
- <DocsLink slug="guides/best-practices" />
<ReadMore root="guides/best-practices" />
## Design guide
We've so far been talking about *patterns* but what you're really be creating is a *design*.
What the difference is, and what goes into a design to generate a pattern is explained in our design guide:
- <DocsLink slug="guides/designs" />
<ReadMore root="guides/designs" />
## Pattern design tutorial
This is our pattern design tutorial. If you're new to designing patterns with
FreeSewing, following the tutorial is the fastest way to get started:
- <DocsLink slug="tutorials/pattern-design" />
<ReadMore root="tutorials/pattern-design" recurse />
## Plugin guide
FreeSewing can be extended with plugins. We provide a range of plugins that you can use.
However, if you'd like to write your own plugins, you should also read the guide on how they work:
- <DocsLink slug="guides/plugins" />
<ReadMore root="guides/plugins" />
## Common design challenges
This is a list of common challenges in designing parametric sewing patterns, and tips on how to tackle them:
- <DocsLink slug="howtos/design" />
<ReadMore root="howtos/design" />
## Common code challenges
While designing patterns in code has a lot of benefits, there might be times
where things that are intuitive on paper don't come naturally to you. This is
a list of common code challenges and how to tackle them:
- <DocsLink slug="howtos/code" />
<ReadMore root="howtos/code" />
## Core API
This is the reference documentation for FreeSewing's core library.
This is where you can look up every possible API call with examples:
- <DocsLink slug="reference/api" />
<ReadMore root="reference/api" />
## Macros
This is the reference documentation for macros provided by FreeSewing's own plugins:
- <DocsLink slug="reference/macros" />
<ReadMore root="reference/macros" />
## Snippets
This is the reference documentation for snippets provided by FreeSewing's own plugins:
- <DocsLink slug="reference/snippets" />
<ReadMore root="reference/snippets" />
## Plugins
This is the list of all plugins we provide:
- <DocsLink slug="reference/plugins" />
<ReadMore root="reference/plugins" />
<Note>
##### Missing something?
If you are missing something or have questions not covered here, the `#pattern-design` channel
on [discord.freesewing.org](https://discord.freesewing.org/) is the best place to ask questions.
</Note>

View file

@ -1,7 +0,0 @@
---
title: Pattern design best practices
---
Here is a list of best practices when designing patterns:
<ReadMore />

View file

@ -1,39 +0,0 @@
---
title: Construct paths counter-clockwise
order: 70
---
Construct your paths _counter-clockwise_ (anti-clockwise). You have to pick a direction anyway, and going
counter-clockwise is a bit of a convention.
This applies both to naming points (specifically the control points of curves)
and the order in which you define your points.
Obviously, the order in which you add points to your code needs to take a backseat
to the logic of your code. But typically what you're doing is constructing an outline
of (a part of) a garment.
So pick a point, and make your way around counter-clockwise.
When naming control points for curves, re-use the name of the point they are attached to
and add `Cp1` to the control point before and `Cp2` to the control point after the point if,
once again, you follow your path counter-clockwise.
For example:
```js
part.paths.seam = new Path()
.move(points.hemCenter)
.line(points.hemSide)
.line(points.waistSide)
.curve(points.waistSideCp2, points.armholeCp1, points.armhole)
```
<Tip>
##### This convention helps with `Path.offset()` too
Constructing a path counter-clockwise will also ensure that the path offset goes outwards
rather than inwards.
</Tip>

View file

@ -1,84 +0,0 @@
---
title: Respect draft settings
order: 40
---
Apart from the pattern options that you configure for your pattern,
all FreeSewing patterns have a set of [draft settings](/reference/settings) that can be tweaked
by the user.
While many of these will automatically be handled by FreeSewing, there are some
that you will need to take into account while developing your pattern. They are:
## Complete
The [`complete`](/reference/settings/complete) setting is a boolean that is either true or false.
Its goal is to determine whether we should draft a _complete_ pattern which
includes elements such as seam allowance lines, labels, and markings for
buttons and notches,
or if the pattern should include the part outlines only.
It is your job when developing your pattern to ensure that the pattern
checks the `complete` setting and includes or omits the appropriate elements
based on the setting's value.
## Paperless
The [`paperless`](/reference/settings/paperless) setting is a boolean that is either true or false.
A _paperless_ pattern is a pattern that has extra dimension markings so
users can trace or transfer the pattern onto fabric or paper without having
the need to print it.
It is your job when developing your pattern to ensure that the pattern
checks the `paperless` setting and includes or omits the dimensions
based on the setting's value.
## Seam allowance
The [`sa`](/reference/settings/sa) setting is a number that controls the seam allowance width.
Unless `sa` is zero, patterns are drafted with seam allowance lines included.
It is your job when developing your pattern to ensure that the pattern
checks the `sa` setting and includes or omits the seam allowance lines
based on the setting's value.
<Tip>
##### Use a multiple of `sa` for your hem allowance
Resist the temptation to use an absolute value for any seam allowance,
including at the hem.
Instead, always use a multiple of the `sa` value.
This will help to ensure that the seam allowances will scale to appropriate
values when the pattern is scaled up or down to giant or doll sizes.
</Tip>
## Example
To respect the `complete`, `paperless`, and `sa` draft settings, structure your parts as such:
```js
export default function(part) {
let { complete, sa, paperless } = part.shorthand()
// Your paths and points here
if (complete) {
// Your snippets, text, helplines and so on here
if (sa) {
// Your seam allowance here
}
if (paperless) {
// Your dimensions
}
}
return part
}
```

View file

@ -1,10 +0,0 @@
---
title: Re-use CSS classes
order: 30
---
While you can style your pattern however you want, try to re-use the
[CSS class names](/reference/css) that
are in use in our default `@freesewing/plugin-theme` plugin.
Doing so will ensure consistent styling for patterns.

View file

@ -1,17 +0,0 @@
---
title: Re-use measurements
order: 10
---
When designing patterns, re-use the measurements that are already in use as much as possible.
Nobody wins when every pattern requires its own set of measurements, or names
certain measurements differently.
<Tip>
###### See our measurements page for standard measurement names
The [measurements reference page](/reference/measurements/)
contains all our standard measurement names.
</Tip>

View file

@ -1,11 +0,0 @@
---
title: Re-use options
order: 20
---
The same arguments for re-using measurements are also (somewhat) true for options.
While your pattern may require some very specific
options, there's probably a bunch that are similar to other patterns. Re-use those names.
As in, `bicepsEase` exists. So don't go creating an `upperArmEase` option.

View file

@ -1,34 +0,0 @@
---
title: Use percentage options where possible
order: 50
---
When designing patterns, you should refrain from using absolute values.
That 6 cm ease you add might be fine for all scenarios you tested.
But, then somebody comes around who is twice your size or who is making clothes for a doll,
and things will go off the rails.
Don't be tempted to add absolute values to your patterns, as they don't scale.
Instead, embrace percentages as options.
By using values that are percentages of measurements, the values will scale
and continue to work as the measurements scale up or down.
<Tip>
##### Use the doll and giant tests
To check how well your pattern scales, you can
use the _doll_ and _giant_ tests by sampling the pattern for 3 measurements sets:
1. A set of measurements from an average person (the person)
2. A set of measurements 1/10th of an average person (the doll)
3. A set of measurements 3 times that of an average person (the giant)
A well-designed pattern will scale a factor 10 down or 3 up and still hold its shape.
If your pattern makes assumptions about size, these tests will show that.
FreeSewing's development environment provides these tests out of the box,
so you can see their results at the click of a button.
</Tip>

View file

@ -1,30 +0,0 @@
---
title: Use translation keys, not text
order: 60
---
Don't insert literal text in your patterns. Instead, insert a key that can then be translated.
For example, if you want to put "_Finish with bias tape_" on your pattern, don't be
tempted to do this:
```js
path.seam.attr("data-text", "Finish with bias tape");
```
That (English) string is now hard-coded in your pattern. As FreeSewing supports
translation out of the box, it would be a real shame not to make use of it.
Instead, insert a key to identify the string:
```js
path.seam.attr("data-text", "finishWithBiasTape");
```
This way, different strings for different languages can be associated with
the key, allowing translated text to be used.
You can find and browse the translations and available translation keys for each design in the design's
[i18n folder on GitHub][1].
[1]: https://github.com/freesewing/freesewing/tree/develop/designs/aaron/i18n

View file

@ -1,20 +0,0 @@
---
title: Code of Conduct
---
All FreeSewing contributors must respect and uphold our Code of Conduct:
<ReadMore />
<Note>
##### Attribution
This Code of Conduct is an almost verbatim copy of the [Contributor Covenant][homepage], version 2.0,
available at [http://contributor-covenant.org/version/2/0][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/2/0/
</Note>

View file

@ -1,17 +0,0 @@
---
title: Correction
order: 10
---
##### Community Impact
Use of inappropriate language or other behavior
deemed unprofessional or unwelcome in the community.
##### Consequence
A private, written warning from community leaders,
providing clarity around the nature of the violation and an
explanation of why the behavior was inappropriate.
A public apology may be requested.

View file

@ -1,10 +0,0 @@
---
title: Enforcement Guidelines
order: 60
---
Community leaders will follow these Community Impact Guidelines
in determining the consequences for any action they deem
in violation of FreeSewing's Code of Conduct:
<ReadMore />

View file

@ -1,15 +0,0 @@
---
title: Permanent ban
order: 40
---
##### Community Impact
Demonstrating a pattern of violation of
community standards, including sustained inappropriate behavior,
harassment of an individual, or aggression toward or
disparagement of classes of individuals.
##### Consequence
A permanent ban from any sort of public interaction within the community.

View file

@ -1,21 +0,0 @@
---
title: Temporary ban
order: 30
---
##### Community Impact
A serious violation of community standards,
including sustained inappropriate behavior.
##### Consequence
A temporary ban from any sort of interaction or
public communication with the community for a specified period
of time.
No public or private interaction with the people
involved, including unsolicited interaction with those enforcing
the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

View file

@ -1,20 +0,0 @@
---
title: Warning
order: 20
---
##### Community Impact
A violation through a single incident or series of actions.
##### Consequence
A warning with consequences for continued behavior.
No interaction with the people involved, including unsolicited
interaction with those enforcing the Code of Conduct, for a
specified period of time. This includes avoiding interactions
in community spaces as well as external channels like social
media.
Violating these terms may lead to a temporary or permanent ban.

View file

@ -1,14 +0,0 @@
---
title: Enforcement responsibilities
order: 30
---
Community leaders are responsible for clarifying and enforcing our standards
of acceptable behavior and will take appropriate and fair corrective action
in response to any behavior that they deem inappropriate, threatening,
offensive, or harmful.
Community leaders have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, and will communicate reasons
for moderation decisions when appropriate.

View file

@ -1,15 +0,0 @@
---
title: Enforcement
order: 50
---
Instances of abusive, harassing, or otherwise unacceptable behavior
may be reported to the community leaders responsible for enforcement:
- Joost De Cock (joost@joost.at)
- Sorcha Ní Dhubhghaill (nidhubhs@gmail.com)
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and
security of the reporter of any incident.

View file

@ -1,15 +0,0 @@
---
title: Our pledge
order: 10
---
We as members, contributors, and leaders of the FreeSewing community pledge
to make participation in our community a harassment-free experience for everyone.
Everyone, regardless of age, body size, visible or invisible disability,
ethnicity, sex characteristics, gender identity and expression, level of experience,
education, socio-economic status, nationality, personal appearance, race,
religion, or sexual identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

View file

@ -1,20 +0,0 @@
---
title: Our standards
order: 20
---
Examples of behavior that contributes to a positive environment for our community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
- Focusing on what is best not just for us as individuals, but for the overall community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others private information, such as a physical or email address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting

View file

@ -1,11 +0,0 @@
---
title: Scope
order: 40
---
This Code of Conduct applies within all FreeSewing community spaces and also applies
when an individual is officially representing the FreeSewing community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed representative
at an online or offline event.

View file

@ -1,3 +0,0 @@
---
title: Content guides
---

View file

@ -1,5 +0,0 @@
---
title: MDX Guide
---
<Fixme>Explain MDX content</Fixme>

View file

@ -1,70 +0,0 @@
---
title: Sanity Content Guide
---
FreeSewing uses Sanity content needs to be edited/written by non-technical contributors,
and for images uploaded by users, such as for their profile image and so on.
<Tldr>
You can manage FreeSewing's Sanity content at
[cms.freesewing.org](https://cms.freesewing.org/)
</Tldr>
By *content that needs to be edited/written by non-technical contributors* we mean:
- Newsletter posts
- Blog posts in all languages
- Showcase posts in all languages
## Why we use Sanity
The (historical) reason that we use a (headless) CMS for this lies with **the
showcase posts**. Our documentation is still hosted in git as MDX, and
historically this was also the case for our blog posts and showcase posts.
However, while documentation is written by contributors who are familiar with
how we work, and blog posts are typically written by Joost, showcase posts are
often provided by users of the site for whom submitting a pull request is a
steep learning curve.
So for this reason, we started using an external CMS to host the showcase
posts. And, since blog posts and showcase posts are so similar, we decided to
use this platform for both. Later, we added newsletter content to this list
because this too is sometimes provided by people not so familiar with the git
workflow.
Prior to version 3, we used a self-hosted version of
[Strapi](https://strapi.io/) for this. And while that did what we needed,
self-hosting adds workload to people and our backend systems, so it's not
without its drawbacks. Then, with the release of Strapi v4, they dropped
support for MongoDB, which was the database we are using, so we were stuck on
v3 of Strapi.
So for FreeSewing v3 we started looking for alternatives, and after trying
various solutions Sanity came out as the best solution for our needs. It's a
SaaS solution -- which is nice because it means we don't have to host anything
-- but the flip side of the coin is that as a communal open source project, we
obviously cannot afford it.
Fortunately for us, the same reasons that mean we don't have any money also
mean that Sanity took pity on us, and they agreed to waive their fees and let
us use their service free of charge. So, Sanity is now a FreeSewing sponsor,
and since everything is in place already, we also use them to host user images
because honestly it's a really nice service.
## How to manage Sanity content
As Sanity is a headless CMS, you essentially have to talk to the API to manage
your content.
Fear not though, we don't expect you to do that. The Sanity Studio is a
web-based frontend that allows you to manage the content in a web environment,
and we have an instance of it deployed at https://cms.freeseiwng.org/ that is
pre-configured to manage FreeSewing's content.
## For developers
If you're looking to learn more about how to interact with the Sanity API,
please refer to [the Sanity reference documentation](/reference/sites/sanity).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

View file

@ -1,404 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="317.5mm"
height="178.59377mm"
viewBox="0 0 317.5 178.59377"
version="1.1"
id="svg8"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
sodipodi:docname="docs.svg">
<defs
id="defs2">
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker1229"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Mend">
<path
transform="matrix(-0.4,0,0,-0.4,-4,0)"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00000003pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path1227"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible"
id="marker1201"
refX="0"
refY="0"
orient="auto"
inkscape:stockid="Arrow1Mstart">
<path
transform="matrix(0.4,0,0,0.4,4,0)"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00000003pt;stroke-opacity:1"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
id="path1199"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mend"
style="overflow:visible"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path844"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mstart"
style="overflow:visible"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path841"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00000003pt;stroke-opacity:1"
transform="matrix(0.4,0,0,0.4,4,0)"
inkscape:connector-curvature="0" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4"
inkscape:cx="631.61926"
inkscape:cy="447.13138"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="3840"
inkscape:window-height="2132"
inkscape:window-x="1080"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(492.12497,-18.620489)">
<rect
style="opacity:1;fill:#5b21b6;fill-opacity:1;stroke:none;stroke-width:3.62117767;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect815"
width="317.5"
height="178.59377"
x="-492.12497"
y="18.620489"
rx="3.4404027"
ry="3.8114519" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:28.70005989px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.15250444"
x="-328.29581"
y="63.211033"
id="text819"><tspan
sodipodi:role="line"
id="tspan817"
x="-328.29581"
y="63.211033"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;fill:#ffffff;stroke-width:2.15250444">Guides</tspan></text>
<text
id="text823"
y="99.14698"
x="-328.29581"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:28.70005989px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.15250444"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;fill:#ffffff;stroke-width:2.15250444"
y="99.14698"
x="-328.29581"
id="tspan821"
sodipodi:role="line">Howtos</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:28.70005989px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.15250444"
x="-328.29581"
y="156.04854"
id="text827"><tspan
sodipodi:role="line"
id="tspan825"
x="-328.29581"
y="156.04854"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;fill:#ffffff;stroke-width:2.15250444">Reference</tspan></text>
<text
id="text831"
y="78.169304"
x="-350.03833"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:28.70005989px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.15250444"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:end;text-anchor:end;fill:#ffffff;stroke-width:2.15250444"
y="78.169304"
x="-350.03833"
id="tspan829"
sodipodi:role="line">Tutorials</tspan></text>
<path
style="opacity:0.66500005;fill:none;stroke:#ffffff;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Mstart);marker-end:url(#Arrow1Mend)"
d="M -333.37497,35.54476 V 180.28998"
id="path833"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path1197"
d="M -198.20312,107.38283 H -468.54681"
style="opacity:0.66600001;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#marker1201);marker-end:url(#marker1229)" />
<text
id="text3411"
y="29.591507"
x="-333.36511"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.84702301px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;opacity:0.66600001;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.15250444"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;text-anchor:middle;fill:#ffffff;stroke-width:2.15250444"
y="29.591507"
x="-333.36511"
id="tspan3409"
sodipodi:role="line">discovering</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.84702301px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;opacity:0.66600001;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.15250444"
x="-107.90753"
y="-479.78055"
id="text3715"
transform="rotate(-90)"><tspan
sodipodi:role="line"
id="tspan3713"
x="-107.90753"
y="-479.78055"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;text-anchor:middle;fill:#ffffff;stroke-width:2.15250444">learning</tspan></text>
<text
transform="rotate(-90)"
id="text3719"
y="-181.55731"
x="-107.90753"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.84702301px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;opacity:0.66600001;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.15250444"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;text-anchor:middle;fill:#ffffff;stroke-width:2.15250444"
y="-181.55731"
x="-107.90753"
id="tspan3717"
sodipodi:role="line">working</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.84702301px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;opacity:0.66600001;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.15250444"
x="-333.36511"
y="191.93228"
id="text4191"><tspan
sodipodi:role="line"
id="tspan4189"
x="-333.36511"
y="191.93228"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:center;text-anchor:middle;fill:#ffffff;stroke-width:2.15250444">double-checking</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.9861412px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.15250444"
x="-352.35159"
y="146.07664"
id="text4195"><tspan
sodipodi:role="line"
id="tspan4193"
x="-352.35159"
y="146.07664"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;text-align:end;text-anchor:end;fill:#ffffff;stroke-width:2.15250444">Discord &amp; Github</tspan></text>
<g
id="g4217"
transform="rotate(-4.9299968,-205.7308,220.23688)">
<text
transform="rotate(5.0638764)"
id="text4207"
y="59.988617"
x="-282.07816"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.59147549px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:#6d28d9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
xml:space="preserve"
inkscape:transform-center-x="0.49090944"
inkscape:transform-center-y="1.5321792"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Pacifico;-inkscape-font-specification:Pacifico;fill:#fde047;stroke:#6d28d9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
y="59.988617"
x="-282.07816"
id="tspan4205"
sodipodi:role="line">I want to learn about...</tspan></text>
<text
inkscape:transform-center-y="1.5321792"
inkscape:transform-center-x="0.49090944"
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.59147549px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
x="-282.07816"
y="59.988617"
id="text4211"
transform="rotate(5.0638764)"><tspan
sodipodi:role="line"
id="tspan4209"
x="-282.07816"
y="59.988617"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Pacifico;-inkscape-font-specification:Pacifico;fill:#fde047;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none">I want to learn about...</tspan></text>
</g>
<g
transform="rotate(-4.9299968,227.67374,431.71495)"
id="g4227">
<text
inkscape:transform-center-y="1.5321792"
inkscape:transform-center-x="0.49090944"
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.59147549px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:#6d28d9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
x="-282.07816"
y="59.988617"
id="text4221"
transform="rotate(5.0638764)"><tspan
sodipodi:role="line"
id="tspan4219"
x="-282.07816"
y="59.988617"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Pacifico;-inkscape-font-specification:Pacifico;fill:#fde047;stroke:#6d28d9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none">I want to do this common thing</tspan></text>
<text
transform="rotate(5.0638764)"
id="text4225"
y="59.988617"
x="-282.07816"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.59147549px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
xml:space="preserve"
inkscape:transform-center-x="0.49090944"
inkscape:transform-center-y="1.5321792"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Pacifico;-inkscape-font-specification:Pacifico;fill:#fde047;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
y="59.988617"
x="-282.07816"
id="tspan4223"
sodipodi:role="line">I want to do this common thing...</tspan></text>
</g>
<g
transform="rotate(-4.9299968,-110.62565,2101.3475)"
id="g4237">
<text
inkscape:transform-center-y="1.5321792"
inkscape:transform-center-x="0.49090944"
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.59147549px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:#6d28d9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
x="-282.07816"
y="59.988617"
id="text4231"
transform="rotate(5.0638764)"><tspan
sodipodi:role="line"
id="tspan4229"
x="-282.07816"
y="59.988617"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Pacifico;-inkscape-font-specification:Pacifico;fill:#fde047;stroke:#6d28d9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none">What even is this thing???</tspan></text>
<text
transform="rotate(5.0638764)"
id="text4235"
y="59.988617"
x="-282.07816"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.59147549px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
xml:space="preserve"
inkscape:transform-center-x="0.49090944"
inkscape:transform-center-y="1.5321792"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Pacifico;-inkscape-font-specification:Pacifico;fill:#fde047;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
y="59.988617"
x="-282.07816"
id="tspan4233"
sodipodi:role="line">What even is this thing???</tspan></text>
</g>
<g
transform="rotate(-4.9299968,1191.8402,500.31153)"
id="g4247">
<text
inkscape:transform-center-y="1.5321792"
inkscape:transform-center-x="0.49090944"
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.59147549px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:#6d28d9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
x="-282.07816"
y="59.988617"
id="text4241"
transform="rotate(5.0638764)"><tspan
sodipodi:role="line"
id="tspan4239"
x="-282.07816"
y="59.988617"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Pacifico;-inkscape-font-specification:Pacifico;fill:#fde047;stroke:#6d28d9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none">What was that parameter again...</tspan></text>
<text
transform="rotate(5.0638764)"
id="text4245"
y="59.988617"
x="-282.07816"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.59147549px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
xml:space="preserve"
inkscape:transform-center-x="0.49090944"
inkscape:transform-center-y="1.5321792"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Pacifico;-inkscape-font-specification:Pacifico;fill:#fde047;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
y="59.988617"
x="-282.07816"
id="tspan4243"
sodipodi:role="line">What was that parameter again...</tspan></text>
</g>
<g
id="g4257"
transform="rotate(-4.9299968,1107.691,1893.1223)">
<text
transform="rotate(5.0638764)"
id="text4251"
y="59.988617"
x="-282.07816"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.59147549px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:#6d28d9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
xml:space="preserve"
inkscape:transform-center-x="0.49090944"
inkscape:transform-center-y="1.5321792"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Pacifico;-inkscape-font-specification:Pacifico;fill:#fde047;stroke:#6d28d9;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
y="59.988617"
x="-282.07816"
id="tspan4249"
sodipodi:role="line">I'm stuck; Help!</tspan></text>
<text
inkscape:transform-center-y="1.5321792"
inkscape:transform-center-x="0.49090944"
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.59147549px;line-height:1.25;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
x="-282.07816"
y="59.988617"
id="text4255"
transform="rotate(5.0638764)"><tspan
sodipodi:role="line"
id="tspan4253"
x="-282.07816"
y="59.988617"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Pacifico;-inkscape-font-specification:Pacifico;fill:#fde047;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none">I'm stuck; Help!</tspan></text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 22 KiB

View file

@ -1,41 +0,0 @@
---
title: How we structure our documentation
---
Whether you're writing documentation for FreeSewing or merely trying
to find what you are looking for, understanding how we structure our
documentation can help you find your feet and figure out what goes where.
## Types of documentation
Our documentation is divided into four different types:
- [**Tutorials**](/tutorials) are lessons that lead you through a series of steps to complete a project.
- [**Guides**](/guides) tell a story to further your understanding of a specific topic.
- [**Howtos**](/howtos) give you concrete steps to solve a common problem or challenge.
- [**Reference**](/reference) holds technical descriptions of the underlying technology and how to make use of it.
Each time you write documentation, you have to ask yourself: Is it a tutorial? Is it a Guide?
Is it a Howto? Or, is it Reference documentation?
If you find it hard to answer that question, the illustration below might help you figure out
where your documentation should go based on what it's trying to accomplish:
![A graphic showing a visual representation of our documentation
structure](docs.png "A visual representation of how our documentation is structured")
- Write a **Tutorial** is your aim is to help people learn the platform
- Write a **Guide** if your aim is to further people's understanding of a topic by going a bit deeper
- Write a **Howto** if your aim is to help people accomplish a task
- Write **Reference** documentation to detail how things work under the hood
- Refer people to **Discord** or **GitHub** for things that are not (yet) covered in our documentation
<Note>
##### Based on a talk by Daniele Procida
This structure is loosely based
on [this talk by Daniele Procida](https://www.youtube.com/watch?v=t4vKPhjcMZg) at
PyCon AU 2017.
</Note>

View file

@ -1,28 +0,0 @@
---
title: Guides
order: zbb
---
You can find a list of all FreeSewing guides below:
## Main sections
<ReadMore />
<Related>
##### What makes a guide a guide?
Guides tell a story to further your understanding of a specific topic.
Guides and Howtos are on a spectrum with Howtos being terse _do-this-then-that_ recipes, whereas
guides take more time to explain in-depth what is being done and why.
For more details, refer to [How we structure our documentation](/guides/docs).
</Related>
## Full list
<ReadMore recurse />

View file

@ -1,56 +0,0 @@
---
title: Code and code blocks
order: 80
---
Especially for our developer documentation, there's a lot of times we include source code
in the documentation.
You can make these look pretty by using a code block.
The basic use is to wrap your code in three backtick characters on a line:
````markdown
```
let me = 'you'
```
````
Gives you:
```text
let me = 'you'
```
This is a generic code block. But we also support syntax highlighting.
To do so, add the language specifier after the opening backticks:
````markdown
```js
let me = 'you'
```
````
To get:
```js
let me = 'you'
```
The following language codes are supported:
- `js` for JavaScript code
- `markdown` for Markdown
- `html` for HTML
- `svg` for SVG
- `bash` for Bash or shell scripts
- `mdx` for MDX
- `jsx` for JSX
- `json` for JSON
<Note>
Note that `mermaid` code blocks will be rendered as
[Mermaid](https://mermaid.js.org/) diagrams. Refer to the docs on [custom
tags](/guides/markdown/custom-components#mermaid) for an example.
</Note>

View file

@ -1,850 +0,0 @@
---
title: Custom tags
order: 90
---
The way we render Markdown on our websites is through the use of
[MDX](https://mdxjs.com/). This allows us to extend Markdown with our own
tags. These tags are custom React components.
Such custom components allow us to put things in Markdown content that would
typically require a lot more complexity.
Below is a list of custom tags that we support in our Markdown-based
documentation, both for freesewing.dev as freesewing.org.
## Summary and Availability
This is a summary of the available custom tags and where each tag
can be used.
- **sde** tags can be used in the standalone development environment
(provided by the [new-design](/reference/packages/new-design) package).
- **dev** and **org** tags can be used on the
freesewing.dev and freesewing.org sites, respectively.
- For convenience, tags with similar functionality have been grouped together.
### Text popouts
These are markdown tags used to display text in a colored _popout_ box,
to make the text stand out and to quickly convey what type of
information is being presented.
| Tag | sde | dev | org |
| ------: | :---: | :---: | :---: |
| [Comment](#comment) | X | X | X |
| [Fixme](#fixme) | X | X | X |
| [Link](#link) | X | X | X |
| [Note](#note) | X | X | X |
| [Related](#related) | X | X | X |
| [Tip](#tip) | X | X | X |
| [Tldr](#tldr) | X | X | X |
| [Warning](#warning) | X | X | X |
### Features and Formatting
These tags provide special features or ways to format content.
| Tag | sde | dev | org |
| --------------------: | :---: | :---: | :---: |
| [ControlTip](#controltip) | | X | X |
| [DocsTitle](#docstitle) | | X | X |
| [DocsLink](#docslink) | | X | X |
| [Example](#example) | | X | X |
| [Legend](#legend) | | | X* |
| [MeasieImage](#measieimage) | | | X* |
| [(Mermaid)](#mermaid) | | X | X |
| [Method](#method) | | X | |
| [StatusCode](#statuscode) | | X | |
| [Tab](#tab) | | X | X |
| [Tabs](#tabs) | | X | X |
| [Youtube](#youtube) | | X | X |
<Note>
- **Legend** is available to use only on the
[Pattern Notation Guide](https://freesewing.org/docs/about/notation) and
[On the Fold](https://freesewing.org/docs/sewing/on-the-fold)
documentation pages.
- **MeasieImage** is available to use only on the immediate subpages in the
[Measurements](https://freesewing.org/docs/measurements)
section of the documentation.
</Note>
### Documentation Generators
These tags generate documentation-related content related to designs
and documentation files.
This prevents the need to write and edit the documentation manually,
making it easier to write and to maintain when changes occur.
| Tag | sde | dev | org |
| -----------------: | :---: | :---: | :---: |
| [DesignInfo](#designinfo) | | | X* |
| [DesignMeasurements](#designmeasurements) | | | X* |
| [DesignOptions](#designoptions) | | | X* |
| [ReadMore](#readmore) | X | X | X |
<Note>
- **DesignInfo** is available to use only on an individual design's
main documentation page, for example
[Aaron A-Shirt](https://freesewing.org/docs/designs/aaron).
- **DesignMeasurements** is available to use only on an individual design's
Required Measurements documentation page, for example
[Aaron A-Shirt: Required Measurements](https://freesewing.org/docs/designs/aaron/measurements).
- **DesignMeasurements** is available to use only on an individual design
Design Options documentation page, for example
[Aaron A-Shirt: Design Options](https://freesewing.org/docs/designs/aaron/options).
</Note>
***
## Details
All custom tags are listed alphabetically below.
### Comment
Use a **Comment** when you want to illustrate something that is a personal opinion
or advice rather than the sort more neutral voice used throughout
our documentation.
| Attribute | Required? | Default | Description |
| ----:| :---: | ------- | ----------- |
| `by` | yes | | Name of the commenter |
| `hideable` | | `false` | Allows popout to be hidden |
<Tabs tabs="example, markdown">
<Tab>
<Comment by="joost">MDX is essentially Markdown + (React) components</Comment>
<Comment hideable by="Ben F.">
It can be helpful to be able to hide long comments that might take up
too much space on the page _(hideable)_
</Comment>
</Tab>
<Tab>
```markdown
<Comment by="joost">MDX is essentially Markdown + (React) components</Comment>
<Comment hideable by="Ben F.">
It can be helpful to hide long comments that might take up too much
space on the page _(hideable)_
</Comment>
</Tab>
```
</Tab>
</Tabs>
### ControlTip
The **ControlTip** tag provides a popout box containing pre-written,
formatted text describing the
[User Experience](https://freesewing.org/account/control)
account setting and explaining what it does.
<Tabs tabs="example, markdown">
<Tab>
<ControlTip />
</Tab>
<Tab>
```markdown
<ControlTip />
```
</Tab>
</Tabs>
### DesignInfo
**DesignInfo** generates a detailed web page for a given FreeSewing
design with information including line drawings, example photos,
required measurements, design options, and links to documentation.
| Attribute | Required? | Default | Description |
| ----:| :---: | ------- | ----------- |
| `design` | yes | | Name of the design |
| `docs` | | `false` | Generates content suitable for a documentation page |
<Tabs tabs="example, markdown">
<Tab>
(Please see the
[Aaron A-Shirt documentation](https://freesewing.org/docs/designs/aaron)
page for an example of this tag.)
</Tab>
<Tab>
```markdown
<DesignInfo design='aaron' docs />
```
</Tab>
</Tabs>
<Note>
Because design documentation pages are the only place this tag can
be used, you should always include the `docs` attribute when using
this tag.
(Omitting it will generate different content, less suited for
documentation.)
</Note>
### DesignMeasurements
**DesignMeasurements** generates a list of required and optional
measurements for a given FreeSewing design.
| Attribute | Required? | Default | Description |
| ----:| :---: | ------- | ----------- |
| `design` | yes | | Name of the design |
<Tabs tabs="example, markdown">
<Tab>
(Please see
[Aaron A-Shirt: Requirement Measurements](https://freesewing.org/docs/designs/aaron/measurements)
for an example of this tag.)
</Tab>
<Tab>
```markdown
<DesignMeasurements design='aaron' />
```
</Tab>
</Tabs>
### DesignOptions
**DesignOptions** generates a list of design options and settings
for a given FreeSewing design.
| Attribute | Required? | Default | Description |
| ----:| :---: | ------- | ----------- |
| `design` | yes | | Name of the design |
<Tabs tabs="example, markdown">
<Tab>
(Please see
[Aaron A-Shirt: Design Options](https://freesewing.org/docs/designs/aaron/options)
for an example of this tag.)
</Tab>
<Tab>
```markdown
<DesignOptions design='aaron' />
```
</Tab>
</Tabs>
### DocsLink
The **DocsLink** tag creates a formatted link from a given slug
(a relative URL path).
It also looks up the title of the linked web page and uses it as
the link text.
| Attribute | Required? | Default | Description |
| ----:| :---: | ------- | ----------- |
| `slug` | yes | | Relative path for the link |
<Tabs tabs="example, markdown">
<Tab>
<DocsLink slug='guides/markdown' />
</Tab>
<Tab>
```markdown
<DocsLink slug='guides/markdown' />
```
</Tab>
</Tabs>
### DocsTitle
The **DocsTitle** tag looks up the title of a web page from a
given slug (a relative URL path) and provides the title as formatted
text.
| Attribute | Required? | Default | Description |
| ----:| :---: | ------- | ----------- |
| `slug` | yes | | Relative path of the link |
| `className` | | | CSS classes to style the text |
| `format` | | defaultFormater | Formatter used to format the text |
<Tabs tabs="example, markdown">
<Tab>
<DocsTitle slug='guides/markdown' />
</Tab>
<Tab>
```markdown
<DocsTitle slug='guides/markdown' />
```
</Tab>
</Tabs>
### Example
The **Example** tag allows you to embed a FreeSewing code example and have it rendered in the browser.
Specifically, you should write a [draft method](/reference/api/part/draft) which will then be rendered.
| Attribute | Required? | Default | Description |
| ----:| :---: | ------- | ----------- |
| `caption` | | | The caption to go under the example |
| `tutorial` | | `false` | Set this to show the Code tab first, rather than the default Preview tab. Also, additional options are made available for use in pattern examples |
| `previewFirst` | | `false` | Set this to always show the Preview tab first, regardless of the value of `tutorial` |
| `withHead` | | `false` | Set this to include a head measurement (for tutorial pattern examples) |
| `paperless` | | `false` | Set this to enable paperless mode |
| `settings` | | | A YAML string of settings to take into account |
<Tabs tabs="example, markdown">
<Tab>
<Example caption="Example of the Path.curve() method">
```js
({ Point, points, Path, paths, part }) => {
points.from = new Point(10, 20)
points.cp1 = new Point(40, 0)
points.cp2 = new Point(60, 40)
points.to = new Point(90, 20)
paths.line = new Path()
.move(points.from)
.curve(points.cp1, points.cp2, points.to)
.setText("Path.curve()", "text-sm center fill-note")
return part
}
```
</Example>
</Tab>
<Tab>
````markdown
<Example caption="Example of the Path.curve() method">
```js
({ Point, points, Path, paths, part }) => {
points.from = new Point(10, 20)
points.cp1 = new Point(40, 0)
points.cp2 = new Point(60, 40)
points.to = new Point(90, 20)
paths.line = new Path()
.move(points.from)
.curve(points.cp1, points.cp2, points.to)
.setText("Path.curve()", "text-sm center fill-note")
return part
}
```
</Example>
````
</Tab>
</Tabs>
### Fixme
Use **Fixme** to indicate something needs attention/work but you don't have time
or can't fix it now.
| Attribute | Required? | Default | Description |
| ---------: | :-------: | ------- | ----------- |
| `compact` | | `false` | Renders compact variant |
| `hideable` | | `false` | Allows popout to be hidden |
<Tabs tabs="example, markdown">
<Tab>
<Fixme>
##### ToDo
- Include link to roadmap
- Fix style for text outside paragraphs
</Fixme>
<Fixme compact>Proofread documentation _(compact)_</Fixme>
<Fixme hideable>
Proofread it a second time _(hideable)_
</Fixme>
</Tab>
<Tab>
```markdown
<Fixme>
##### ToDo
- Include link to roadmap
- Fix style for text outside paragraphs
</Fixme>
<Fixme compact>Proofread documentation _(compact)_</Fixme>
<Fixme hideable>
Proofread it a second time _(hideable)_
</Fixme>
```
</Tab>
</Tabs>
### Legend
The **Legend** tag is used to display parts from a pattern of the
Legend design (a non-public design in the FreeSewing repository
created to provide examples of pattern features).
| Attribute | Required? | Default | Description |
| ---------: | :-------: | ------- | ----------- |
| `part` | yes | | The Legend part to display |
<Tabs tabs="example, markdown">
<Tab>
(Please see
[On the fold](https://freesewing.org/docs/sewing/on-the-fold)
for an example of this tag, used to display the _cut-on-fold_ indicator
on that page.)
</Tab>
<Tab>
```markdown
<Legend part='cutonfold' />
```
</Tab>
</Tabs>
### Link
Use **Link** for URLs.
| Attribute | Required? | Default | Description |
| ---------: | :-------: | ------- | ----------- |
| `compact` | | `false` | Renders compact variant |
| `hideable` | | `false` | Allows popout to be hidden |
<Tabs tabs="example, markdown">
<Tab>
<Link>
https://freesewing.org/
</Link>
<Link compact>https://freesewing.org/ _(compact)_</Link>
<Link hideable>https://freesewing.org/ _(hideable)_</Link>
</Tab>
<Tab>
```markdown
<Link>
https://freesewing.org
</Link>
<Link compact>https://freesewing.org/ _(compact)_</Link>
<Link hideable>https://freesewing.org/ _(hideable)_</Link>
```
</Tab>
</Tabs>
### MeasieImage
**MeasieImage** will show images of a FreeSewing measurement.
The name of the directory in which the tag is used is the
measurement which will be shown.
<Tabs tabs="example, markdown">
<Tab>
(Please see
[Biceps circumference](https://freesewing.org/docs/measurements/biceps)
for an example of this tag, used to display the image showing the
biceps circumference measurement.
</Tab>
<Tab>
```markdown
<MeasieImage />
```
</Tab>
</Tabs>
### (Mermaid)
There is no actual "Mermaid" custom tag.
However, by using a fenced [code block](/guides/markdown/code-blocks)
and specifying the `mermaid` language, you can generate
[Mermaid](https://mermaid.js.org/) diagrams. Like this:
<Tabs tabs="example, markdown">
<Tab>
```mermaid
graph LR;
A--> B & C & D;
B--> A & E;
C--> A & E;
D--> A & E;
E--> B & C & D;
```
</Tab>
<Tab>
````markdown
```mermaid
graph LR;
A--> B & C & D;
B--> A & E;
C--> A & E;
D--> A & E;
E--> B & C & D;
```
````
</Tab>
</Tabs>
### Method
**Method** is used to format HTTP methods.
| Attribute | Required? | Default | Description |
| ---------: | :-------: | ------- | ----------- |
| `get` | | `false` | Display the HTTP `GET` method |
| `post` | | `false` | Display the HTTP `POST` method |
| `put` | | `false` | Display the HTTP `PUT` method |
| `delete` | | `false` | Display the HTTP `DELETE` method |
<Tabs tabs="example, markdown">
<Tab>
<Method get /><br />
<Method post />
</Tab>
<Tab>
```markdown
<Method get /><br />
<Method post />
```
</Tab>
</Tabs>
<Note>
- It is required that you provide one of the `get`, `post`, `put`,
or `delete` attributes when using **Method**.
- If more than one of those attributes is provided, only the first
one that gets processed will be used.
</Note>
### Note
Use **Note** to add something that stands out to draw attention.
| Attribute | Required? | Default | Description |
| ---------: | :-------: | ------- | ----------- |
| `compact` | | `false` | Renders compact variant |
| `hideable` | | `false` | Allows popout to be hidden |
<Tabs tabs="example, markdown">
<Tab>
<Note>
##### Also available in black
This style also comes in black, which we can all agree is the superior color
</Note>
<Note compact>And in pink _(compact)_</Note>
<Note hideable>Yet another note _(hideable)_</Note>
</Tab>
<Tab>
```markdown
<Note>
##### Also available in black
This style also comes in black, which we can all agree is the superior color
</Note>
<Note compact>And in pink _(compact)_</Note>
<Note hideable>Yet another note _(hideable)_</Note>
```
</Tab>
</Tabs>
### ReadMore
The **ReadMore** tag allows you to insert a list of child-pages.
The list is automatically generated from the pages in the subdirectories
of the documentation page's directory.
This tag is typically used on overview pages, such as our [Markdown guide](/guides/markdown) page.
| Attribute | Required? | Default | Description |
| ----:| :---: | ------- | ----------- |
| `asMenu` | | `false` | Start from the parent directory |
| `depth` | | 99 | Maximum levels to recurse |
| `recurse` | |`false` | Include all child-pages and sub-child-pages in the entire directory tree |
| `root` | | `false` | Start from the root directory |
<Tabs tabs="example, markdown">
<Tab>
<ReadMore asMenu />
</Tab>
<Tab>
```markdown
<ReadMore asMenu />
```
</Tab>
</Tabs>
### Related
Use **Related** to add something that is relevant to the current topic.
| Attribute | Required? | Default | Description |
| ---------: | :-------: | ------- | ----------- |
| `compact` | | `false` | Renders compact variant |
| `hideable` | | `false` | Allows popout to be hidden |
<Tabs tabs="example, markdown">
<Tab>
<Related>
This snippet is provided by [the annotations plugin](/reference/plugins/annotations)
</Related>
<Related compact>See [snippets](/reference/snippets) _(compact)_</Related>
<Related hideable>
See [snippets](/reference/snippets) _(hideable)_
</Related>
</Tab>
<Tab>
```markdown
<Related>
This snippet is provided by [the annotations plugin](/reference/plugins/annotations)
</Related>
<Related compact>See [snippets](/reference/snippets) _(compact)_</Related>
<Related hideable>
See [snippets](/reference/snippets) _(hideable)_
</Related>
```
</Tab>
</Tabs>
### StatusCode
**StatusCode** is used to format HTTP response status codes.
| Attribute | Required? | Default | Description |
| ---------: | :-------: | ------- | ----------- |
| `status` | yes | | The HTTP response status code to format |
<Tabs tabs="example, markdown">
<Tab>
<StatusCode status='200' /><br />
<StatusCode status='401' />
</Tab>
<Tab>
```markdown
<StatusCode status='200' /><br />
<StatusCode status='401' />
```
</Tab>
</Tabs>
### Tab
**Tabs** and **Tab** tags are used to present content in a tabbed view.
This is a view where only the active tab content is shown, with
content in other tabs hidden.
Selecting a different tab shows its contents while hiding
the others.
The **Tab** tag is used to add content for a tab.
<Tabs tabs="example, markdown">
<Tab>
<Tabs tabs="one, two">
<Tab>
Content for tab one.
</Tab>
<Tab>
This is tab two content.
</Tab>
</Tabs>
</Tab>
<Tab>
```markdown
<Tabs tabs="one, two">
<Tab>
Content for tab one.
</Tab>
<Tab>
Content for tab two.
</Tab>
</Tabs>
```
</Tab>
</Tabs>
<Note>
- The content of **Tabs** is individual **Tab** tags.
- The content of **Tab** is content for that tab.
- There should be one **Tab** for every tab defined in the `tabs` attribute of **Tabs**.
</Note>
### Tabs
**Tabs** and **Tab** tags are used to present content in a tabbed view.
This is a view where only the active tab content is shown, with
content in other tabs hidden.
Selecting a different tab shows its contents while hiding
the others.
The **Tabs** tag is used to set up the tabbed view.
It specifies how many tabs are in the view and what their names
are.
| Attribute | Required? | Default | Description |
| ---------: | :-------: | ------- | ----------- |
| `tabs` | yes | | Comma-separated list of tab names |
<Tabs tabs="example, markdown">
<Tab>
<Tabs tabs="one, two">
<Tab>
Content for tab one.
</Tab>
<Tab>
This is tab two content.
</Tab>
</Tabs>
</Tab>
<Tab>
```markdown
<Tabs tabs="one, two">
<Tab>
Content for tab one.
</Tab>
<Tab>
Content for tab two.
</Tab>
</Tabs>
```
</Tab>
</Tabs>
<Note>
- The content of **Tabs** is individual **Tab** tags.
- The content of **Tab** is content for that tab.
- There should be one **Tab** for every tab defined in the `tabs` attribute of **Tabs**.
</Note>
### Tip
Use **Tip** for, you know, tips.
| Attribute | Required? | Default | Description |
| ---------: | :-------: | ------- | ----------- |
| `compact` | | `false` | Renders compact variant |
| `hideable` | | `false` | Allows popout to be hidden |
<Tabs tabs="example, markdown">
<Tab>
<Tip>
The notches on the shoulder and sleeve parts are used to help with
alignment when attaching the sleeve.
</Tip>
<Tip compact>Align the notches so they match _(compact)_</Tip>
<Tip hideable>
Yet another tip _(hideable)_
</Tip>
</Tab>
<Tab>
```markdown
<Tip>
The notches on the shoulder and sleeve parts are used to help with
alignment when attaching the sleeve.
</Tip>
<Tip compact>Align the notches so they match _(compact)_</Tip>
<Tip hideable>
Yet another tip _(hideable)_
</Tip>
```
</Tab>
</Tabs>
### Tldr
"TL;DR" stands for "Too long; didn't read", and the **Tldr** tag used
to provide a short summary for readers who might not want to read
the full text.
| Attribute | Required? | Default | Description |
| ---------: | :-------: | ------- | ----------- |
| `compact` | | `false` | Renders compact variant |
| `hideable` | | `false` | Allows popout to be hidden |
<Tabs tabs="example, markdown">
<Tab>
<Tldr>
This page lists all the custom tags you can use.
</Tldr>
<Tldr compact>This page lists custom tags _(compact)_</Tldr>
<Tldr hideable>
Yet another TL;DR summary _(hideable)_
</Tldr>
</Tab>
<Tab>
```markdown
<Tldr>
This page lists all the custom tags you can use.
</Tldr>
<Tldr compact>This page lists custom tags _(compact)_</Tldr>
<Tldr hideable>
Yet another TL;DR summary _(hideable)_
</Tldr>
```
</Tab>
</Tabs>
### Warning
Use **Warning** when you want to warn the reader of potential danger or unintended side-effects.
| Attribute | Required? | Default | Description |
| ---------: | :-------: | ------- | ----------- |
| `compact` | | `false` | Renders compact variant |
| `hideable` | | `false` | Allows popout to be hidden |
<Tabs tabs="example, markdown">
<Tab>
<Warning>
##### Please make a backup
Following these instructions will remove all your data
</Warning>
<Warning compact>Take it slow _(compact)_</Warning>
<Warning hideable>
Yet another warning _(hideable)_
</Warning>
</Tab>
<Tab>
```markdown
<Warning>
##### Please make a backup
Following these instructions will remove all your data
</Warning>
<Warning compact>Take it slow _(compact)_</Warning>
<Warning hideable>
Yet another warning _(hideable)_
</Warning>
```
</Tab>
</Tabs>
### YouTube
The **YouTube** tag will embed YouTube videos or YouTube playlists responsively.
| Attribute | Required? | Default | Description |
| ----:| :---: | ------- | ----------- |
| `id` | yes | | ID of the YouTube video or playlist |
| `playlist` | | `false` | Set this when embedding a playlist |
<Tabs tabs="example, markdown">
<Tab>
#### Video
<YouTube id='Rz6ShSftDlI' />
#### Playlist
<YouTube id='PL1gv5yv3DoZOFSXz7yydeV1H8m6pfwstn' playlist />
</Tab>
<Tab>
```markdown
### Video
<YouTube id='Rz6ShSftDlI' />
### Playlist
<YouTube id='PL1gv5yv3DoZOFSXz7yydeV1H8m6pfwstn' playlist />
```
</Tab>
</Tabs>

View file

@ -1,17 +0,0 @@
---
title: Markdown guide
order: 900
---
Markdown is a lightweight markup language with plain text formatting syntax.
It is designed to be easily readable by humans and computers alike.
Markdown is often used to format documentation, online comments,
or anywhere where you want rich text while using a plain text editor.
In this guide, we'll look at the following topics:
<ReadMore />
This will be enough to get you started. If you'd like to learn more,
visit [markdownguide.org](https://www.markdownguide.org/).

View file

@ -1,146 +0,0 @@
---
title: Avoiding frequent mistakes
order: zzz
---
Some things to keep in mind when working in Markdown are:
## Use remark-jargon for glossary terms
There is no need to add a _glossary_ section to documentation.
We use a plugin called [rehype-jargon][rj] to explain terms.
Information can be found at the link.
[rj]: https://github.com/freesewing/freesewing/blob/develop/packages/rehype-jargon/README.md
## Let lists be lists
Please make sure to use Markdown proper, doing things such as hardcoding
numbers for lists and using `&middot;` for bulleted lists won't be rendered
properly and will be styled differently.
Using Markdown in the same way for everything ensures the site and
documentation look clean and professional. You can use a Markdown editor
like [StackEdit](https://stackedit.io/) to preview your text.
<Note>
GitHub itself also allows working in Markdown and will give you a handy preview!
</Note>
## Create links with meaningful link text
When adding links please do not create them using a structure like:
"Link [here][yt]". Instead use relevant terms for the link text.
An example of meaningful link text is this link to a
[famous 80s pop song video][yt].
[yt]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
## Make sure your links lead where you think they do
### Linking within the same website
When you are linking within freesewing.dev or freesewing.org you can use a relative link from
the site root.
Use:
```text
/guides/markdown/frequent-mistakes
```
instead of
```text
https://freesewing.dev/guides/markdown/frequent-mistakes
```
### Linking images
Images can be put in the same folder you are working on with a link
to the filename. For example:
```markdown
This is [a picture of a banana](banana.jpg)
```
## Avoid ambiguity when listing a number of steps
If you're writing documentation that involves steps, please do not mix levels
of steps. Steps written out in documentation are there to facilitate brainless
execution. Don't be afraid to repeat yourself.
If you use substeps we want those substeps to take away ambiguity rather
than introduce it into your instructions. In the next example the substep
introduces something that ought to be done before the previous steps.
This creates confusion about when that step ought to be executed.
An example of what not to do:
```md
1. cut collar
2. cut collar stand
3. sew collar stand to collar
1. sewing staystitch collar and collar stand
4. sew collar stand to neckline
```
## Be mindful of white space and whitespace characters
Markdown syntax for white space in text is a little unintuitive.
- If you want a line break after a line but no white space between it and
the next line, you need to add two space characters at the end of the
first line.
- If you want a paragraph break with white space between the two lines,
you need to add at least one blank line after the first line.
- If you don't have two space characters at the end of the first line or
any blank lines between it and the second line, then no white space or
line break will be generated.
Instead, the two lines will be part of the same continuous paragraph in the
resulting page even though they are on two separate lines in your document.
It may be helpful to experiment and keep checking the preview or resulting
page to see how things look. Not all the empty lines and white space in your
document will render in the preview or result.
## Using custom tag components
When you're using custom tag components you want to leave an empty line before
and after the tags.
```markdown
Lorem ipsum dolor sit amet,
<Note>
consectetur adipisci elit,
</Note>
sed eiusmod tempor incidunt ut labore et dolore magna aliqua.
```
If you're using any Markdown syntax within a custom component you want to also
leave an empty line at the start and end of your component.
```markdown
Lorem ipsum dolor sit amet,
<Note>
*consectetur adipisci elit,*
</Note>
sed eiusmod tempor incidunt ut labore et dolore magna aliqua.
```
## Don't be shy to ask a friend
Learning a new language can be intimidating, whether its JavaScript, Norse, or
Markdown, but everyone in the Freesewing community is glad you're here and
helping us make the site even more awesome.
If you get lost or have a question about how to do something, feel free to come
[ask on the Discord](https://discord.freesewing.org/).
We've all had to learn Markdown at some point and would be
delighted to pass knowledge on.

View file

@ -1,26 +0,0 @@
---
title: Headings
order: 40
---
Prefix your line with a number of `#` characters to determine the header level.
```md
### This is a H3 heading
#### This is a H4 heading
##### This is a H5 heading
```
### This is a H3 heading
#### This is a H4 heading
##### This is a H5 heading
<Note>
Keep in mind that you should never use an H1 element, for that will be the page title.
</Note>

View file

@ -1,27 +0,0 @@
---
title: Images
order: 70
---
Images are like links, but you prefix them with an exclamation mark.
The part between square brackets is the image alt text.
Between the curly brackets you place the location of the image file
followed by a space and the image title between quotes.
```md
![This is the alt text](image.jpg "This is the image title")
```
![This is the alt text & title](image.jpg "This is the image title")
<Tip>
##### Images go in the same folder as your Markdown file
The convention is to always place your images in the same folder as the
text where you are including the image. That way, you just need to specify
the image name, and not the path to its location.
</Tip>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

View file

@ -1,17 +0,0 @@
---
title: Italics and bold
order: 30
---
```md
You can make text *italic* or **bold**
by wrapping it in 1 or 2 asterisk respectively.
```
You can make text _italic_ or **bold** by wrapping it in 1 or 2 asterisk respectively:
```md
Alternatively, you can also use underscores to mark _italic_ or __bold__.
```
Alternatively, you can also use underscores to mark _italic_ or **bold**.

View file

@ -1,84 +0,0 @@
---
title: Using jargon and terms
---
Jargon or terms is anything that could throw off new users.
Rather than create a glossary on every page, we use MDX to manage
jargon/terms for us. This page shows you how to use it.
<Tip compact>Think of jargon as glossary terms</Tip>
## Defining terms
To define a term, we need to establish a link between the term itself, and the documentation page that defines it.
In the most common scenario, the term is the title of the page.
For example, the title of this page is `Using jargon and terms`:
```mdx
---
title: Using jargon and terms
---
```
If we wanted to make it available as jargon, we only need to add the `jargon` frontmatter:
```mdx
---
title: Using jargon and terms
jargon: true
---
```
## Multiple terms for the same page
We can add additional terms that point to the same page by setting the `terms` in frontmatter to a comma-seperated list of terms.
For example to make both `jargon` and `term` point to this page, we can do this:
```mdx
---
title: Using jargon and terms
jargon: true
terms: jargon, term
---
```
## Terminology per site
The following pages show a list of all terminology per site:
| Site | Terminology List |
| ---- | ---------------- |
| FreeSewing.dev | [/reference/terminology](/reference/terms) |
| FreeSewing.org | [/docs/about/terminology](https://freesewing.org/docs/about/terms) |
All of the terms listed in the pages above can be used in the markdown/mdx
content of those websites.
## Using jargon terms in MDX content
To use jargon inside MDX content (like the markdown of our documentation, blog
posts, and so on), it's sufficient to emphasize the term:
```md
We are migrating from _cjs_ to _esm_ modules
```
Which renders as:
We are migrating from _cjs_ to _esm_ modules
## Using jargon terms outside MDX content
Outside MDX content -- more precisely, in React components -- you can achieve the same effect with the `Term` component:
```mjs
import { Term } from 'site/components/jargon.mjs'
export const MyComponent = () => (
<p>Look, it works here too: <Term>esm</Term></p>
)
```

View file

@ -1,15 +0,0 @@
---
title: Line breaks
order: 20
---
If you want to force a line break but not a new paragraph,
simply leave 2 spaces at the end of the line.
```md
Like
this.
```
Like
this.

View file

@ -1,39 +0,0 @@
---
title: Links
order: 60
---
Links combine square brackets for the link text with round brackets for the destination.
```md
[Like this](https://freesewing.org)
```
[Like this](https://freesewing.org)
An alternative notation allows you to include the links as such:
```md
See [the reference documentation][1] on [freesewing.dev][2]
[1]: https://freesewing.dev/reference
[2]: https://freesewing.dev/reference
```
See [the reference documentation][1] on [freesewing.dev][2]
[1]: https://freesewing.dev/reference
[2]: https://freesewing.dev/reference
You don't have to use numbers, but can also use named references.
```md
We moved the Markdown content to [our monorepo][monorepo]
[monorepo]: https://github.com/freesewing/freesewing
```
We moved the Markdown content to [our monorepo][monorepo]
[monorepo]: https://github.com/freesewing/freesewing

View file

@ -1,32 +0,0 @@
---
title: Lists
order: 50
---
To make a list, just do as you would in plain text:
```md
- a bullet
- list
- a sublist
- item
```
- a bullet
- list
- a sublist
- item
If you want an numbered list, just write numbers.
They don't even have to be the correct numbers:
```md
1. Item 1
2. Item 2
2. Item 3
```
1. Item 1
2. Item 2
3. Item 3

View file

@ -1,36 +0,0 @@
---
title: Tables
order: 70
---
If you need them, you can create tables too, using a structure as shown below:
```md
| Name | Description |
| ---- | ----------- |
| Compound | A substance composed of two or more elements. Chemically combined in definite proportions by weight |
| Mixture | Two or more substances that are not chemically united, such as air |
| Solution | A uniform mixture of varying proportions of a solvent and a solute |
```
| Name | Description |
| ---- | ----------- |
| Compound | A substance composed of two or more elements. Chemically combined in definite proportions by weight |
| Mixture | Two or more substances that are not chemically united, such as air |
| Solution | A uniform mixture of varying proportions of a solvent and a solute |
You can change the alignment of the columns by using a colon (`:`) on the line below the column title:
```md
| Align-right | Align-center |
| -----------:|:------------:|
| Compound | A substance composed of two or more elements. Chemically combined in definite proportions by weight |
| Mixture | Two or more substances that are not chemically united, such as air |
| Solution | A uniform mixture of varying proportions of a solvent and a solute |
```
| Align-right | Align-center |
| -----------:|:------------:|
| Compound | A substance composed of two or more elements. Chemically combined in definite proportions by weight |
| Mixture | Two or more substances that are not chemically united, such as air |
| Solution | A uniform mixture of varying proportions of a solvent and a solute |

View file

@ -1,16 +0,0 @@
---
title: Text and paragraphs
order: 10
---
For the most part, you can just write as you would in any other format.
```md
You can just start writing.
An empty line starts a new paragraph.
```
You can just start writing.
An empty line starts a new paragraph.

View file

@ -1,23 +0,0 @@
---
title: Plugin guide
---
Plugins allow you to extend FreeSewing with new features and functionality.
A FreeSewing plugin can extend FreeSewing in 3 different ways:
- It can [provide macros](/guides/plugins/macros), which are a way to automate a number of steps into a
single command.
- It can [hook into the pattern](/guides/plugins/hooks), which allows you to manipulate the pattern or
interact with it at various stages of it's lifecycle.
- It can [provide store methods](/guides/plugins/store), which allows you to add new ways to handle data
in the pattern, including providing a custom logger.
We have [a list of plugins](/reference/plugins/) that we maintain, but
if you can't find what you're looking for, you can write your own plugin.
If you plan on doing that or if you would like to understand how plugins work,
this guide is for you.
We'll cover the following topics:
<ReadMore />

View file

@ -1,53 +0,0 @@
---
title: Lifecycle hook methods
order: 110
---
FreeSewing plugins can provide hooks, which is a way to hook into the pattern's
lifecycle.
## Signature
To provide one or more hooks, your plugin should have a `hooks` property that
is an object where the keys are the lifecycle hook name and the value holds a
method. When the lifecycle hook is triggered, your method will be called.
```mjs
const myPlugin = {
name: 'example',
version: '0.0.1',
hooks: {
hookName: function (obj, data = {}) {
}
}
}
```
If you want to attach multiple methods to the same lifecycle hook, you can pass
them as an array:
```mjs
const myPlugin = {
name: 'example',
version: '0.0.1',
hooks: {
hookName: [
function one (obj, data = {}) { },
function two (obj, data = {}) { }
]
}
}
```
## Arguments
All lifecycle methods will receive two parameters:
- An object relevant to the lifecycle hook. See the [hooks API reference](/reference/hooks/) for details.
- Data passed when the hook was registered (optional)
## Notes
Refer to the [hooks API reference](/reference/hooks/) for a list of all
available lifecycle hooks.

View file

@ -1,13 +0,0 @@
---
title: Loading plugins
order: 140
---
Plugins can be loaded at build time and added to the design.
Or, they can be added at run time and added to an instantiated pattern.
To load a plugin at build time, it should be added to [the `plugins` key of the part configuration](/reference/api/part/config/plugins).
To load a plugin at run time, it should be loaded with a call to [`Pattern.use()`](/reference/api/pattern/use).
Please refer to the relevant documentation for more details.

View file

@ -1,46 +0,0 @@
---
title: Macro methods
order: 120
---
FreeSewing plugins can provide macros, which is a way to automate multiple
steps into a single command.
## Signature
To provide one or more macros, your plugin should have a `macros` property that
is an object where the keys are the macro name, and the value holds a method to
run when the macro is executed.
```mjs
const myPlugin = {
name: 'example',
version: '0.0.1',
macros: {
example: function(so, { log }) {
log.info('Running the example macro')
}
}
}
```
## Arguments
All macros receive two arguments:
- `so`: A plain object holding configuration object passed to the macro
- `props`: The same object as passed to the [`Part.draft()`](/reference/api/part/draft) method that you can destructure
<Note>
###### Macros take only 1 argument
When writing a macro, keep in mind that all information that needs to be passed
to a macro needs to be contained in a single argument.
Typically, you use a single plain object to configure the macro.
</Note>
## Return value
Macros do not need to return anything. If they do, it will be ignored.

View file

@ -1,57 +0,0 @@
---
title: Store methods
order: 130
---
FreeSewing plugins can provide store methods, which facilitate data handling
within a pattern.
## Signature
To provide one or more store methods, your plugin should have a `store` property that
is an array where each member is itself an array with two members:
- The first member holds the key to attach the method to (in dot notation)
- The second member holds the method to attach
```mjs
const myPlugin = {
name: 'example',
version: '0.0.1',
store: [
[
'log.panic',
function(store, ...params) {
store.setIfUnset('logs.panic', new Array())
store.push(...params)
}
]
}
}
```
## Arguments
All store methods receive at least two arguments:
- `store`: The store object itself
- `...params`: All additional plugins that were passed to the store method
## Overwriting store methods
You are allowed to overwrite existing store methods.
As it happens, this is how you should implement a custom logging solution,
by overwriting the logging methods under the store's `log` key,
However, the following store methods cannot be overwritten:
- `extend()`
- `get()`
- `push()`
- `set()`
- `setIfUnset()`
- `unset()`
## Return value
Store methods do not need to return anything. If they do, it will be ignored.

View file

@ -1,25 +0,0 @@
---
title: Plugin structure
order: 100
---
A FreeSewing plugin is a plain object with the following structure:
```mjs
Object plugin = {
String name,
String version,
Object hooks,
Object macros,
Array store,
}
```
A plugin **must** have the `name` and `version` properties.
The other properties are optional, and they map to the three different functionalities macros can provide:
- [`hooks`](/guides/plugins/hooks): Holds an object with lifecycle hooks the plugin wants to hook into
- [`macros`](/guides/plugins/macros): Holds and object with macros the plugin provides
- [`store`](/guides/plugins/store): Holds and Array with store methods the plugin provides.
Click on the links above for more details on the structure of these properties.

View file

@ -1,55 +0,0 @@
---
title: Understanding Bézier curves
order: 50
---
While lines on computers are easy to store with a start and end point,
curves require more information.
In FreeSewing — as in SVG and countless of other computer applications —
curves are stored as [Bézier curves](https://en.wikipedia.org/wiki/B%C3%A9zier_curve),
named after French engineer [Pierre Bézier](https://en.wikipedia.org/wiki/Pierre_B%C3%A9zier) who
popularized their use back in the 1960s.
In FreeSewing, we use so-called cubic Bézier curves which have:
- A start point
- A first control point thats linked to the start point
- A second control point thats linked to the end point
- An end point
<Example caption="An example of a Bézier curve drawn by the Path.curve() method" settings="margin: 20">
```js
({ Point, points, Path, paths, part }) => {
points.from = new Point(10, 20)
points.cp1 = new Point(40, 0)
points.cp2 = new Point(60, 40)
points.to = new Point(90, 20)
paths.line = new Path()
.move(points.from)
.curve(points.cp1, points.cp2, points.to)
.setText("Path.curve()", "text-sm center fill-note")
return part
}
```
</Example>
Bézier curves and their _handles_ or _control points_ are surprisingly intuitive.
The following illustration does a great job at explaining how they are constructed:
![How Bézier curves are constructed](bezier.gif)
You don't need to understand the mathematics behind Bézier Curves.
As long as you intuitively _get_ how the control points influence the curve, you're good to go.
<Note>
###### More on Bézier curves
Wikipedia has a good [introduction to Bézier curves](https://en.wikipedia.org/wiki/B%C3%A9zier_curve).
For a deep-dive into the subject, check out [A Primer on Bézier Curves](https://pomax.github.io/bezierinfo/) by
[Pomax](https://github.com/Pomax).
</Note>

View file

@ -1,43 +0,0 @@
---
title: The coordinate system
order: 30
---
The coordinate system in FreeSewing -- and in SVG -- follows the same rules as text on a page.
You start at the top-left, and as you go to the right, the X-coordinate will increase.
As you go down the Y-coordinate will increase.
<Example caption="The coordinate system in an SVG document">
```mjs
({ Point, points, paths, Path, part }) => {
points.origin = new Point(10, 10)
points.x = new Point(100, 10)
points.y = new Point(10, 50)
points.textX = new Point(85, 20).addText('X', 'text-lg')
points.textY = new Point(12, 43).addText('Y', 'text-lg')
paths.coords = new Path()
.move(points.y)
.line(points.origin)
.line(points.x)
.addClass('mark')
.attr('marker-start', 'url(#dimensionFrom)')
.attr('marker-end', 'url(#dimensionTo)')
return part
}
```
</Example>
The image above illustrates both the X-axis and Y-axis.
On the X-axis, `20` is further to the right than `10`.
On the Y-axis, `50` is lower than `20`.
<Note>
The Y-axis is inverted in many drawing programs, with the origin
`(0,0)` being the lower left corner, rather than the upper left corner.
This is a common point of confusion so keep in mind that the Y-axis may
not behave as you would have intuitively expected.
</Note>

View file

@ -1,28 +0,0 @@
---
title: Before you start
---
Drawing lines and curves on paper is a skill most people have been practicing since kindergarten.
In FreeSewing, we draw lines and curves with code, which is a bit more abstract
but doesn't have to be complicated once you understand a few basic building blocks.
Understanding the concepts that are involved in designing sewing patterns in code will pay dividends later.
That is why we recommend you familiarize yourself with the following topics:
<ReadMore />
<Note>
##### There's no need to know everything
FreeSewing sits at the intersection of the world of makers and developers.
If your background is in development, you will need no explaining what SVG is but might not
know much about designing sewing patterns.
If on the other hand your background is in sewing or pattern design, you might wonder what
the heck NodeJS is and why you should care.
Few people straddle both worlds, so as you start using FreeSewing, chances are
you'll learn a few new things along the way.
And if you get stuck [our chatrooms on Discord](https://discord.freesewing.org/) are the best place to get help.
</Note>

View file

@ -1,14 +0,0 @@
---
title: Scalable Vector Graphics
order: 20
---
Patterns are rendered as **SVG** — short
for [Scalable Vector Graphics](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics) —
an XML-based vector image format and an open standard.
While you dont need to be an SVG expert, a basic understanding of the format
will greatly help you to understand FreeSewing.
For example, the coordinate system and the way paths
are structured are all related to the SVG drawing system, which is closely related
to other 2D drawing technologies such as PostScript or PDF.

View file

@ -1,14 +0,0 @@
---
title: Units in FreeSewing
order: 40
---
FreeSewing uses _millimeter (mm)_ for all its internal units.
We do support both imperial and metrics units, which are displayed
as _cm_ or _inch_, but under the hood everything is handled in millimeter.
So as a pattern designer, you will work with mm.
When you write `1`, thats one millimeter. When you write `7.8`, thats 7.8 mm.
While you can use cm or inch on the FreeSewing website, that is merely a layer of
abstraction on top of the internal units, which are always mm.

View file

@ -1,223 +0,0 @@
---
title: Translation guide
---
Supporting multiple languages is one of the best way to promote inclusion and
accessibility. Thanks to the efforts of our community, FreeSewing is proudly
multilingual.
This translation guide covers everything you need to know to join the effort of
translating FreeSewing into other languages.
## Supported Languages
FreeSewing is currently available in the following languages:
| Code | Language | Website |
| ----:|:-------------- |:------- |
| `de` | **German** | https://freesewing.org/de |
| `en` | **English** | https://freesewing.org/ |
| `es` | **Spanish** | https://freesewing.org/es |
| `fr` | **French** | https://freesewing.org/fr |
| `nl` | **Dutch** | https://freesewing.org/nl |
| `uk` | **Ukrainian** | https://freesewing.org/uk |
<Note compact>
English is the translation source language and the working language of the FreeSewing project
</Note>
## Become a FreeSewing translator
To gain access as a FreeSewing translator, you will need an invite.
You can request a translator invite with the link below.
When you do, we will send you an email with all further instructions.
<Link compact>
###### [Request a FreeSewing translator invite](https://freesewing.org/translation/join)
</Link>
<Tip>
We also have [a dedicated __Translation__ channel on
Discord](https://discord.freesewing.org) for any questions that may remain.
</Tip>
## Adding a new language
We would love to make FreeSewing available in more languages. If you are
interested in starting a new translation effort, that is great.
We ask that you familiarize yourself with this translation guide to understand
what it takes to add a new language. Then if you can submit your request to setup
a new language with the link below.
<Link compact>
###### [Suggest a new FreeSewing language](https://freesewing.org/translation/suggest-language)
</Link>
<Tip>
##### Get the band together
We recommend finding some like-minded people who can help translating.
While the core materials of FreeSewing can realistically be handled by one
person, translating all of FreeSewing's documentation and content realistically
is a job you should not undertake on your own.
</Tip>
<Comment by="joost" >
##### Do or do not. There is no try.
There is a certain cost to adding a new language. It's not a cost in money,
but rather in increased bandwidth, storage requirements, build times,
repository size, test times, and so on.
It's a cost we are __more than happy__ to pay for the benefit gaining another
langauge. But it is also a cost that needs to be paid up front, at the start
of the effort.
So, without wanting to discourage anyone, I would really like to avoid a
scenario where people enthusiastically start working on a new languages, only
to lose interest days or weeks later and see the effort falter.
With that out of the way, I hope to see many more languages being added in the
future.
</Comment>
## Translation status
The status of the ongoing translation work is available at
[FreeSewing.org/translation](https://freesewing.org/translation).
It's a good place to check what languages need extra help, and which are
leading the scoreboard.
## Translation priorities
To fully translate FreeSewing, the following types of content needs to be
translated:
### Top priority: UX Translations
These are translations the directly impact
the user experience (_UX_). They include the content used in design, the names
of options, translations of menus, emails, and so on.
This is a relatively small amount of text, and makes up less than 10% of the
top & high priority content. It's an effort that a motivated translator can
complete over the course of a weekend.
<Tip>
The top-priority translations in Crowdin are everything under the `packages`
and `sites` folder. Do this first.
</Tip>
### High priority: Translation of Documentation
This includes all the documentation on FreeSewing.org.
This is a significant amount of text that makes up more than 90% of the top &
high priority content. It's an effort you should probably not take on by
yourself, but rather tackle with a team of translators.
<Tip>
The high-priory translations in Crowdin is everything under the
`markdown/org/docs` folder.
</Tip>
### Low Priority: Content of blog and showcase posts, and newsletters
This is _nice to have_ as people can use and navigate FreeSewing even when this
content remains untranslated.
<Tip>
The low-priory translations in Crowdin is everything under the
`markdown/org/blog`, `markdown/org/showcase`, and `markdown/org/newsletter` folders.
</Tip>
## Translation through Crowdin
All of our translation work is handled through [Crowdin](https://crowdin.com/),
an online platform to facilitate translation.
<Tip compact>
You can reach the FreeSewing project on Crowdin directly via
[translate.freesewing.org](https://translate.freesewing.org).
</Tip>
Crowdin is configured to automatically detect all of the various translation
files in our repository, upload them to the platform, and break them apart into
bite-sized portions that you can translate in a collaborative way.
Rather than work on one large block of text, various people can jump in and
translate smaller snippets,
Once translated, there is a proofreading step that will be handled by one of
our proofreaders. This is often a formality, but it's an extra step to allow
quality assurance and avoid any mistakes from slipping in. Much like the code
review process when you submit a pull request on GitHub.
Once your translation is approved, Crowdin will automatically submit a pull
request on GitHub to update the translation files in our repository. And the
next time our website or software packages get built, they will include the new
translations.
## Machine translation
While everybody knows that translation is best when it's done by a human being,
we also have to be realistic that the growing body of documentation and other
FreeSewing content can be a daunting task to take on for translators, especially
when you want to start a new language.
Fortunately, machine translation has gotten rather good so we can get some help.
Our Crowdin project is integrated with a [DeepL](https://www.deepl.com)
subscription, and this can be a great help to translators.
You can use the DeepL suggestions when translating, or there is also the possibility
to machine-translate entire files or folders. For example, you may start a new
language by machine-translating everything, and then focus on proofreading the
top-priority content, and then move on to the high-priority content.
## Syntax
Most strings are just text, but sometimes you'll find a little markup sprinkled in.
### HTML formatting
When you encounter HTML tags, simply translate around them. For example:
```yaml
<b>No</b>, never.
```
looks like this in Spanish:
```yaml
<b>No</b>, nunca.
```
### Placeholders
When you encounter a `{key}` between curly braces, leave it as-is.
These will be filled in later with the correct value. For example:
```yaml
{field} saved
```
looks like this in Spanish
```yaml
{field} guardado
```
## Questions, Suggestions, Discussion
If you have questions, suggestions, or would like to discuss
translation-related matters, please join
[discord.freesewing.org](https://discord.freesewing.org/) and head to the
__Translation__ channel.

View file

@ -1,16 +0,0 @@
---
title: Body ambassador
---
Maybe youre unusually short or tall.
Maybe you have a bit of a pot belly or very large breasts.
Maybe you have a disability that requires fit adjustments.
Whatever it is, if you represent a minority fitting issue you could
represent this minority to make sure their needs are heard and understood.
<Tip>
Join the `#pattern-design` channel on the Discord server and help us understand how we can design patterns that fit people with your body type.
</Tip>

View file

@ -1,15 +0,0 @@
---
title: Community building
---
The FreeSewing community resides [on Discord](https://discord.freesewing.org/).
Just being there to answer questions and chat with other people is a valuable part of community building.
We also can be found in plenty of other places where we'd love to have you join us:
* [Instagram](https://instagram.com/freesewing_org)
* [freesewing.social](https://freesewing.social/@freesewing) (our Mastodon instance)
* [Facebook](https://www.facebook.com/groups/627769821272714/)
* [Reddit](https://www.reddit.com/r/freesewing)
Apart from being present in chat rooms and social media, you could also take on some responsibility on one or more platforms.

View file

@ -1,8 +0,0 @@
---
title: Design sewing patterns
---
Everybody wants us to add more patterns. But somebody has to design them.
That somebody could be you.
We can help you with the development side of things.

View file

@ -1,7 +0,0 @@
---
title: Develop sewing patterns
---
You could program new designs for FreeSewing.
If you're not afraid of JavaScript and are happy to team up with a designer,
you could work on a new pattern together.

View file

@ -1,10 +0,0 @@
---
title: Devops
---
We have use a lot of automation from GitHub actions to automated deployment on Vercel.
We also have some Ansible playbooks to run maintenance tasks.
There's also other technical tasks like database or server administration, certificate renewal, and so on.
If that's your kind of thing, we could use your help.

View file

@ -1,51 +0,0 @@
---
title: Ways to contribute
---
Thank you for being part of our community, and for wanting to contribute! ❤️
FreeSewing is an open source project ran by volunteers from different corners of the world.
We would love to have you on board, and this page lists everything you need to know to get started.
## Requirements
The only requirement we ask from our contributors is that they are the kind of people who
value a safe and welcoming environment for all members of the FreeSewing community.
To that extend, we impose the following requirements to ensure everyone feels safe and welcome:
- Any member of our community must respect [our community standards](https://freesewing.org/docs/about/community-standards/)
- As a contributor, you must uphold [our Code of Conduct](/guides/code-of-conduct/)
Go ahead and read those, we'll wait.
## Good to know
With that out of the way, here's a few more things that are _good to know_:
- Nobody gets paid to work on/for FreeSewing. We are a 100% volunteer organisation.
- We have patrons who support us financially, but all the money that comes in goes to charity —
See our [revenue pledge](https://freesewing.org/docs/about/pledge/) for details
- FreeSewing follows the [all-contributors](https://allcontributors.org/) specification.
Contributions of any kind are welcome.
## Where to begin
Below is a list of ideas or roles you could take up.
If you're not sure what to do, or if you have questions, [please reach out to
us](https://discord.freesewing.org/).
<ReadMore />
<Comment by="joost">
##### Who wants a job in the tech sector?
For many in our community, contributing to FreeSewing marked their
first steps into the world of open source software development.
I (joost) am happy to provide guidance or mentorship to anyone who
wants to learn, especially when doing so enables upwards social mobility.
[Reach out](https://discord.freesewing.org/) and we let's do this.
</Comment>

View file

@ -1,6 +0,0 @@
---
title: Make illustrations
---
Our documentation can always use some more/better illustrations to help people figure out how
to make our patterns into garments.

View file

@ -1,7 +0,0 @@
---
title: Language ambassador
---
You could represent FreeSewing in a non-English community.
There, you can help answer questions or triage problem reports.
Or you can point out where translations are missing.

View file

@ -1,9 +0,0 @@
---
title: Pattern ambassador
---
You could take charge of a specific FreeSewing design/pattern.
Youll be the person to ask questions about how to make that pattern.
Youll make sure the documentation is not forgotten.
And you can help with questions or triage problem reports to developers or designers.

View file

@ -1,11 +0,0 @@
---
title: Pattern testing
---
You could make (a muslin for) our patterns prior to release to make sure everything is ok.
<Tip>
Join the `#pattern-design` channel on the Discord server and let us know you would like to help. Here you will find people designing new patterns and reviewing existing patterns. Feedback is very welcome!
</Tip>

View file

@ -1,14 +0,0 @@
---
title: Project management
---
There's a lot going on within the FreeSewing project and it's easy to forget about something.
A project manager would be helpful to prioritize tasks, makes sure all tasks have an issue,
organize milestones, and so on.
This is helpful in more than one way:
- It reduces the cognitive load of the people implementing changes because they don't have to worry about forgetting things
- It increases transparency by making it clear what sort of things are being worked on
- It gives us that good feeling of closing the issue when the task is done

View file

@ -1,6 +0,0 @@
---
title: Proofreading
---
You could check the original English text or translations for typos and/or grammar mistakes.
You could propose improvements and watch over a consistent style and tone across FreeSewings documentation and written text.

View file

@ -1,17 +0,0 @@
---
title: Report bugs
---
Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/).
Create an issue [in our monorepo](https://github.com/freesewing/freesewing/issues/new?assignees=\&labels=%F0%9F%90%9B+bug\&template=bug-report.md\&title=Bug+report) if you've found one.
Explain the problem and include additional details to help maintainers reproduce the problem:
- **Use a clear and descriptive title** for the issue to identify the problem.
- **Describe the exact steps which reproduce the problem** in as many details as possible.
- **Include relevant information** such as your username on the site, or the person you drafted a pattern for.
Provide more context by answering these questions:
- **Did the problem start happening recently** (e.g. it worked fine before but since the latest update it doesn't)
- **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens.

View file

@ -1,82 +0,0 @@
---
title: Showcase our patterns
---
Anytime somebody has made one of our patterns, we like to Showcase it on [freesewing.org](https://freesewing.org/showcase/).
## How to get your pictures to us
If you've got pictures, there's a few ways you can get them on the site:
- [FreeSewing](#freesewing)
- [Instagram](#instagram)
- [Mastodon](#mastodon)
- [Facebook](#facebook)
- [Discord](#discord)
- [Reddit](#reddit)
- [GitHub](#github)
- [Email](#email)
### FreeSewing
You can share something you (or someone else, with permission) made based on our designs at [FreeSewing.org/new/showcase](https://freesewing.org/new/showcase).
### Instagram
Post your pictures on Instagram, and tag or mention [@freesewing\_org](https://instagram.com/freesewing_org).
### Mastodon
Post your pictures — or a link to them — on freesewing.social (our Mastodon instance), and tag or mention [@freesewing](https://freesewing.social/@freesewing).
### Facebook
Post your pictures — or a link to them — on Facebook, and tag or mention the [@FreeSewing](https://www.facebook.com/groups/627769821272714/) group.
### Discord
Post your pictures — or a link to them — in the `#pattern-showcase` channel [on our Discord](https://discord.freesewing.org).
### Reddit
Post your pictures — or a link to them — in [r/freesewing](https://www.reddit.com/r/freesewing).
### GitHub
Create an issue [on GitHub](https://github.com/freesewing/freesewing/issues/new?assignees=&labels=:%2B1:+good+first+issue%2C+:camera_flash:+showcase%2C+:hugs:+community&template=04_showcase-template.yaml&title=%5Bshowcase%5D%3A+Found+a+great+project+to+showcase) and attach your pictures to it, or include a link to the pictures.
### Email
Email your pictures — or a link to them — to showcase@freesewing.org.
## Tips for great pictures
Below are just a few easy tips and tricks for your Showcase post.
Of course, any Showcase is infinitely better than nothing, so go ahead and send us those low-light mirror selfies - we love them.
But if you want to take things to the next level, a few things to consider:
### Show it all
Show the whole garment. From multiple angles, if possible.
It's awesome to see garments from the front, but back and side views can be really helpful, too.
Bonus points for adding in a seated picture, which are especially great for sewists who use a wheelchair.
### Embrace the light
Take pictures in the best light you can — that might be next to a bright window,
in a room where you've turned on all the extra lamps you could find,
or that elusive "golden hour" outdoors.
Bonus points if you can make it bright enough to not need a flash.
### Background
A neutral background can be helpful for seeing details.
Try to avoid black on black or another setting that makes it hard to see what is what.
And remember that the outdoors is often the best background.
### Close-ups
If you nailed that welt pocket or hand-stitched all your buttonholes, go ahead and show them off.
Close-up pictures make the showcase so much more relevant for people looking to make the same thing.

View file

@ -1,7 +0,0 @@
---
title: Writing for freesewing.dev
---
You could write documentation for freesewing.dev, our developers website.
You would need good writing skills and a familiarity with code (JavaScript).

View file

@ -1,5 +0,0 @@
---
title: Technical writing
---
<ReadMore />

View file

@ -1,7 +0,0 @@
---
title: Writing for freesewing.org
---
You could write documentation for freesewing.org, our makers website.
You would need good writing skills and a familiarity with sewing.

View file

@ -1,6 +0,0 @@
---
title: Translation
---
You could translate FreeSewing into one of its additional languages
(French, German, Dutch, Spanish, Ukrainian). Or if youre ambitious, add a new one.

View file

@ -1,14 +0,0 @@
---
title: Triage issues
---
Triaging issues is a great way to get involved in FreeSewing. You can do tasks such as:
- Making sure issues are properly labeled
- Ensuring they have a good title that explains the issue in brief
- Assigning issues to people to make sure they are tended to
- Keeping an eye on stale issues, and either updating or closing them
- Assigning issues to milestones so we can plan our releases
All FreeSewing contributors have triage permissions that allows them to do this.
If you don't have the rights, or bump into any issues, [reach out to us on Discord](https://discord.freesewing.org).

View file

@ -1,5 +0,0 @@
---
title: UI / UX Webdesign
---
You could help us make our website and tools pretty and improve the user experience.

View file

@ -1,22 +0,0 @@
---
title: Translate
---
FreeSewing is proudly multilingual. For that, we rely on the
support of our translators.
FreeSewing currently is available in the following languages:
- English
- Dutch
- French
- Spanish
- German
- Ukrainian
## Translation guide
This guide for translators covers everything you need to know about (helping out with) the translation of FreeSewing.
- <DocsLink slug="guides/translation" />

View file

@ -1,35 +0,0 @@
---
title: Point.dist()
---
The `Point.dist()` method returns the distance (in mm) between this point and
the point you pass it.
## Signature
```js
float point.dist(Point point)
```
## Example
<Example caption="An example of the Point.dist() method">
```js
({ Point, points, Path, paths, units, part }) => {
points.from = new Point(10, 10)
points.to = new Point(80, 70)
points.text = points.from
.shiftFractionTowards(points.to, 0.6)
.setText(units(points.from.dist(points.to)), 'text-sm fill-note center')
paths.line = new Path()
.move(points.from)
.line(points.to)
.setClass('dashed')
return part
}
```
</Example>

View file

@ -1,113 +0,0 @@
---
title: Confirm an account
---
Confirms a newly created User account.
If confirmation is successful this will also result in a (passwordless) sign-in.
## Endpoints
Confirming a new User account is possible via this endpoint:
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method post /> | `/confirm/signup/:id` | None |
<Note compact>This endpoint requires no authentication</Note>
## Request URL
The URL should contain the confirmation ID that was E-mailed to the E-mail
address used for the signup. It replaces the `:id` placeholder in the
[endpoint listed above](#endpoints).
## Request body
| Property | Type | Description |
| ----------: | :------- | :---------- |
| `consent` | Number | An integer representing the consent given by the user to process their data |
## Response status codes
Possible status codes for these endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="200"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="404"/> | the confirmation was not found |
| <StatusCode status="500"/> | server error |
<Note>
If the status code is not <StatusCode status="200" /> the `error` property
in the response body should indicate the nature of the problem.
</Note>
## Response body
| Value | Type | Description |
| ------------------- | -------- | ----------- |
| `result` | String | Either `success` or `error` |
| `error` | String | Will give info on the nature of the error. Only set if an error occurred. |
| `token` | String | A JSON web token (JWT) token to authenticate with |
| `account.id` | Number | The ID of the User |
| `account.bio` | String | The bio of the User |
| `account.consent` | Number | The consent given by the User |
| `account.control` | Number | The control desired by the User |
| `account.createdAt` | String | Date string indicating the moment the User was created |
| `account.email` | String | The E-mail address currently tied to the User |
| `account.github` | String | The GitHub username of the User |
| `account.img` | String | The URL to the image stored with this User |
| `account.imperial` | Boolean| Whether or not the User prefers imperial units |
| `account.initial` | String | The E-mail address that the User was created with |
| `account.language` | String | The language preferred by the user |
| `account.lastSignIn`| String | Date string indicating them moment the User last signed in |
| `account.mfaEnabled`| Boolean| Whether or not the User has MFA enabled |
| `account.newsletter`| Boolean| Whether or not the User is subscribed to the FreeSewing newsletter |
| `account.patron` | Number | The level of patronage the user provides to FreeSewing |
| `account.role` | String | The role of the User |
| `account.status` | Number | The status of the user |
| `account.updatedAt` | String | Date string indicating the last time the User was updated |
| `account.username` | String | The username of the User |
| `account.lusername` | String | A lowercased version of the username of the User |
## Example request
```js
const confirm = await axios.post(
'https://backend.freesewing.org/confirm/signup/3985f312-e407-458a-a78c-4596c361d284',
{ consent: 2 },
)
```
## Example response
```200.json
{
"result": "success",
"token": "eyJhbGciOiJIUzI1NiIsInR5c...truncated",
"account": {
"id": 14,
"bio": "",
"consent": 1,
"control": 1,
"createdAt": "2022-11-19T18:15:22.642Z",
"email": "test_54c6856275aaa8a1@freesewing.dev",
"github": "",
"img": "https://freesewing.org/avatar.svg",
"imperial": false,
"initial": "test_54c6856275aaa8a1@freesewing.dev",
"language": "en",
"lastSignIn": "2022-11-19T18:15:22.668Z",
"mfaEnabled": false,
"newsletter": false,
"patron": 0,
"role": "user",
"status": 1,
"updatedAt": "2022-11-19T18:15:22.668Z",
"username": "user-14",
"lusername": "user-14"
}
}
```
[duri]: https://en.wikipedia.org/wiki/Data_URI_scheme

View file

@ -1,66 +0,0 @@
---
title: Create an account
---
Creates a new User account. The User account will remain inactive
until [it is confirmed](/reference/backend/account/confirm).
## Endpoints
Creating a new User account is possible via this endpoint:
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method post /> | `/signup` | None |
<Note compact>This endpoint requires no authentication</Note>
## Request body
| Property | Type | Description |
| ----------: | :------- | :---------- |
| `email` | `string` | The E-mail address of the User |
| `language` | `boolean`| The language code for the User |
## Response status codes
Possible status codes for these endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="201"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="500"/> | server error |
<Note>
If the status code is not <StatusCode status="201" /> the `error` property
in the response body should indicate the nature of the problem.
</Note>
## Response body
| Value | Type | Description |
| ------------------- | -------- | ----------- |
| `result` | String | Either `success` or `error` |
| `error` | String | Will give info on the nature of the error. Only set if an error occurred. |
| `email` | String | The E-mail address where the confirmation email was sent to |
## Example request
```js
const signup = await axios.post(
'https://backend.freesewing.org/signup',
{
email: "joost@joost.at",
language: "en"
}
)
```
## Example response
```201.json
{
"result": "success",
"email": "joost@joost.at"
}
```

View file

@ -1,94 +0,0 @@
---
title: Account
---
From an end-user's point of view, their account holds all of their data. From
an API point of view, these endpoints deal with data in the User table.
As the endpoints typically use `/account` we tend to use _account_ more often
than _user_.
## Endpoints
<ReadMore />
## Notes
### The `consent` field is about data protection
The `consent` field holds a number indicating to which level the user has
agreed to the processing of their data:
- `0` : No consent given (yet)
- `1` : Consent given for processing profile data
- `2` : Consent given for processing profile & people data
- `3` : Consent given for processing profile & people data, and for publishing
anonymized measurements as open data
Providing a consent value (that is higher than `0`) is a requirement for
confirming a User account. In other words, without sufficient consent, you
can't sign up.
### The `control` field is about keeping it simple
The `control` field holds a number indicating to which level the user wants to
be in control of the FreeSewing platform. It was added as a way to allow for
progressive disclosure of (more) advanced features and settings on the
FreeSewing website.
Possible values are:
- `1` : Hide all but the most crucial features. Make it as simple as possible.
- `2` : Hide the majority of features. Make it simple, but not too much.
- `3` : Reveal the majority of features, but not all. Balance simplicity with
power.
- `4` : Reveal everything, but keep handrails and safety checks. Only intervene
when I'm about to do something dangerous.
- `5` : Reveal everything, remove the handrails and safety checks. Get out of
my way, I know what I'm doing.
### The `ihash` and `ehash` fields are for search
Because we encrypt a lot of data at rest, it can be difficult for support or
administrators to find users when they don't know or remember their username
because we cannot search on their E-mail address since that data is encrypted.
That is why we store a hash of the (lowercased) email address. This way, we can
hash the email provided to us, and search the hash instead.
The `ehash` and `ihash` fields hold the hash for the `email` and `initial`
fields.
### The `imperial` property is a Boolean
If the `imperial` property is `false`, the user wants metric units.
If the `imperial` property is `true`, the user wants imperial units.
### The `initial` field guards against account takeover
The `initial` field will be set to the E-mail address the account was
registered with. It can never be changed.
This ensures that when there's an account takeover dispute, we can always know
what E-mail address was used to create the account, even if the E-mail address
associated with the account was changed.
### The `lusername` field should be unique
For the backend users `Joost` and `joost` are -- strictly speaking -- two
different users. This tends to lead to confusion and possible impersonation.
So we enforce uniqueness on the `lusername` field which holds a lowercased
version of the `username` field..
In other words, lowercased username must be unique.
### The `status` field holds the account status
Possible values are:
- `0` : The account is not active (yet)
- `1` : The account is active
- `-1` : The account was disabled by the user
- `-2` : The account was administratively disabled

View file

@ -1,213 +0,0 @@
---
title: MFA
---
Enable of disable Multi-Factor Authentication (MFA) on the User account.
- [Setup MFA](#setup-mfa)
- [Confirm MFA](#confirm-mfa)
- [Disable MFA](#disable-mfa)
## Endpoints
Enabling, confirming, and disabling MFA is all possible via this endpoint:
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method post /> | `/account/mfa/jwt` | [JSON Web Token](/reference/backend/authentication#jwt-authentication) |
| <Method post /> | `/account/mfa/key` | [API Key & Secret](/reference/backend/authentication#key-authentication) |
## Setup MFA
### Request body
| Property | Type | Description |
| ----------: | :------- | :---------- |
| `mfa` | `boolean`| Set to `true` to enable MFA |
### Response status codes
Possible status codes for this endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="201"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | authentication failed |
| <StatusCode status="403"/> | access denied |
| <StatusCode status="500"/> | server error |
<Note>
If the status code is not <StatusCode status="200" /> the `error` property
in the response body should indicate the nature of the problem.
</Note>
### Response body
| Value | Type | Description |
| -------------- | -------- | ----------- |
| `result` | String | Either `success` or `error` |
| `error` | String | Will give info on the nature of the error. Only set if an error occurred. |
| `mfa.secret` | String | The shared secret for generating one-time password (OTP) tokens |
| `mfa.otpauth` | String | The OTP Auth URI that is encoded in the QR code |
| `mfa.qrcode` | String | SVG to display a QR code with the otpauth URI encoded |
<Tip>
##### Styling the SVG
The SVG returned by the backend uses `currentColor` for the QR code, so you can
style it with CSS if you embed it in the page.
</Tip>
### Example request
```js
const mfa = await axios.post(
'https://backend.freesewing.org/account/mfa/jwt',
{ mfa: true },
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
```
### Example response
```200.json
{
"result": "success",
"mfa": {
"secret": "KBTSKUKRDJPEGCZK",
"otpauth": "otpauth://totp/FreeSewing:user-294?secret=KBTSKUKRDJPEGCZK&period=30&digits=6&algorithm=SHA1&issuer=FreeSewing",
"qrcode": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 53 53\" shape-rendering=\"crispEdges\"><path fill=\"none\" d=\"M0 0h53v53H0z\"/><path stroke=\"currentColor\" d=\"M4 4.5h7m1 0h1m3 0h1m1 0h3m2 0h1m1 0h1m1 0h1m1 0h2m1 0h5m3 0h1m1 0h7M4 5.5h1m5 0h1m1 0h4m1 0h2m4 0h1m2 0h3m3 0h1m2 0h2m2 0h1m2 0h1m5 0h1M4 6.5h1m1 0h3m1 0h1m1 0h2m1 0h3m4 0h2m1 0h2m3 0h4m2 0h1m2 0h1m2 0h1m1 0h3m1 0h1M4 7.5h1m1 0h3m1 0h1m7 0h1m6 0h3m3 0h1m1 0h1m5 0h2m1 0h1m1 0h3m1 0h1M4 8.5h1m1 0h3m1 0h1m1 0h1m1 0h3m1 0h3m1 0h8m3 0h1m2 0h1m1 0h3m1 0h1m1 0h3m1 0h1M4 9.5h1m5 0h1m7 0h1m1 0h3m1 0h1m3 0h1m2 0h3m1 0h1m1 0h1m4 0h1m5 0h1M4 10.5h7m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h7M14 11.5h2m3 0h4m1 0h1m3 0h4m2 0h1m1 0h3m1 0h1M4 12.5h1m2 0h6m1 0h2m6 0h1m1 0h5m1 0h1m1 0h2m1 0h1m3 0h1m1 0h1m2 0h1m1 0h3M5 13.5h3m3 0h2m1 0h2m5 0h2m1 0h2m2 0h5m1 0h2m2 0h1m2 0h4m1 0h2M5 14.5h1m1 0h2m1 0h1m5 0h1m2 0h1m2 0h1m1 0h3m10 0h2m2 0h1m3 0h1m1 0h2M5 15.5h2m2 0h1m2 0h4m1 0h1m4 0h3m2 0h1m2 0h3m1 0h1m2 0h4m2 0h6M5 16.5h1m4 0h1m2 0h4m1 0h3m1 0h2m1 0h1m3 0h4m2 0h1m2 0h2m3 0h2M5 17.5h3m1 0h1m1 0h1m3 0h2m2 0h3m5 0h2m2 0h1m2 0h1m2 0h1m1 0h2m1 0h2m2 0h1M4 18.5h2m1 0h2m1 0h2m4 0h5m5 0h1m2 0h5m1 0h1m5 0h3m3 0h2M4 19.5h1m1 0h2m3 0h2m2 0h1m1 0h1m1 0h1m1 0h2m3 0h1m2 0h3m1 0h1m1 0h1m1 0h2m1 0h1m1 0h3m1 0h3M6 20.5h1m1 0h3m1 0h1m2 0h1m1 0h1m1 0h4m1 0h1m3 0h1m1 0h3m2 0h3m1 0h1m1 0h1m1 0h1m2 0h1M4 21.5h1m1 0h2m1 0h1m3 0h5m2 0h1m4 0h2m1 0h1m1 0h2m2 0h1m4 0h2m3 0h2m1 0h2M4 22.5h5m1 0h2m3 0h1m1 0h1m3 0h2m9 0h3m1 0h1m2 0h1m3 0h1m2 0h2M4 23.5h1m1 0h1m1 0h1m3 0h1m2 0h1m2 0h1m1 0h2m1 0h2m2 0h4m1 0h3m8 0h2M4 24.5h1m1 0h9m2 0h1m1 0h2m1 0h7m2 0h1m3 0h3m1 0h7M6 25.5h1m1 0h1m3 0h1m1 0h4m1 0h3m2 0h1m3 0h1m1 0h2m3 0h1m3 0h2m3 0h4M4 26.5h1m1 0h1m1 0h1m1 0h1m1 0h2m2 0h1m1 0h1m1 0h1m3 0h1m1 0h1m1 0h3m1 0h2m3 0h4m1 0h1m1 0h3m1 0h1M4 27.5h1m1 0h1m1 0h1m3 0h1m5 0h1m2 0h1m1 0h2m3 0h2m3 0h3m1 0h1m1 0h2m3 0h1m1 0h2M5 28.5h1m2 0h8m2 0h2m4 0h5m1 0h1m1 0h4m4 0h5M8 29.5h1m2 0h2m3 0h1m2 0h1m2 0h1m2 0h2m1 0h1m1 0h2m3 0h1m1 0h1m2 0h2m1 0h1m3 0h1M4 30.5h3m1 0h1m1 0h1m1 0h1m1 0h1m3 0h1m2 0h1m1 0h3m4 0h1m1 0h2m2 0h1m2 0h1m1 0h2m2 0h2M4 31.5h1m1 0h1m2 0h1m2 0h1m1 0h1m2 0h3m1 0h1m5 0h4m1 0h1m1 0h1m1 0h5m2 0h1m2 0h1M6 32.5h1m2 0h3m2 0h1m1 0h2m1 0h1m1 0h2m2 0h1m2 0h1m3 0h1m4 0h1m2 0h3m1 0h1M4 33.5h1m1 0h2m1 0h1m2 0h1m2 0h1m1 0h1m1 0h3m3 0h3m2 0h1m2 0h1m4 0h2m3 0h2m2 0h2M7 34.5h1m2 0h5m1 0h5m1 0h2m1 0h1m2 0h1m4 0h4m2 0h1m2 0h1m1 0h2m1 0h1M4 35.5h2m2 0h1m2 0h1m1 0h1m1 0h1m2 0h8m2 0h2m1 0h4m3 0h2m1 0h1m5 0h2M9 36.5h5m1 0h5m3 0h1m1 0h1m1 0h5m5 0h1m7 0h2M5 37.5h2m2 0h1m2 0h3m6 0h1m1 0h2m3 0h1m1 0h2m1 0h3m2 0h5m4 0h1M8 38.5h1m1 0h1m1 0h3m2 0h1m3 0h2m1 0h1m1 0h1m2 0h1m1 0h1m3 0h1m2 0h2m1 0h5M5 39.5h4m5 0h1m2 0h4m3 0h1m2 0h4m1 0h1m2 0h2m3 0h1m1 0h1m1 0h2M4 40.5h1m2 0h2m1 0h1m1 0h2m4 0h12m3 0h1m1 0h1m2 0h7m3 0h1M12 41.5h1m1 0h3m1 0h3m3 0h1m3 0h1m2 0h1m3 0h1m2 0h1m1 0h1m3 0h1m1 0h2M4 42.5h7m1 0h1m2 0h4m1 0h3m1 0h1m1 0h1m1 0h2m1 0h1m2 0h2m4 0h1m1 0h1m1 0h1m1 0h2M4 43.5h1m5 0h1m1 0h1m1 0h1m1 0h2m1 0h3m2 0h1m3 0h3m2 0h6m1 0h1m3 0h3M4 44.5h1m1 0h3m1 0h1m1 0h1m2 0h2m1 0h2m1 0h1m2 0h6m3 0h1m3 0h1m2 0h6m2 0h1M4 45.5h1m1 0h3m1 0h1m1 0h5m3 0h2m1 0h3m1 0h3m3 0h3m1 0h2m4 0h2m1 0h1m1 0h1M4 46.5h1m1 0h3m1 0h1m3 0h5m3 0h5m1 0h2m1 0h2m2 0h1m1 0h1m1 0h3m1 0h1m1 0h4M4 47.5h1m5 0h1m2 0h1m2 0h1m1 0h1m2 0h1m4 0h2m2 0h1m3 0h2m1 0h3m1 0h3m2 0h3M4 48.5h7m1 0h5m2 0h3m3 0h1m2 0h1m1 0h3m1 0h2m2 0h1m1 0h1m1 0h2m1 0h1\"/></svg>\n"
}
}
```
## Confirm MFA
To confirm the MFA, we need to provide an MFA token to ensure the user can
generate them.
### Request body
| Property | Type | Description |
| ----------: | :------- | :---------- |
| `mfa` | `boolean`| Must be set to `true` to confirm MFA |
| `secret` | `boolean`| The secret returned when setting up MFA |
| `token` | `boolean`| Must be set to `true` to confirm MFA |
### Response status codes
Possible status codes for this endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="201"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | authentication failed |
| <StatusCode status="403"/> | access denied |
| <StatusCode status="500"/> | server error |
<Note>
If the status code is not <StatusCode status="200" /> the `error` property
in the response body should indicate the nature of the problem.
</Note>
### Response body
| Value | Type | Description |
| -------------- | -------- | ----------- |
| `result` | String | Either `success` or `error` |
| `error` | String | Will give info on the nature of the error. Only set if an error occurred. |
### Example request
```js
import { authenticator } from '@otplib/preset-default'
const confirm = await axios.post(
'https://backend.freesewing.org/account/mfa/jwt',
{
mfa: true,
secret: mfa.secret,
token: authenticator.generate(mfa.secret)
},
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
```
### Example response
```200.json
{
"result": "success",
}
```
## Disable MFA
To disable MFA, you need to provide both the account password and a valid token.
### Request body
| Property | Type | Description |
| ----------: | :------- | :---------- |
| `mfa` | `boolean`| Must be set to `false` to disable MFA |
| `password` | `boolean`| The User's password |
| `token` | `boolean`| Must be set to `true` to confirm MFA |
### Response status codes
Possible status codes for this endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="201"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | authentication failed |
| <StatusCode status="403"/> | access denied |
| <StatusCode status="500"/> | server error |
<Note>
If the status code is not <StatusCode status="200" /> the `error` property
in the response body should indicate the nature of the problem.
</Note>
### Response body
| Value | Type | Description |
| -------------- | -------- | ----------- |
| `result` | String | Either `success` or `error` |
| `error` | String | Will give info on the nature of the error. Only set if an error occurred. |
### Example request
```js
import { authenticator } from '@otplib/preset-default'
const confirm = await axios.post(
'https://backend.freesewing.org/account/mfa/jwt',
{
mfa: false,
password: "I like big bewbs and I just can't lie",
token: authenticator.generate(mfa.secret)
},
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
```
### Example response
```200.json
{
"result": "success",
}
```

View file

@ -1,113 +0,0 @@
---
title: Sign In
---
Sign in as a User with username and password, and optional MFA token.
## Endpoints
Password-based sign-in is possible via this endpoint:
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method post /> | `/signin` | None |
<Note compact>This endpoint requires no authentication</Note>
## Request body
| Property | Type | Description |
| ----------: | :------- | :---------- |
| `username` | `string` | The E-mail address of the User |
| `password` | `boolean`| The language code for the User |
| `token` | `boolean`| The MFA token |
<Note compact>An MFA token is required (only) when the User enabled MFA</Note>
## Response status codes
Possible status codes for these endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="201"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | authentication failed |
| <StatusCode status="403"/> | MFA token missing |
| <StatusCode status="500"/> | server error |
<Note>
If the status code is not <StatusCode status="200" /> the `error` property
in the response body should indicate the nature of the problem.
</Note>
## Response body
| Value | Type | Description |
| ------------------- | -------- | ----------- |
| `result` | String | Either `success` or `error` |
| `error` | String | Will give info on the nature of the error. Only set if an error occurred. |
| `token` | String | A JSON web token (JWT) token to authenticate with |
| `account.id` | Number | The ID of the User |
| `account.bio` | String | The bio of the User |
| `account.consent` | Number | The consent given by the User |
| `account.control` | Number | The control desired by the User |
| `account.createdAt` | String | Date string indicating the moment the User was created |
| `account.email` | String | The E-mail address currently tied to the User |
| `account.github` | String | The GitHub username of the User |
| `account.img` | String | The URL to the image stored with this User |
| `account.imperial` | Boolean| Whether or not the User prefers imperial units |
| `account.initial` | String | The E-mail address that the User was created with |
| `account.language` | String | The language preferred by the user |
| `account.lastSignIn`| String | Date string indicating them moment the User last signed in |
| `account.mfaEnabled`| Boolean| Whether or not the User has MFA enabled |
| `account.newsletter`| Boolean| Whether or not the User is subscribed to the FreeSewing newsletter |
| `account.patron` | Number | The level of patronage the user provides to FreeSewing |
| `account.role` | String | The role of the User |
| `account.status` | Number | The status of the user |
| `account.updatedAt` | String | Date string indicating the last time the User was updated |
| `account.username` | String | The username of the User |
| `account.lusername` | String | A lowercased version of the username of the User |
## Example request
```js
const signup = await axios.post(
'https://backend.freesewing.org/signup',
{
username: "jimmy",
language: "I like big bewbs and I just can't lie",
token: 231586
}
)
```
## Example response
```200.json
{
"result": "success",
"token": "eyJhbGciOiJIUzI1NiIsInR5c...truncated",
"account": {
"id": 14,
"bio": "",
"consent": 1,
"control": 1,
"createdAt": "2022-11-19T18:15:22.642Z",
"email": "test_54c6856275aaa8a1@freesewing.dev",
"github": "",
"img": "https://freesewing.org/avatar.svg",
"imperial": false,
"initial": "test_54c6856275aaa8a1@freesewing.dev",
"language": "en",
"lastSignIn": "2022-11-19T18:15:22.668Z",
"mfaEnabled": false,
"newsletter": false,
"patron": 0,
"role": "user",
"status": 1,
"updatedAt": "2022-11-19T18:15:22.668Z",
"username": "jimmy",
"lusername": "jimmy"
}
}
```

View file

@ -1,126 +0,0 @@
---
title: Update account
---
Updates an existing User account.
## Access control
- [Permission level](/reference/backend/rbac) `4` or higher is required to update your own User account
- [Permission level](/reference/backend/rbac) `8` is required to update **another user's** account
## Endpoints
Updating an existing User account is possible via these endpoints:
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method put /> | `/account/jwt` | [JSON Web Token](/reference/backend/authentication#jwt-authentication) |
| <Method put /> | `/account/key` | [API Key & Secret](/reference/backend/authentication#key-authentication) |
## Request body
| Property | Type | Description |
| ----------: | :------- | :---------- |
| `bio` | `string` | The User's bio |
| `consent` | `string` | A number that indicates [the consent given by the user](/reference/backend/account#the-consent-field-is-about-data-protection) |
| `control` | `string` | A number that indicates [the level of control the user prefers](/reference/backend/account#the-control-field-is-about-keeping-it-simple) |
| `github` | `string` | The User's username on GitHub |
| `imperial` | `boolean`| Whether or not the User prefers imperial units |
| `newsletter`| `boolean`| Whether this Person prefers imperial measurements (`true`) or not (`false`) |
| `img` | `string` | An image [data-uri][duri] to store with this Person |
| `password` | `string` | The (new) password for the User |
| `username` | `string` | The (new) username for the User |
## Response status codes
Possible status codes for these endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="200"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | the request lacks authentication |
| <StatusCode status="403"/> | authentication failed |
| <StatusCode status="500"/> | server error |
<Note>
If the status code is not <StatusCode status="200" /> the `error` property
in the response body should indicate the nature of the problem.
</Note>
## Response body
| Value | Type | Description |
| ------------------- | -------- | ----------- |
| `result` | String | Either `success` or `error` |
| `error` | String | Will give info on the nature of the error. Only set if an error occurred. |
| `account.id` | Number | The ID of the User |
| `account.bio` | String | The bio of the User |
| `account.consent` | Number | The consent given by the User |
| `account.control` | Number | The control desired by the User |
| `account.createdAt` | String | Date string indicating the moment the User was created |
| `account.email` | String | The E-mail address currently tied to the User |
| `account.github` | String | The GitHub username of the User |
| `account.img` | String | The URL to the image stored with this User |
| `account.imperial` | Boolean| Whether or not the User prefers imperial units |
| `account.initial` | String | The E-mail address that the User was created with |
| `account.language` | String | The language preferred by the user |
| `account.lastSignIn`| String | Date string indicating them moment the User last signed in |
| `account.mfaEnabled`| Boolean| Whether or not the User has MFA enabled |
| `account.newsletter`| Boolean| Whether or not the User is subscribed to the FreeSewing newsletter |
| `account.patron` | Number | The level of patronage the user provides to FreeSewing |
| `account.role` | String | The role of the User |
| `account.status` | Number | The status of the user |
| `account.updatedAt` | String | Date string indicating the last time the User was updated |
| `account.username` | String | The username of the User |
| `account.lusername` | String | A lowercased version of the username of the User |
## Example request
```js
const udpate = await axios.put(
'https://backend.freesewing.org/account/jwt',
{
bio: "I like imperial now",
imperial: true,
username: "ImperialLover"
},
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
```
## Example response
```200.json
{
"result": "success",
"account": {
"id": 14,
"bio": "I like imperial now",
"consent": 1,
"control": 1,
"createdAt": "2022-11-19T18:15:22.642Z",
"email": "test_54c6856275aaa8a1@freesewing.dev",
"github": "",
"img": "https://freesewing.org/avatar.svg",
"imperial": true,
"initial": "test_54c6856275aaa8a1@freesewing.dev",
"language": "en",
"lastSignIn": "2022-11-19T18:15:22.668Z",
"mfaEnabled": false,
"newsletter": false,
"patron": 0,
"role": "user",
"status": 1,
"updatedAt": "2022-11-19T18:15:22.668Z",
"username": "ImperialLover",
"lusername": "imperiallover"
}
}
```
[duri]: https://en.wikipedia.org/wiki/Data_URI_scheme

View file

@ -1,97 +0,0 @@
---
title: Create an API key
---
Creates a new API key. An API key can be used to authenticate against the
backend API.
## Access control
- [Permission level](/reference/backend/rbac) `4` or higher is required to create an API key
## Endpoints
Creating a new API key is possible via these endpoints:
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method post /> | `/apikeys/jwt` | [JSON Web Token](/reference/backend/authentication#jwt-authentication) |
| <Method post /> | `/apikeys/key` | [API Key & Secret](/reference/backend/authentication#key-authentication) |
## Request body
| Property | Type | Description |
| ----------: | :------- | :---------- |
| `name` | `string` | A name for the API key |
| `level` | `number` | A privilege level from 0 to 8. |
| `expiresIn` | `number` | The number of seconds until the API key expires |
## Response status codes
Possible status codes for these endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="201"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | the request lacks authentication |
| <StatusCode status="403"/> | authentication failed |
| <StatusCode status="500"/> | server error |
<Note>
If the status code is not <StatusCode status="201" /> the `error` property
in the response body should indicate the nature of the problem.
</Note>
## Response body
<Warning>
##### Make sure to save the secret
The response body is the only time the API key's secret will be revealed.
</Warning>
| Value | Type | Description |
| ------------------- | -------- | ----------- |
| `result` | `string` | Either `success` or `error` |
| `error` | `string` | Will give info on the nature of the error. Only set if an error occurred. |
| `apikey.key` | `string` | The API key |
| `apikey.secret` | `string` | The API secret |
| `apikey.level` | `number` | The privilege level of the API key |
| `apikey.expiresAt` | `string` | A string representation of the moment the API key expires |
| `apikey.name` | `string` | The name of the API key |
| `apikey.userId` | `number` | The ID of the user who created the API key |
## Example request
```js
const apiKey = axios.post(
'https://backend.freesewing.org/apikeys/jwt',
{
name: 'My first API key',
level: 2, // Read only
expiresIn: 3600, // One hour
},
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
```
## Example response
```201.json
{
"result": "success",
"apikey": {
"key": "7ea12968-7758-40b6-8c73-75cc99be762b",
"secret": "503d7adbdb3ec18ab27adfcd895d8b47a8d6bc8307d548500fbf9c05a5a8820e",
"level": 3,
"expiresAt": "2022-11-06T15:57:30.190Z",
"name": "My first API key",
"userId": 61
}
}
```

View file

@ -1,58 +0,0 @@
---
title: Delete an API key
---
Deletes an existing API key.
## Access control
- [Permission level](/reference/backend/rbac) `4` or higher is required to delete an API key
## Endpoints
Deleting an API key is possible via these endpoints:
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method delete /> | `/apikeys/:id/jwt` | [JSON Web Token](/reference/backend/authentication#jwt-authentication) |
| <Method delete /> | `/apikeys/:id/key` | [API Key & Secret](/reference/backend/authentication#key-authentication) |
## Request URL
The URL should contain the ID of the API key you wish to remove.
It replaces the `:id` placeholder in the [endpoints listed above](#endpoints).
## Response status codes
Possible status codes for these endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="204"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | the request lacks authentication |
| <StatusCode status="403"/> | authentication failed |
| <StatusCode status="500"/> | server error |
## Example request
```js
await axios.delete(
'https://backend.freesewing.org/apikeys/7ea12968-7758-40b6-8c73-75cc99be762b/jwt',
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
```
## Example response
```204.json
```
<Note>
These endpoints return status code <StatusCode status="204"/> (no content) on
success, with no response body.
</Note>

View file

@ -1,53 +0,0 @@
---
title: API Keys
---
API keys are a way to authenticate to the API with basic authentication.
They are intended to be used when interacting with the API in an automated
way such as from a script or a CI/CD pipeline.
They are an alternative to JSON Web Tokens (JWT) which is typically used
to authenticate users in a browser session.
The FreeSewing backend REST API supports authentication both with JSON Web
Tokens (JWT) as with API keys (KEY). This describes the endpoints that deal
with creating, reading, and removing API keys. For authentication details,
refer to [the section on
authenticating](/reference/backend/authentication).
## Endpoints
<ReadMore />
## Notes
The following is good to keep in mind when working with API keys:
### API keys are immutable
Once created, API keys cannot be updated.
You should remove them and re-create a new one if you want to make a change.
### API keys have an expiry
API keys have an expiry date. The maximum validity for an API key is 1 year.
### API keys have a permission level
API keys have a permission level. You can never create an API key with a higher
permission level than your own permission level.
### Circumstances that will trigger your API keys to be revoked
As a precaution, all your API keys will be revoked when:
- Your role is downgraded to a role with fewer privileges
- Your account is (b)locked
- You revoke your consent for FreeSewing to process your data
<Note>
This is not an exhaustive list. For example, if we find your use of our API to
be excessive, we might also revoke your API keys to shield us from the
financial impact of your use of our API.
</Note>

View file

@ -1,81 +0,0 @@
---
title: Read an API key
---
Reads an existing API key. Note that the API secret can only be retrieved at
the moment the API key is created.
## Access control
- [Permission level](/reference/backend/rbac) `4` or higher is required to read an API key
## Endpoints
Reading an API key is possible via these endpoints:
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method get /> | `/apikeys/:id/jwt` | [JSON Web Token](/reference/backend/authentication#jwt-authentication) |
| <Method get /> | `/apikeys/:id/key` | [API Key & Secret](/reference/backend/authentication#key-authentication) |
## Request URL
The URL should contain the ID of the API key you wish to remove.
It replaces the `:id` placeholder in the [endpoints listed above](#endpoints).
## Response status codes
Possible status codes for these endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="200"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | the request lacks authentication |
| <StatusCode status="403"/> | authentication failed |
| <StatusCode status="404"/> | API key not found |
| <StatusCode status="500"/> | server error |
<Note>
If the status code is not <StatusCode status="200" /> the `error` property
in the response body should indicate the nature of the problem.
</Note>
## Response body
| Value | Type | Description |
| ------------------- | -------- | ----------- |
| `result` | `string` | `success` on success, and `error` on error |
| `error` | `string` | Will give info on the nature of the error. Only set if an error occurred. |
| `apikey.key` | `string` | The API key |
| `apikey.level` | `number` | The privilege level of the API key |
| `apikey.expiresAt` | `string` | A string representation of the moment the API key expires |
| `apikey.name` | `string` | The name of the API key |
| `apikey.userId` | `number` | The ID of the user who created the API key |
## Example request
```js
const keyInfo = await axios.get(
'https://backend.freesewing.org/apikeys/7ea12968-7758-40b6-8c73-75cc99be762b/jwt',
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
```
## Example response
```200.json
{
"result": "success",
"apikey": {
"key": "7ea12968-7758-40b6-8c73-75cc99be762b",
"level": 3,
"expiresAt": "2022-11-06T15:57:30.190Z",
"name": "My first API key",
"userId": 61
}
}
```

View file

@ -1,73 +0,0 @@
---
title: Read the current API key
---
Reads the current API key used to authenticate the request.
For obvious reasons, this endpoint is only available with API key authentication.
However, there's an equivalent endpoint for JWT authentication.
## Access control
- [Permission level](/reference/backend/rbac) `0` or higher is required to read the current API key
## Endpoints
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method get /> | `/whoami/key` | [API Key & Secret](/reference/backend/authentication#key-authentication) |
## Response status codes
Possible status codes for these endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="200"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | the request lacks authentication |
| <StatusCode status="403"/> | authentication failed |
| <StatusCode status="500"/> | server error |
<Note>
If the status code is not <StatusCode status="200" /> the `error` property
in the response body should indicate the nature of the problem.
</Note>
## Response body
| Value | Type | Description |
| ------------------- | -------- | ----------- |
| `result` | `string` | `success` on success, and `error` on error |
| `error` | `string` | Will give info on the nature of the error. Only set if an error occurred. |
| `apikey.key` | `string` | The API key |
| `apikey.level` | `number` | The privilege level of the API key |
| `apikey.expiresAt` | `string` | A string representation of the moment the API key expires |
| `apikey.name` | `string` | The name of the API key |
| `apikey.userId` | `number` | The ID of the user who created the API key |
## Example request
```js
const keyInfo = await axios.get(
'https://backend.freesewing.org/whoami/key',
{
auth: {
username: apikey.key,
password: apikey.secret,
}
}
)
```
## Example response
```200.json
{
"result": "success",
"apikey": {
"key": "7ea12968-7758-40b6-8c73-75cc99be762b",
"level": 3,
"expiresAt": "2022-11-06T15:57:30.190Z",
"name": "My first API key",
"userId": 61
}
}

View file

@ -1,64 +0,0 @@
---
title: Authentication
---
The FreeSewing backend API requires authentication for all but a handful of
endpoints.
The API supports two different types of authentication:
| Type | Name | Description |
| ---- | ---- | ----------- |
| [JSON Web Tokens](#jwt-authentication) | `jwt` | This is typically used to authenticate humans in a browser session. |
| [API Keys](#key-authentication) | `key` | This is typically used to interact with the API in an automated way. Like in a script, a CI/CD context, a serverless runner, and so on. |
While the API supports both, they are not supported on the same endpoint.
Instead, add the authentication type you want to use as the final part of
endpoint:
- `/some/endpoint/jwt` : Authenticate with a JSON Web Token
- `/some/endpoint/key` : Authenticate with an API key and secret
## `jwt` authentication
The use of JSON Web Tokens ([jwt](https://jwt.io)) is typically used in a
browser context where we want to establish a *session*.
To get a token, you must first authenticate at the [`/signin`](/reference/backend/account/signin) endpoint.
You will receive a JSON Web Token (jwt) as part of the response.
In subsequent API calls, you must then include this token in the
`Authorization` header prefixed by `Bearer `. Like his:
```js
const account = await axios.get(
`https://backend.freesewing.org/account/jwt`,
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
```
## `key` authentication
The combination of API key & secret serves as a username & password for [HTTP
basic authentication](https://en.wikipedia.org/wiki/Basic_access_authentication).
<Note>
In basic authentication, the password is sent
unencrypted. To guard against this, this API should only be served over a
connection that is encrypted with TLS. (a URL starting with `https://`).
</Note>
Sending a username and password with a request like this is supported
pretty much everywhere. In addition, there is no need to establish a session
first, so this make the entire transaction stateless.
Below is an example using curl:
```sh
curl -u api-key-here:api-secret-here \
https://backend.freesewing.org/account/key
```

View file

@ -1,109 +0,0 @@
---
title: Clone a Pattern
---
Create a new Pattern by cloning an existing one.
## Access control
The [Permission level](/reference/backend/rbac) required to clone a
Pattern depends on:
- Whether the Pattern is `public`
- Who created the Pattern
The details are outlined in the table below:
| | Public Patterns | Non-Public Patterns |
| ---------------: | :-------------: | :-----------------: |
| **Your own** | `0` or higher | `3` or higher |
| **Other user's** | `0` or higher | `5` or higher |
## Endpoints
Creating a new Person is possible via these endpoints:
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method post /> | `/patterns/:id/clone/jwt` | [JSON Web Token](/reference/backend/authentication#jwt-authentication) |
| <Method post /> | `/patterns/:id/clone/key` | [API Key & Secret](/reference/backend/authentication#key-authentication) |
## Request URL
The URL should contain the ID of the Pattern you wish to remove.
It replaces the `:id` placeholder in the [endpoints listed above](#endpoints).
## Response status codes
Possible status codes for these endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="200"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | the request lacks authentication |
| <StatusCode status="403"/> | authentication failed |
| <StatusCode status="500"/> | server error |
<Note>
If the status code is not <StatusCode status="200" /> the `error` property
in the response body should indicate the nature of the problem.
</Note>
## Response body
| Value | Type | Description |
| ------------------- | -------- | ----------- |
| `result` | String | Either `success` or `error` |
| `error` | String | Will give info on the nature of the error. Only set if an error occurred. |
| `pattern.id` | Number | The ID of the Pattern |
| `pattern.createdAt` | String | Date string indicating the moment the pattern was created |
| `pattern.data` | Object | Any additional data that was stored with Pattern data |
| `pattern.design` | String | The name of the design of which this Pattern is an instance |
| `pattern.img` | String | The URL to the image stored with this Pattern |
| `pattern.name` | String | The name of the Pattern |
| `pattern.notes` | String | The notes stored with the Pattern |
| `pattern.personId` | Number | The ID of the Person for whom the Pattern was created |
| `pattern.public` | Boolean| Indicates whether the Pattern is publicly accessible or not |
| `pattern.settings` | Object | The settings used to (re-)create the Pattern |
| `pattern.userId` | Number | The ID of the user who created the Pattern |
| `pattern.updatedAt` | String | Date string indicating the last time the pattern was updated |
## Example request
```js
const clone = axios.post(
'https://backend.freesewing.org/patterns/10/clone/jwt',
null,
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
```
## Example response
```200.json
{
"result": "success",
"pattern": {
"id": 19,
"createdAt": "2022-11-19T16:29:33.346Z",
"data": {
"some": "value"
},
"design": "aaron",
"img": "https://cdn.sanity.io/images/hl5bw8cj/production/a1565c8c6c70cfe7ea0fdf5c65501cd885adbe78-200x187.png",
"name": "Just a test",
"notes": "These are my notes",
"personId": 17,
"public": true,
"settings": {
"sa": 5
},
"userId": 10,
"updatedAt": "2022-11-19T16:29:33.346Z"
}
}
```

View file

@ -1,121 +0,0 @@
---
title: Create a Pattern
---
Creates a new Pattern. This is typically used when users choose to save a pattern.
## Access control
- [Permission level](/reference/backend/rbac) `3` or higher is required to create a Pattern
## Endpoints
Creating a new Pattern is possible via these endpoints:
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method post /> | `/patterns/jwt` | [JSON Web Token](/reference/backend/authentication#jwt-authentication) |
| <Method post /> | `/patterns/key` | [API Key & Secret](/reference/backend/authentication#key-authentication) |
## Request body
The request body is a JSON object with the following properties:
| Property | Type | Description |
| ----------: | :------- | :---------- |
| `data` | `object` | Any additional data to store with the pattern |
| `design` | `string` | The name of the design this Pattern is an instance of |
| `img` | `object` | An image [data-uri][duri] to store with this Pattern |
| `name` | `string` | A name for the Pattern |
| `notes` | `string` | User notes for the pattern |
| `person` | `object` | The ID of the person to associate with this pattern |
| `settings` | `object` | The settings object to (re-)create the Pattern |
## Response status codes
Possible status codes for these endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="201"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | the request lacks authentication |
| <StatusCode status="403"/> | authentication failed |
| <StatusCode status="500"/> | server error |
<Note>
If the status code is not <StatusCode status="201" /> the `error` property
in the response body should indicate the nature of the problem.
</Note>
## Response body
| Value | Type | Description |
| ------------------- | -------- | ----------- |
| `result` | String | Either `success` or `error` |
| `error` | String | Will give info on the nature of the error. Only set if an error occurred. |
| `pattern.id` | Number | The ID of the Pattern |
| `pattern.createdAt` | String | Date string indicating the moment the pattern was created |
| `pattern.data` | Object | Any additional data that was stored with Pattern data |
| `pattern.design` | String | The name of the design of which this Pattern is an instance |
| `pattern.img` | String | The URL to the image stored with this Pattern |
| `pattern.name` | String | The name of the Pattern |
| `pattern.notes` | String | The notes stored with the Pattern |
| `pattern.personId` | Number | The ID of the Person for whom the Pattern was created |
| `pattern.public` | Boolean| Indicates whether the Pattern is publicly accessible or not |
| `pattern.settings` | Object | The settings used to (re-)create the Pattern |
| `pattern.userId` | Number | The ID of the user who created the Pattern |
| `pattern.updatedAt` | String | Date string indicating the last time the pattern was updated |
## Example request
```js
const pattern = await axios.post(
'https://backend.freesewing.org/patterns/jwt',
{
data: {
some: 'value',
}
design: "aaron",
img: "data:image/png;base64,iVBORw0KGgoAAAANSUhEU...truncated",
name: "Just a test",
notes: "These are my notes",
person: 17,
public: true,
settings: {
sa: 5,
},
},
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
```
## Example response
```201.json
{
"result": "success",
"pattern": {
"id": 10,
"createdAt": "2022-11-19T16:29:33.346Z",
"data": {
"some": "value"
},
"design": "aaron",
"img": "https://cdn.sanity.io/images/hl5bw8cj/production/a1565c8c6c70cfe7ea0fdf5c65501cd885adbe78-200x187.png",
"name": "Just a test",
"notes": "These are my notes",
"personId": 17,
"public": true,
"settings": {
"sa": 5
},
"userId": 10,
"updatedAt": "2022-11-19T16:29:35.023Z"
}
}
```
[duri]: https://en.wikipedia.org/wiki/Data_URI_scheme

View file

@ -1,58 +0,0 @@
---
title: Delete a Pattern
---
Deletes an existing Pattern.
## Access control
- [Permission level](/reference/backend/rbac) `3` or higher is required to delete a Pattern
- [Permission level](/reference/backend/rbac) `8` is required to delete **another user's** Pattern
## Endpoints
Deleting a Pattern is possible via these endpoints:
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method delete /> | `/patterns/:id/jwt` | [JSON Web Token](/reference/backend/authentication#jwt-authentication) |
| <Method delete /> | `/patterns/:id/key` | [API Key & Secret](/reference/backend/authentication#key-authentication) |
## Request URL
The URL should contain the ID of the Pattern you wish to remove.
It replaces the `:id` placeholder in the [endpoints listed above](#endpoints).
## Response status codes
Possible status codes for these endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="204"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | the request lacks authentication |
| <StatusCode status="403"/> | authentication failed |
| <StatusCode status="500"/> | server error |
## Example request
```js
await axios.delete(
'https://backend.freesewing.org/patterns/10/jwt',
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
```
## Example response
```204.json
```
<Note>
These endpoints return status code <StatusCode status="204"/> (no content) on
success, with no response body.
</Note>

View file

@ -1,33 +0,0 @@
---
title: Patterns
---
Patterns hold information on and settings for a user's patterns.
## Endpoints
<ReadMore />
## Notes
### The `design` property should hold the design
The `design` property should hold the name of the FreeSewing design.
For example, `aaron`.
### The `notes` vs `data` properties
Both the `data` and `notes` properties can hold additional information about
the pattern.
Keep in mind that:
- The `notes` property is intended to be used by the user to add notes about
their pattern. It will only accept data of type `string`.
- The `data` property is intended to allow frontend developers to store
additional data about the pattern. It will only accept data of type `object`.
### The `settings` property should hold the pattern settings
The `settings` property should hold [a settings object](/reference/settings)
that can be passed to [the Pattern
constructor](/reference/api/pattern#creating-a-pattern).

View file

@ -1,109 +0,0 @@
---
title: Read a Pattern
---
Reads an existing Pattern.
## Access control
The [Permission level](/reference/backend/rbac) required to read a
Pattern depends on:
- Whether the Pattern is `public`
- Who created the Pattern
The details are outlined in the table below:
| | Public Patterns | Non-Public Patterns |
| ---------------: | :-------------: | :-----------------: |
| **Your own** | `0` or higher | `1` or higher |
| **Other user's** | `0` or higher | `5` or higher |
## Endpoints
Reading a Pattern is possible via these endpoints:
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method get /> | `/patterns/:id/jwt` | [JSON Web Token](/reference/backend/authentication#jwt-authentication) |
| <Method get /> | `/patterns/:id/key` | [API Key & Secret](/reference/backend/authentication#key-authentication) |
## Request URL
The URL should contain the ID of the Pattern you wish to read.
It replaces the `:id` placeholder in the [endpoints listed above](#endpoints).
## Response status codes
Possible status codes for these endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="200"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | the request lacks authentication |
| <StatusCode status="403"/> | authentication failed |
| <StatusCode status="404"/> | API key not found |
| <StatusCode status="500"/> | server error |
<Note>
If the status code is not <StatusCode status="200" /> the `error` property
in the response body should indicate the nature of the problem.
</Note>
## Response body
| Value | Type | Description |
| ------------------- | -------- | ----------- |
| `result` | String | Either `success` or `error` |
| `error` | String | Will give info on the nature of the error. Only set if an error occurred. |
| `pattern.id` | Number | The ID of the Pattern |
| `pattern.createdAt` | String | Date string indicating the moment the pattern was created |
| `pattern.data` | Object | Any additional data that was stored with Pattern data |
| `pattern.design` | String | The name of the design of which this Pattern is an instance |
| `pattern.img` | String | The URL to the image stored with this Pattern |
| `pattern.name` | String | The name of the Pattern |
| `pattern.notes` | String | The notes stored with the Pattern |
| `pattern.personId` | Number | The ID of the Person for whom the Pattern was created |
| `pattern.public` | Boolean| Indicates whether the Pattern is publicly accessible or not |
| `pattern.settings` | Object | The settings used to (re-)create the Pattern |
| `pattern.userId` | Number | The ID of the user who created the Pattern |
| `pattern.updatedAt` | String | Date string indicating the last time the pattern was updated |
## Example request
```js
const pattern = await axios.get(
'https://backend.freesewing.org/patterns/10/jwt',
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
```
## Example response
```200.json
{
"result": "success",
"pattern": {
"id": 10,
"createdAt": "2022-11-19T16:29:33.346Z",
"data": {
"some": "value"
},
"design": "aaron",
"img": "https://cdn.sanity.io/images/hl5bw8cj/production/a1565c8c6c70cfe7ea0fdf5c65501cd885adbe78-200x187.png",
"name": "Just a test",
"notes": "These are my notes",
"personId": 17,
"public": true,
"settings": {
"sa": 5
},
"userId": 10,
"updatedAt": "2022-11-19T16:29:35.023Z"
}
}
```

View file

@ -1,118 +0,0 @@
---
title: Update a Pattern
---
Updates an existing Pattern.
## Access control
- [Permission level](/reference/backend/rbac) `3` or higher is required to update a Pattern
- [Permission level](/reference/backend/rbac) `8` is required to update **another user's** Pattern
## Endpoints
Updating an existing Pattern is possible via these endpoints:
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method put /> | `/patterns/:id/jwt` | [JSON Web Token](/reference/backend/authentication#jwt-authentication) |
| <Method put /> | `/patterns/:id/key` | [API Key & Secret](/reference/backend/authentication#key-authentication) |
## Request URL
The URL should contain the ID of the Pattern you wish to remove.
It replaces the `:id` placeholder in the [endpoints listed above](#endpoints).
## Request body
| Property | Type | Description |
| ----------: | :------- | :---------- |
| `data` | `object` | Any additional data to store with the pattern |
| `design` | `string` | The name of the design this Pattern is an instance of |
| `img` | `object` | An image [data-uri][duri] to store with this Pattern |
| `name` | `string` | A name for the Pattern |
| `notes` | `string` | User notes for the pattern |
| `person` | `object` | The ID of the person to associate with this pattern |
| `settings` | `object` | The settings object to (re-)create the Pattern |
## Response status codes
Possible status codes for these endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="200"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | the request lacks authentication |
| <StatusCode status="403"/> | authentication failed |
| <StatusCode status="500"/> | server error |
<Note>
If the status code is not <StatusCode status="200" /> the `error` property
in the response body should indicate the nature of the problem.
</Note>
## Response body
| Value | Type | Description |
| ------------------- | -------- | ----------- |
| `result` | String | Either `success` or `error` |
| `error` | String | Will give info on the nature of the error. Only set if an error occurred. |
| `pattern.id` | Number | The ID of the Pattern |
| `pattern.createdAt` | String | Date string indicating the moment the pattern was created |
| `pattern.data` | Object | Any additional data that was stored with Pattern data |
| `pattern.design` | String | The name of the design of which this Pattern is an instance |
| `pattern.img` | String | The URL to the image stored with this Pattern |
| `pattern.name` | String | The name of the Pattern |
| `pattern.notes` | String | The notes stored with the Pattern |
| `pattern.personId` | Number | The ID of the Person for whom the Pattern was created |
| `pattern.public` | Boolean| Indicates whether the Pattern is publicly accessible or not |
| `pattern.settings` | Object | The settings used to (re-)create the Pattern |
| `pattern.userId` | Number | The ID of the user who created the Pattern |
| `pattern.updatedAt` | String | Date string indicating the last time the pattern was updated |
## Example request
```js
const udpate = await axios.put(
'https://backend.freesewing.org/patterns/10/jwt',
{
data: {
some: 'new value',
}
public: false,
},
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
```
## Example response
```200.json
{
"result": "success",
"pattern": {
"id": 10,
"createdAt": "2022-11-19T16:29:33.346Z",
"data": {
"some": "new value"
},
"design": "aaron",
"img": "https://cdn.sanity.io/images/hl5bw8cj/production/a1565c8c6c70cfe7ea0fdf5c65501cd885adbe78-200x187.png",
"name": "Just a test",
"notes": "These are my notes",
"personId": 17,
"public": false,
"settings": {
"sa": 5
},
"userId": 10,
"updatedAt": "2022-11-19T16:43:39.223Z"
}
}
```
[duri]: https://en.wikipedia.org/wiki/Data_URI_scheme

View file

@ -1,103 +0,0 @@
---
title: Clone a Person
---
Create a new Person by cloning an existing one.
## Access control
The [Permission level](/reference/backend/rbac) required to clone a
Person depends on:
- Whether the Person is `public`
- Who created the Pattern
The details are outlined in the table below:
| | Public Patterns | Non-Public Patterns |
| ---------------: | :-------------: | :-----------------: |
| **Your own** | `0` or higher | `3` or higher |
| **Other user's** | `0` or higher | `5` or higher |
## Endpoints
Creating a new Person is possible via these endpoints:
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method post /> | `/people/:id/clone/jwt` | [JSON Web Token](/reference/backend/authentication#jwt-authentication) |
| <Method post /> | `/people/:id/clone/key` | [API Key & Secret](/reference/backend/authentication#key-authentication) |
## Request URL
The URL should contain the ID of the Person you wish to remove.
It replaces the `:id` placeholder in the [endpoints listed above](#endpoints).
## Response status codes
Possible status codes for these endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="200"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | the request lacks authentication |
| <StatusCode status="403"/> | authentication failed |
| <StatusCode status="500"/> | server error |
<Note>
If the status code is not <StatusCode status="200" /> the `error` property
in the response body should indicate the nature of the problem.
</Note>
## Response body
| Value | Type | Description |
| ------------------- | -------- | ----------- |
| `result` | String | Either `success` or `error` |
| `error` | String | Will give info on the nature of the error. Only set if an error occurred. |
| `person.id` | Number | The ID of the Person |
| `person.createdAt` | String | Date string indicating the moment the Person was created |
| `person.img` | String | The URL to the image stored with this Person |
| `person.name` | String | The name of the Person |
| `person.notes` | String | The notes stored with the Person |
| `person.userId` | Number | The ID of the user who created the Person |
| `person.measies` | Object | The measurements of the Person |
| `person.public` | Boolean| Indicates whether the Person is publicly accessible or not |
| `person.updatedAt` | String | Date string indicating the last time the Person was updated |
## Example request
```js
const clone = axios.post(
'https://backend.freesewing.org/people/27/clone/jwt',
null,
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
```
## Example response
```200.json
{
"result": "success",
"person": {
"id": 32,
"createdAt": "2022-11-19T17:36:41.342Z",
"img": "https://cdn.sanity.io/images/hl5bw8cj/production/a1565c8c6c70cfe7ea0fdf5c65501cd885adbe78-200x187.png",
"imperial": false,
"name": "Someone",
"notes": "These are some notes",
"userId": 12,
"measies": {
"chest": 930,
"neck": 360
},
"public": true,
"updatedAt": "2022-11-19T17:36:41.342Z"
}
}
```

View file

@ -1,110 +0,0 @@
---
title: Create a Person
---
Creates a new Person.
## Access control
- [Permission level](/reference/backend/rbac) `3` or higher is required to create a Person
## Endpoints
Creating a new Person is possible via these endpoints:
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method post /> | `/people/jwt` | [JSON Web Token](/reference/backend/authentication#jwt-authentication) |
| <Method post /> | `/people/key` | [API Key & Secret](/reference/backend/authentication#key-authentication) |
## Request body
| Property | Type | Description |
| ----------: | :------- | :---------- |
| `img` | `string` | An image [data-uri][duri] to store with this Person |
| `imperial` | `boolean`| Whether this Person prefers imperial measurements (`true`) or not (`false`) |
| `name` | `string` | A name for the Person |
| `notes` | `string` | User notes for the person |
| `measies` | `object` | The measurements for this person |
| `public` | `string` | The name of the design this Pattern is an instance of |
## Response status codes
Possible status codes for these endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="201"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | the request lacks authentication |
| <StatusCode status="403"/> | authentication failed |
| <StatusCode status="500"/> | server error |
<Note>
If the status code is not <StatusCode status="201" /> the `error` property
in the response body should indicate the nature of the problem.
</Note>
## Response body
| Value | Type | Description |
| ------------------- | -------- | ----------- |
| `result` | String | Either `success` or `error` |
| `error` | String | Will give info on the nature of the error. Only set if an error occurred. |
| `person.id` | Number | The ID of the Person |
| `person.createdAt` | String | Date string indicating the moment the Person was created |
| `person.img` | String | The URL to the image stored with this Person |
| `person.name` | String | The name of the Person |
| `person.notes` | String | The notes stored with the Person |
| `person.userId` | Number | The ID of the user who created the Person |
| `person.measies` | Object | The measurements of the Person |
| `person.public` | Boolean| Indicates whether the Person is publicly accessible or not |
| `person.updatedAt` | String | Date string indicating the last time the Person was updated |
## Example request
```js
const person = await axios.post(
'https://backend.freesewing.org/people/jwt',
{
name: "Someone",
notes: "These are some notes",
measies: {
"chest": 930,
"neck": 360
},
public: true,
imperial: false,
img: "data:image/png;base64,iVBORw0KGgoAAAANSUhEU...truncated"
},
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
```
## Example response
```201.json
{
"result": "success",
"person": {
"id": 27,
"createdAt": "2022-11-19T17:36:41.342Z",
"img": "https://cdn.sanity.io/images/hl5bw8cj/production/a1565c8c6c70cfe7ea0fdf5c65501cd885adbe78-200x187.png",
"imperial": false,
"name": "Someone",
"notes": "These are some notes",
"userId": 12,
"measies": {
"chest": 930,
"neck": 360
},
"public": true,
"updatedAt": "2022-11-19T17:36:41.342Z"
}
}
```
[duri]: https://en.wikipedia.org/wiki/Data_URI_scheme

View file

@ -1,58 +0,0 @@
---
title: Delete a Person
---
Deletes an existing Person.
## Access control
- [Permission level](/reference/backend/rbac) `3` or higher is required to delete a Person
- [Permission level](/reference/backend/rbac) `8` is required to delete **another user's** Person
## Endpoints
Deleting a Person is possible via these endpoints:
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method delete /> | `/people/:id/jwt` | [JSON Web Token](/reference/backend/authentication#jwt-authentication) |
| <Method delete /> | `/people/:id/key` | [API Key & Secret](/reference/backend/authentication#key-authentication) |
## Request URL
The URL should contain the ID of the Person you wish to remove.
It replaces the `:id` placeholder in the [endpoints listed above](#endpoints).
## Response status codes
Possible status codes for these endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="204"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | the request lacks authentication |
| <StatusCode status="403"/> | authentication failed |
| <StatusCode status="500"/> | server error |
## Example request
```js
await axios.delete(
'https://backend.freesewing.org/people/27/jwt',
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
```
## Example response
```204.json
```
<Note>
These endpoints return status code <StatusCode status="204"/> (no content) on
success, with no response body.
</Note>

View file

@ -1,44 +0,0 @@
---
title: People
---
A Person hold information and measurements on the people we generate patterns
for.
## Endpoints
<ReadMore />
## Notes
### The `imperial` property is a Boolean
- If the `imperial` property is `false`, the person wants metric units.
- If the `imperial` property is `true`, the person wants imperial units.
### The `measies` property holds measurements
These measurements should be structured as an object that can be used for the
`measurements` key in the [pattern settings
object](/reference/settings/measurements).
The backend will only accept known measurements listed in the configuration file.
<Comment by="joost">
##### Why we use measies instead of measurements
First of all, _measies_ is a cute and adorable alternative for _measurements_
coined by Karen. She deserves all the credit.
But also, I am slightly dyslexic and for some reason, I often drop the middle
_e_ when typing measurements' (sic).
Those typos lead to bugs and I find it much easier to write _measies_.
So because fewer bugs, plus did I mention it's cute?
</Comment>
### The `settings` property should hold the pattern settings
The `settings` property should hold [a settings object](/reference/settings)
that can be passed to [the Pattern
constructor](/reference/api/pattern#creating-a-pattern).

View file

@ -1,103 +0,0 @@
---
title: Read a Person
---
Reads an existing Person.
## Access control
The [Permission level](/reference/backend/rbac) required to read a
Person depends on:
- Whether the Person is `public`
- Who created the Person
The details are outlined in the table below:
| | Public People | Non-Public People |
| ---------------: | :-------------: | :-----------------: |
| **Your own** | `0` or higher | `4` or higher |
| **Other user's** | `0` or higher | `5` or higher |
## Endpoints
Reading a Person is possible via these endpoints:
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method get /> | `/people/:id/jwt` | [JSON Web Token](/reference/backend/authentication#jwt-authentication) |
| <Method get /> | `/people/:id/key` | [API Key & Secret](/reference/backend/authentication#key-authentication) |
## Request url
The url should contain the ID of the Person you wish to read.
It replaces the `:id` placeholder in the [endpoints listed above](#endpoints).
## Response status codes
Possible status codes for these endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="200"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | the request lacks authentication |
| <StatusCode status="403"/> | authentication failed |
| <StatusCode status="404"/> | API key not found |
| <StatusCode status="500"/> | server error |
<Note>
If the status code is not <StatusCode status="200" /> the `error` property
in the response body should indicate the nature of the problem.
</Note>
## Response body
| Value | Type | Description |
| ------------------- | -------- | ----------- |
| `result` | String | Either `success` or `error` |
| `error` | String | Will give info on the nature of the error. Only set if an error occurred. |
| `person.id` | Number | The ID of the Person |
| `person.createdAt` | String | Date string indicating the moment the Person was created |
| `person.img` | String | The URL to the image stored with this Person |
| `person.name` | String | The name of the Person |
| `person.notes` | String | The notes stored with the Person |
| `person.userId` | Number | The ID of the user who created the Person |
| `person.measies` | Object | The measurements of the Person |
| `person.public` | Boolean| Indicates whether the Person is publicly accessible or not |
| `person.updatedAt` | String | Date string indicating the last time the Person was updated |
## Example request
```js
const person = await axios.get(
'https://backend.freesewing.org/people/27/jwt',
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
```
## Example response
```200.json
{
"result": "success",
"person": {
"id": 27,
"createdAt": "2022-11-19T17:36:41.342Z",
"img": "https://cdn.sanity.io/images/hl5bw8cj/production/a1565c8c6c70cfe7ea0fdf5c65501cd885adbe78-200x187.png",
"imperial": false,
"name": "Someone",
"notes": "These are some notes",
"userId": 12,
"measies": {
"chest": 930,
"neck": 360
},
"public": true,
"updatedAt": "2022-11-19T17:36:41.342Z"
}
}
```

View file

@ -1,109 +0,0 @@
---
title: Update a Person
---
Updates an existing Person.
## Access control
- [Permission level](/reference/backend/rbac) `3` or higher is required to update a Person
- [Permission level](/reference/backend/rbac) `8` is required to update **another user's** Person
## Endpoints
Updating an existing Person is possible via these endpoints:
| Method | Path | Authentication |
| --------: | :--- | :------------- |
| <Method put /> | `/people/:id/jwt` | [JSON Web Token](/reference/backend/authentication#jwt-authentication) |
| <Method put /> | `/people/:id/key` | [API Key & Secret](/reference/backend/authentication#key-authentication) |
## Request URL
The URL should contain the ID of the Person you wish to remove.
It replaces the `:id` placeholder in the [endpoints listed above](#endpoints).
## Request body
| Property | Type | Description |
| ----------: | :------- | :---------- |
| `img` | `string` | An image [data-uri][duri] to store with this Person |
| `imperial` | `boolean`| Whether this Person prefers imperial measurements (`true`) or not (`false`) |
| `name` | `string` | A name for the Person |
| `notes` | `string` | User notes for the person |
| `measies` | `object` | The measurements for this person |
| `public` | `string` | The name of the design this Pattern is an instance of |
## Response status codes
Possible status codes for these endpoints are:
| Status code | Description |
| ----------: | :---------- |
| <StatusCode status="200"/> | success |
| <StatusCode status="400"/> | the request was malformed |
| <StatusCode status="401"/> | the request lacks authentication |
| <StatusCode status="403"/> | authentication failed |
| <StatusCode status="500"/> | server error |
<Note>
If the status code is not <StatusCode status="200" /> the `error` property
in the response body should indicate the nature of the problem.
</Note>
## Response body
| Value | Type | Description |
| ------------------- | -------- | ----------- |
| `result` | String | Either `success` or `error` |
| `error` | String | Will give info on the nature of the error. Only set if an error occurred. |
| `person.id` | Number | The ID of the Person |
| `person.createdAt` | String | Date string indicating the moment the Person was created |
| `person.img` | String | The URL to the image stored with this Person |
| `person.name` | String | The name of the Person |
| `person.notes` | String | The notes stored with the Person |
| `person.userId` | Number | The ID of the user who created the Person |
| `person.measies` | Object | The measurements of the Person |
| `person.public` | Boolean| Indicates whether the Person is publicly accessible or not |
| `person.updatedAt` | String | Date string indicating the last time the Person was updated |
## Example request
```js
const udpate = await axios.put(
'https://backend.freesewing.org/people/27/jwt',
{
notes: "Turns out some people like imperial",
imperial: true,
},
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
```
## Example response
```200.json
{
"result": "success",
"person": {
"id": 27,
"createdAt": "2022-11-19T17:36:41.342Z",
"img": "https://cdn.sanity.io/images/hl5bw8cj/production/a1565c8c6c70cfe7ea0fdf5c65501cd885adbe78-200x187.png",
"imperial": true,
"name": "Someone",
"notes": "Turns out some people like imperial",
"userId": 12,
"measies": {
"chest": 930,
"neck": 360
},
"public": true,
"updatedAt": "2022-11-19T17:36:41.342Z"
}
}
```
[duri]: https://en.wikipedia.org/wiki/Data_URI_scheme

Some files were not shown because too many files have changed in this diff Show more