First Layout
Build a working GDS in ten minutes. Cell, polygon, port, write, view.
This guide picks up right after Installation.
You already have a project created with rosette init. Now you will write
your first design script, build a GDS file, and view it in the browser.
If any of the concepts below feel new, skim the Core Concepts page first. Everything on this page is explained there in more depth.
Create a design file
After rosette init your project has an empty designs/ directory.
Create a new Python file there:
touch designs/hello.pyOpen designs/hello.py in your editor and add the following:
# designs/hello.py
from rosette import Cell, Layer, Point, Polygon, Port, Vector2
from rosette.io import write_gds
# 1. Create a top-level cell.
top = Cell("hello")
# 2. Add a waveguide: a 50 x 0.5 um rectangle on layer 1/0.
wg = Polygon.rect(Point(0, -0.25), 50, 0.5)
top.add_polygon(wg, Layer(1, 0))
# 3. Add a label on layer 10/0.
top.add_text("hello", Point(0, 2), Layer(10, 0), height=1.0)
# 4. Mark the waveguide endpoints as ports.
top.add_port(Port("in", Point(0, 0), Vector2(-1, 0), width=0.5))
top.add_port(Port("out", Point(50, 0), Vector2( 1, 0), width=0.5))
# 5. Write it to GDS.
write_gds("output/hello.gds", top)That is everything, five short steps. Let's break down what each line does before we run it.
What's going on
Cell("hello")creates an emptyCellnamedhello. This is your top-level design.Polygon.rect(origin, width, height)builds a rectangle whose lower-left corner sits atorigin. Centering it ony = 0makes the waveguide symmetric about the X axis.Layer(1, 0)is GDS layer1/0. The CLI's default config treats layer1/0as the silicon waveguide layer and layer10/0as text.add_textwrites a label on the text layer. Labels are useful for debugging and are typically not fabricated.Port(name, position, direction, width)marks a connection point.directionis a unit vector pointing outward from the component. The input faces-X, the output faces+X. Width matches the waveguide.write_gdsserializes the cell to a GDS file.
Build and view
You have two ways to see the result: build a GDS file and open it in the viewer, or run the dev server for live reload while you edit.
Running rosette commands with uv
The examples below use uv run, which guarantees the command and design import
the project-local Rosette version. If you installed via uv tool install librosette or inside an activated pip venv, you can omit the uv run prefix.
Live preview (recommended)
uv run rosette serve designs/hello.pyThe dev server opens http://localhost:5173/preview in your browser with an
interactive WebGPU viewer. Every time you save designs/hello.py the
viewer reloads automatically, so you can tweak the script and see the
result immediately. The Python file remains the source of truth, so the live
viewer is read-only. Use Edit a copy when you intentionally want to detach
the rendered layout into an editable app document. See
Editing and Persistence for the full
save and export contract.
One-shot build
If you just want the GDS file:
uv run rosette build designs/hello.pyThe output is written to output/hello.gds. Open it later with
uv run rosette run output/hello.gds.
What you should see
A 50 um long, 0.5 um wide pink rectangle centered on the X axis, with the
word hello rendered just above it on a different layer. Two port markers
sit at the ends of the waveguide, pointing outward.
Build summary
uv run rosette build and write_gds print a short summary to the terminal:
cell count, polygon count, and output path. If nothing shows up, pass
verbose=True to write_gds for a more detailed breakdown, including
port positions.
Extend it
Now that you have a working build, try a few small edits and watch them update live:
- Change the rectangle's width to
100to make a longer waveguide. - Add a second
Celland reference it fromtopwithtop.add_ref(child.at(x, y)). See the Cells & Hierarchy guide. - Replace the hand-built rectangle with a connected
Routebetween two ports. See the Routing guide. - Define named layers in
rosette.tomland load them withload_layer_map()so you can writelayers.silicon.layerinstead ofLayer(1, 0).