Compare commits

..

No commits in common. "19ea597528d412408ea175952fb7a3d2f66e86cf" and "cc5fb290ecd95c12686916101de58785ac42ddee" have entirely different histories.

27 changed files with 378 additions and 800 deletions

79
Makefile Normal file
View file

@ -0,0 +1,79 @@
PY?=
PELICAN?=pelican
PELICANOPTS=
BASEDIR=$(CURDIR)
INPUTDIR=$(BASEDIR)/content
OUTPUTDIR=$(BASEDIR)/output
CONFFILE=$(BASEDIR)/pelicanconf.py
PUBLISHCONF=$(BASEDIR)/publishconf.py
DEBUG ?= 0
ifeq ($(DEBUG), 1)
PELICANOPTS += -D
endif
RELATIVE ?= 0
ifeq ($(RELATIVE), 1)
PELICANOPTS += --relative-urls
endif
SERVER ?= "0.0.0.0"
PORT ?= 0
ifneq ($(PORT), 0)
PELICANOPTS += -p $(PORT)
endif
help:
@echo 'Makefile for a pelican Web site '
@echo ' '
@echo 'Usage: '
@echo ' make html (re)generate the web site '
@echo ' make clean remove the generated files '
@echo ' make regenerate regenerate files upon modification '
@echo ' make publish generate using production settings '
@echo ' make serve [PORT=8000] serve site at http://localhost:8000'
@echo ' make serve-global [SERVER=0.0.0.0] serve (as root) to $(SERVER):80 '
@echo ' make devserver [PORT=8000] serve and regenerate together '
@echo ' make devserver-global regenerate and serve on 0.0.0.0 '
@echo ' make mail file=FILEPATH generate HTML email '
@echo ' '
@echo 'Set the DEBUG variable to 1 to enable debugging, e.g. make DEBUG=1 html '
@echo 'Set the RELATIVE variable to 1 to enable relative urls '
@echo ' '
html:
"$(PELICAN)" "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS)
clean:
[ ! -d "$(OUTPUTDIR)" ] || rm -rf "$(OUTPUTDIR)"
regenerate:
"$(PELICAN)" -r "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS)
serve:
"$(PELICAN)" -l "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS)
serve-global:
"$(PELICAN)" -l "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS) -b $(SERVER)
devserver:
"$(PELICAN)" -lr "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS)
devserver-global:
"$(PELICAN)" -lr "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS) -b 0.0.0.0
publish:
"$(PELICAN)" "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(PUBLISHCONF)" $(PELICANOPTS)
rsync -e ssh -av --delete-after /Users/pascal/Documents/craft-letter/output/ craftletter@ssh-craftletter.alwaysdata.net:/home/craftletter/www
ssh:
ssh craftletter@ssh-craftletter.alwaysdata.net
mail:
PYTHONPATH=PWD venv/bin/python ./prepare_email.py $(file)
.PHONY: html help clean regenerate serve serve-global devserver devserver-global publish mail

BIN
content/.DS_Store vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

View file

@ -1,157 +1,70 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Created with Inkscape (http://www.inkscape.org/) --> <!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg <svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="191.23006mm" width="629.69px" height="136.735px" viewBox="0 0 629.69 136.735" enable-background="new 0 0 629.69 136.735"
height="29.989243mm" xml:space="preserve">
viewBox="0 0 191.23006 29.989242" <g>
version="1.1" <g>
id="svg1" <path fill="#00819E" d="M37.601,5.57c5.764,0,10.667,0.764,14.709,2.292c4.042,1.529,7.746,3.685,11.112,6.47L54.079,25.59
sodipodi:docname="horizontal.svg" c-2.205-1.818-4.642-3.259-7.311-4.323c-2.669-1.064-5.571-1.596-8.704-1.596c-3.365,0-6.441,0.958-9.226,2.873
inkscape:version="1.4.3 (0d15f75, 2025-12-25)" c-2.785,1.914-5.01,4.932-6.673,9.051c-1.664,4.12-2.495,9.468-2.495,16.044c0,9.671,1.75,16.702,5.25,21.092
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" s7.999,6.585,13.491,6.585c4.023,0,7.37-0.754,10.038-2.264c2.67-1.508,5.126-3.152,7.37-4.932l8.646,11.024
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" c-3.017,2.979-6.731,5.533-11.141,7.66c-4.41,2.127-9.729,3.192-15.957,3.192c-7.273,0-13.722-1.617-19.351-4.847
xmlns="http://www.w3.org/2000/svg" c-5.628-3.229-10.038-7.986-13.23-14.273C1.596,64.592,0,56.846,0,47.639c0-8.974,1.653-16.595,4.96-22.862
xmlns:svg="http://www.w3.org/2000/svg"> c3.308-6.267,7.805-11.034,13.492-14.303C24.138,7.205,30.521,5.57,37.601,5.57z"/>
<sodipodi:namedview <path fill="#00819E" d="M74.387,88.024V75.723h8.123V38.587h-8.123V26.401h22.107l3.365,13.868
id="namedview1" c2.206-5.299,5.02-9.244,8.443-11.836c3.423-2.591,7.61-3.888,12.563-3.888c2.088,0,3.945,0.165,5.571,0.493
pagecolor="#ffffff" c1.625,0.329,3.152,0.783,4.583,1.364l-3.423,25.764h-11.489V40.792c-3.481,0.619-6.538,2.504-9.167,5.657
bordercolor="#000000" c-2.631,3.154-4.662,7.031-6.093,11.634v17.64h12.186v12.302H74.387z"/>
borderopacity="0.25" <path fill="#00819E" d="M195.31,70.269c0,2.32,0.319,4.004,0.958,5.048c0.638,1.044,1.672,1.839,3.104,2.379l-3.771,12.069
inkscape:showpageshadow="2" c-3.637-0.348-6.702-1.151-9.198-2.408c-2.495-1.257-4.458-3.163-5.889-5.715c-2.36,2.823-5.377,4.923-9.052,6.297
inkscape:pageopacity="0.0" c-3.675,1.372-7.427,2.06-11.257,2.06c-6.344,0-11.401-1.811-15.173-5.427c-3.771-3.616-5.657-8.27-5.657-13.955
inkscape:pagecheckerboard="0" c0-6.691,2.62-11.856,7.862-15.493c5.241-3.635,12.621-5.454,22.137-5.454h8.297v-2.321c0-6.304-4.061-9.458-12.185-9.458
inkscape:deskcolor="#d1d1d1" c-1.973,0-4.507,0.281-7.601,0.841c-3.096,0.561-6.19,1.364-9.284,2.408l-4.236-12.186c3.984-1.509,8.133-2.649,12.447-3.423
inkscape:document-units="mm" c4.313-0.773,8.171-1.161,11.576-1.161c9.167,0,15.947,1.866,20.338,5.6c4.39,3.733,6.585,9.12,6.585,16.159V70.269z
showguides="true" M166.53,76.882c1.973,0,4.042-0.589,6.209-1.768c2.166-1.18,3.81-2.854,4.931-5.02v-9.98h-4.526
inkscape:zoom="2.0186728" c-5.105,0-8.858,0.783-11.256,2.35c-2.399,1.566-3.598,3.858-3.598,6.875c0,2.36,0.725,4.207,2.176,5.541
inkscape:cx="367.32054" C161.917,76.217,163.938,76.882,166.53,76.882z"/>
inkscape:cy="111.70706" <path fill="#00819E" d="M252.289,0c4.487,0,8.451,0.357,11.895,1.074c3.442,0.716,6.518,1.653,9.227,2.814l-5.049,11.954
inkscape:window-width="2560" c-2.127-0.813-4.313-1.402-6.556-1.771c-2.244-0.367-4.468-0.551-6.673-0.551c-3.637,0-6.238,0.659-7.804,1.974
inkscape:window-height="1351" c-1.567,1.315-2.351,3.501-2.351,6.557v8.24h20.077l-2.031,12.707h-18.046v45.028h-17.866l-0.064-44.74l-13.228-0.289V30.29
inkscape:window-x="-9" h12.939v-8.937c0-4.061,0.966-7.697,2.9-10.908c1.935-3.211,4.797-5.753,8.589-7.63C242.039,0.938,246.719,0,252.289,0z"/>
inkscape:window-y="-9" <path fill="#00819E" d="M308.438,84.997c-2.399,1.547,1.767,3.918-1.636,5.001c-3.405,1.082,6.423-0.54,2.167-0.54
inkscape:window-maximized="1" c-8.047,0-5.02-1.52-8.927-5.641c-3.907-4.12-5.859-9.719-5.859-16.799V39.051h-12.941V26.401h12.941V13.056l18.335-2.205v15.551
inkscape:current-layer="g18"> h19.844l-1.799,12.649h-18.045v27.968c0,3.057,0.696,5.242,2.088,6.558c1.394,1.314,3.617,1.973,6.673,1.973
<sodipodi:guide c2.167,0,4.149-0.261,5.948-0.783c1.799-0.521-11.841-0.48-10.409-1.294L308.438,84.997z"/>
position="60.83391,3.6250775" </g>
orientation="0,-1" <g>
id="guide22" <path fill="#00819E" d="M227.004,134.764V54.34h17.974l0.125,65.393h35.808l-1.973,15.03H227.004z"/>
inkscape:locked="false" /> <path fill="#00819E" d="M309.862,109.288c0.619,5.031,2.263,8.638,4.933,10.823c2.668,2.186,5.957,3.277,9.864,3.277
</sodipodi:namedview> c2.823,0,5.551-0.463,8.182-1.392c2.63-0.928,5.164-2.165,7.602-3.714l7.37,9.98c-2.902,2.477-6.412,4.508-10.532,6.093
<defs c-4.12,1.587-8.811,2.379-14.072,2.379c-7.041,0-12.939-1.403-17.697-4.205c-4.759-2.807-8.337-6.664-10.735-11.578
id="defs1" /> c-2.398-4.911-3.597-10.56-3.597-16.943c0-6.072,1.16-11.594,3.481-16.565c2.321-4.971,5.715-8.936,10.184-11.896
<g c4.468-2.958,9.931-4.437,16.392-4.437c5.881,0,10.977,1.256,15.29,3.771c4.313,2.514,7.659,6.131,10.038,10.851
inkscape:label="Calque 1" c2.379,4.721,3.569,10.387,3.569,17.001c0,1.045-0.031,2.167-0.088,3.366c-0.058,1.199-0.146,2.263-0.261,3.189H309.862z
inkscape:groupmode="layer" M321.235,83.41c-3.288,0-5.938,1.181-7.949,3.54c-2.012,2.36-3.23,6.132-3.656,11.315h22.63
id="layer1"> c-0.039-4.487-0.909-8.085-2.611-10.794C327.946,84.765,325.142,83.41,321.235,83.41z"/>
<g <path fill="#00819E" d="M419.065,131.165c-2.4,1.55-5.301,2.862-8.705,3.946c-3.404,1.082-7.232,1.624-11.487,1.624
id="g19" c-8.047,0-14.022-2.061-17.93-6.18c-3.908-4.118-5.861-9.718-5.861-16.798V85.789h-12.939V73.14h12.939V59.794l18.335-2.206V73.14
transform="translate(-6.494133,-6.033493)"> h19.847l-1.799,12.649h-18.048v27.969c0,3.057,0.696,5.242,2.09,6.556c1.394,1.316,3.616,1.974,6.673,1.974
<rect c2.167,0,4.149-0.261,5.949-0.782c1.799-0.522,3.412-1.191,4.844-2.003L419.065,131.165z"/>
style="fill:#249bb3;fill-opacity:1;stroke-width:0.23553" <path fill="#00819E" d="M488.692,131.165c-2.397,1.55-5.3,2.862-8.701,3.946c-3.406,1.082-7.234,1.624-11.492,1.624
id="rect26-3-6" c-8.044,0-14.021-2.061-17.928-6.18c-3.907-4.118-5.861-9.718-5.861-16.798V85.789h-12.938V73.14h12.938V59.794l18.335-2.206
width="95.615021" V73.14h19.847l-1.798,12.649h-18.049v27.969c0,3.057,0.696,5.242,2.091,6.556c1.394,1.316,3.616,1.974,6.673,1.974
height="29.989243" c2.167,0,4.149-0.261,5.948-0.782c1.799-0.522,3.413-1.191,4.843-2.003L488.692,131.165z"/>
x="6.494133" <path fill="#00819E" d="M518.748,109.288c0.62,5.031,2.266,8.638,4.933,10.823c2.67,2.186,5.957,3.277,9.864,3.277
y="6.033493" c2.824,0,5.551-0.463,8.181-1.392c2.631-0.928,5.166-2.165,7.603-3.714l7.37,9.98c-2.9,2.477-6.413,4.508-10.531,6.093
ry="0.008925369" /> c-4.122,1.587-8.812,2.379-14.072,2.379c-7.042,0-12.938-1.403-17.699-4.205c-4.758-2.807-8.336-6.664-10.733-11.578
<path c-2.399-4.911-3.598-10.56-3.598-16.943c0-6.072,1.161-11.594,3.481-16.565c2.32-4.971,5.716-8.936,10.184-11.896
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699" c4.47-2.958,9.933-4.437,16.394-4.437c5.879,0,10.974,1.256,15.289,3.771c4.313,2.514,7.658,6.131,10.037,10.851
d="m 96.399823,31.800868 c -0.61408,0.40592 -0.66317,0.4146 -1.53746,0.6748 -0.87429,0.26021 -1.82143,0.39031 -2.84143,0.39031 -2.01919,0 -3.53878,-0.52041 -4.55878,-1.56122 -1.02,-1.05123 -1.54047,-2.44595 -1.53,-4.18409 l 0.0463,-7.17819 -0.0463,-7.71591 4.12163,0.0101 0.0463,4.80364 -5e-5,2.9021 -0.0463,7.16259 c -0.005,0.85345 0.20817,1.47796 0.62449,1.87347 0.41633,0.3955 1.08766,0.59327 2.01399,0.59327 0.59326,0 1.13449,-0.0677 1.62367,-0.20297 0.49959,-0.14571 0.95235,-0.32786 1.35827,-0.54643 z" c2.381,4.721,3.568,10.387,3.568,17.001c0,1.045-0.026,2.167-0.086,3.366c-0.058,1.199-0.146,2.263-0.261,3.189H518.748z
id="path12-9-4-7" M530.123,83.41c-3.29,0-5.939,1.181-7.949,3.54c-2.014,2.36-3.232,6.132-3.655,11.315h22.627
sodipodi:nodetypes="csscscccccccsssc" /> c-0.037-4.487-0.908-8.085-2.608-10.794C536.833,84.765,534.027,83.41,530.123,83.41z"/>
<path <path fill="#00819E" d="M573.056,134.764v-12.302h8.125V85.326h-8.125V73.14h22.109l3.367,13.869
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699" c2.204-5.3,5.019-9.245,8.441-11.838c3.425-2.591,7.611-3.888,12.562-3.888c2.091,0,3.948,0.164,5.571,0.493
d="m 77.522843,8.8230973 c 1.10327,0 2.07643,0.0885 2.9195,0.26541 0.85347,0.17694 1.63408,0.41632 2.34183,0.71816 l -1.18653,2.7789807 c -0.55163,-0.22898 -1.12928,-0.39551 -1.73296,-0.49959 -0.60367,-0.10408 -1.20735,-0.15612 -1.81102,-0.15612 -1.03041,0 -1.785,0.19776 -2.26378,0.59326 -0.47877,0.38511 -0.71816,1.0044 -0.71816,1.85786 v 2.67561 l 19.601696,-0.0095 v 2.88231 l -19.601696,0.0096 v 12.45858 h -4.10603 v -12.45857 h -3.63765 v -2.88241 h 3.63765 v -2.76926 c 0,-1.59246 0.57766,-2.89868 1.73297,-3.918681 1.16571,-1.0304097 2.77377,-1.5456097 4.82418,-1.5456097 z" c1.625,0.329,3.153,0.784,4.583,1.363l-3.423,25.764h-11.488V87.529c-3.48,0.62-6.537,2.506-9.169,5.657
id="path11-8-9-3" c-2.63,3.155-4.661,7.032-6.091,11.636v17.64h12.184v12.302H573.056z"/>
sodipodi:nodetypes="ccccsscsccccccccccsccc" /> </g>
<path </g>
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699" </svg>
d="m 63.839893,28.041788 c 0,0.6349 0.0937,1.09807 0.28102,1.3895 0.18735,0.29143 0.48919,0.50479 0.90551,0.6401 l -0.0442,2.79812 c -1.56938,-0.001 -2.46937,-0.347 -3.09386,-0.69047 -0.62449,-0.35387 -1.10326,-0.87949 -1.43632,-1.57684 -0.6245,0.7598 -1.41552,1.32705 -2.37307,1.70174 -0.94714,0.37469 -1.94112,0.56204 -2.981938,0.56204 -1.686124,0 -3.023574,-0.47878 -4.01235,-1.43633 -0.988777,-0.95755 -1.483165,-2.20132 -1.483165,-3.73132 0,-1.75899 0.686939,-3.11205 2.060818,-4.05919 1.384287,-0.95755 3.341023,-1.43633 5.870205,-1.43633 h 2.31062 v -0.8899 c 0,-0.97837 -0.30704,-1.68612 -0.92113,-2.12327 -0.60367,-0.44755 -1.46755,-0.67132 -2.59163,-0.67132 -0.530817,0 -1.19694,0.0729 -1.998369,0.21857 -0.801429,0.13531 -1.618471,0.34867 -2.451124,0.6401 l -0.983572,-2.82583 c 1.051225,-0.3955 2.107655,-0.68693 3.169288,-0.87428 1.072041,-0.18734 2.045207,-0.28102 2.919487,-0.28102 2.32103,0 4.04358,0.49439 5.16766,1.48316 1.12408,0.97838 1.68612,2.36787 1.68612,4.16848 z"
id="path10-6-6-7"
sodipodi:nodetypes="sscccccssscscscsccccscss" />
<path
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#249bb3;fill-opacity:1;stroke-width:2.53699"
d="m 56.439683,29.884038 c 0.62449,0 1.25419,-0.17173 1.88909,-0.5152 0.6349,-0.35388 1.13969,-0.85347 1.51439,-1.49878 v -3.21613 h -1.62368 c -1.53,0 -2.638471,0.24459 -3.32541,0.73378 -0.676531,0.48919 -1.014796,1.18133 -1.014796,2.07643 0,1.61327 0.85347,2.4199 2.560406,2.4199 z"
id="path9-5-3-2"
sodipodi:nodetypes="scccscss" />
<path
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699"
d="m 32.598108,32.397608 v -2.85704 h 2.326226 v -10.83491 h -2.326226 v -2.84144 l 5.974025,0.0232 0.255265,3.77062 c 0.603674,-1.39469 1.36347,-2.45112 2.279389,-3.1693 0.915919,-0.71816 2.066022,-1.07724 3.450309,-1.07724 0.530817,0 0.999184,0.0416 1.405103,0.1249 0.405919,0.0833 0.801429,0.19255 1.186531,0.32785 l -0.432569,4.826 h -3.025794 l -0.02317,-1.60986 c -1.072041,0.0937 -1.998368,0.58286 -2.778981,1.46755 -0.780613,0.87429 -1.476612,2.07874 -1.924163,3.51507 l 0.08192,5.47759 h 3.294186 v 2.85704 z"
id="path8-0-7-6"
sodipodi:nodetypes="ccccccccssscccccccccc" />
<path
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699"
d="m 21.842901,10.337487 c 1.498777,0 2.768574,0.197761 3.809391,0.593261 1.040817,0.38511 2.003572,0.94195 2.888267,1.67051 l -2.170104,2.57603 c -0.62449,-0.51 -1.301021,-0.9003 -2.029593,-1.17092 -0.728572,-0.28102 -1.509185,-0.42154 -2.341838,-0.42154 -1.009593,0 -1.93592,0.26541 -2.778982,0.79623 -0.832653,0.53082 -1.498776,1.38429 -1.99837,2.56041 -0.499592,1.16572 -0.749388,2.70613 -0.749388,4.62124 0,1.88388 0.239388,3.40868 0.718164,4.57439 0.489185,1.15531 1.150104,2.00357 1.982757,2.5448 0.843062,0.54122 1.79541,0.81183 2.857043,0.81183 1.124083,0 2.055614,-0.19255 2.794594,-0.57765 0.749389,-0.39551 1.415512,-0.83266 1.998369,-1.31143 l 2.013981,2.5448 c -0.759797,0.74939 -1.712144,1.38949 -2.857043,1.92031 -1.134491,0.53081 -2.513573,0.79622 -4.137248,0.79622 -1.883879,0 -3.564798,-0.42673 -5.04276,-1.2802 -1.47796,-0.86388 -2.638471,-2.13368 -3.481533,-3.80939 -0.843061,-1.68613 -1.264592,-3.75735 -1.264592,-6.21368 0,-2.4147 0.431939,-4.4547 1.295817,-6.12002 0.874286,-1.67571 2.050409,-2.94551 3.528369,-3.80939 1.48837,-0.86387 3.143269,-1.295811 4.964699,-1.295811 z"
id="text1-1-9-2-8-0"
sodipodi:nodetypes="sccccsccsccsccccsccsccs" />
</g>
<g
id="g18"
transform="translate(-6.4941406,-6.0334926)">
<rect
style="fill:#ffffff;stroke-width:0.23553"
id="rect26-3-6-5"
width="95.615021"
height="29.989243"
x="102.10917"
y="6.0334926"
ry="0.008925369"
inkscape:label="rect26-3-6-5" />
<path
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#a02c2c;fill-opacity:1;stroke-width:2.53699"
d="m 167.25894,25.406429 c 0.1249,1.55082 0.58286,2.6697 1.37388,3.35664 0.79102,0.68693 1.75378,1.0304 2.88827,1.0304 0.79102,0 1.5352,-0.1249 2.23255,-0.37469 0.69735,-0.24979 1.38429,-0.59847 2.06082,-1.04602 l 1.22586,2.71789 c -0.81937,0.56339 -1.19983,0.80528 -2.27188,1.20079 -1.06163,0.39551 -2.23255,0.59326 -3.51276,0.59326 -1.79021,0 -3.29939,-0.36949 -4.52755,-1.10847 -1.21776,-0.73898 -2.13888,-1.76418 -2.76337,-3.07561 -0.62449,-1.31143 -0.93674,-2.82062 -0.93674,-4.52756 0,-1.64449 0.30184,-3.12765 0.90551,-4.44949 0.61409,-1.32184 1.49878,-2.36786 2.65409,-3.13807 1.16571,-0.78061 2.56561,-1.17092 4.19969,-1.17092 2.26899,0 4.0696,0.73898 5.40184,2.21695 1.33225,1.47796 1.99837,3.52316 1.99837,6.13561 0,0.60368 -0.026,1.10096 -0.0781,1.63929 z"
id="path19-4-4-6-5" />
<path
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#a02c2c;fill-opacity:1;stroke-width:2.53699"
d="m 179.51963,32.453911 v -2.85704 h 2.32622 v -10.83491 h -2.32622 v -2.84144 l 5.97402,0.0232 0.25527,3.77062 c 0.60366,-1.39469 1.36347,-2.45112 2.27939,-3.1693 0.91591,-0.71816 2.06602,-1.07724 3.4503,-1.07724 0.53082,0 0.99919,0.0416 1.40511,0.1249 0.40592,0.0833 0.80143,0.19255 1.18653,0.32785 l -0.43257,4.826 h -3.02579 l -0.0232,-1.60986 c -1.07205,0.0937 -1.99837,0.58286 -2.77899,1.46755 -0.78061,0.87429 -1.47661,2.07874 -1.92416,3.51507 l 0.0819,5.47759 h 3.29418 v 2.85704 z"
id="path20-7-4-3" />
<path
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#a02c2c;fill-opacity:1;stroke-width:2.53699"
d="m 124.31121,25.498691 c 0.1249,1.55082 0.58286,2.6697 1.37388,3.35664 0.79102,0.68693 1.75378,1.0304 2.88827,1.0304 0.79102,0 1.5352,-0.1249 2.23255,-0.37469 0.69735,-0.24979 1.38429,-0.59847 2.06082,-1.04602 l 1.22586,2.71789 c -0.81937,0.56339 -1.19983,0.80528 -2.27188,1.20079 -1.06163,0.39551 -2.23255,0.59326 -3.51276,0.59326 -1.79021,0 -3.29939,-0.36949 -4.52755,-1.10847 -1.21776,-0.73898 -2.13888,-1.76418 -2.76337,-3.07561 -0.62449,-1.31143 -0.93674,-2.82062 -0.93674,-4.52756 0,-1.64449 0.30184,-3.12765 0.90551,-4.44949 0.61409,-1.32184 1.49878,-2.36786 2.65409,-3.13807 1.16571,-0.78061 2.56561,-1.17092 4.19969,-1.17092 2.26899,0 4.0696,0.73898 5.40184,2.21695 1.33225,1.47796 1.99837,3.52316 1.99837,6.13561 0,0.60368 -0.026,1.10096 -0.0781,1.63929 z"
id="path19-4-4-6" />
<path
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699"
d="m 127.85521,18.410731 c -0.99919,0 -1.82144,0.35908 -2.46675,1.07724 -0.6349,0.71817 -1.00959,1.84225 -1.12408,3.37225 h 6.96307 c -0.0208,-1.39469 -0.30702,-2.48235 -0.85867,-3.26296 -0.55163,-0.79102 -1.38949,-1.18653 -2.51357,-1.18653 z"
id="path18-2-6-1" />
<path
id="path17-7-0-5"
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#a02c2c;fill-opacity:1;stroke-width:2.53699"
d="m 140.17463,12.245649 v 4.827095 h -3.59048 v 2.887163 h 3.59048 v 7.179923 c 0,1.73817 0.51014,3.132494 1.53014,4.183724 1.02,1.04081 2.53971,1.561145 4.55889,1.561145 1.02001,0 1.96688,-0.129947 2.84117,-0.390157 0.87429,-0.2602 0.92381,-0.268974 1.53789,-0.674894 l -0.72605,-2.97863 c -0.40591,0.21857 -0.85847,0.401027 -1.35806,0.546737 -0.48919,0.13527 -1.03041,0.203088 -1.62367,0.203088 -0.92632,0 -1.59751,-0.197745 -2.01383,-0.593245 -0.41634,-0.39551 -0.62477,-1.020318 -0.62477,-1.873788 v -7.163903 h 7.73493 v 7.179923 c 0,1.73817 0.51014,3.132494 1.53014,4.183724 1.02,1.04081 2.5392,1.561145 4.55838,1.561145 1.02,0 1.96739,-0.129947 2.84168,-0.390157 0.87429,-0.2602 0.9233,-0.268974 1.53738,-0.674894 l -0.72554,-2.97863 c -0.40591,0.21857 -0.85846,0.401027 -1.35806,0.546737 -0.48919,0.13527 -1.0304,0.203088 -1.62367,0.203088 -0.92632,0 -1.59802,-0.197745 -2.01435,-0.593245 -0.41633,-0.39551 -0.62425,-1.020318 -0.62425,-1.873788 v -7.163903 h 5.04259 v -2.887163 h -5.04259 v -4.817277 l -4.12171,-0.0098 v 4.827095 h -7.73493 v -4.817277 z"
sodipodi:nodetypes="cccccscsscccsssccscsscccssscccccccccc" />
<path
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;stroke-width:2.53699"
d="m 170.93889,18.844808 c -0.99919,0 -1.82143,0.35908 -2.46674,1.07724 -0.6349,0.71817 -1.00959,1.84225 -1.12408,3.37225 h 6.96306 c -0.0208,-1.39469 -0.30702,-2.48235 -0.85867,-3.26296 -0.55163,-0.79102 -1.38949,-1.18653 -2.51357,-1.18653 z"
id="path14-3-1-0" />
<path
d="M 105.67699,10.821962 V 32.41341 h 13.81621 l -0.478,-3.432865 -9.06043,-0.03307 v -1.414384 h -1.91151 c -0.22141,0 -0.39946,-0.178053 -0.39946,-0.399459 0,-0.221405 0.17805,-0.399976 0.39946,-0.399976 h 1.91151 v -2.004012 h -1.91151 c -0.22141,0 -0.39946,-0.178569 -0.39946,-0.399975 0,-0.221405 0.17805,-0.399459 0.39946,-0.399459 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178054 -0.39946,-0.399459 0,-0.221406 0.17805,-0.399975 0.39946,-0.399975 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178054 -0.39946,-0.399459 0,-0.221406 0.17805,-0.399459 0.39946,-0.399459 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178053 -0.39946,-0.399458 0,-0.221406 0.17805,-0.399976 0.39946,-0.399976 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178054 -0.39946,-0.399459 0,-0.221406 0.17805,-0.399458 0.39946,-0.399458 h 1.91151 v -1.893426 z"
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#a02c2c;fill-opacity:1;stroke-width:2.53699"
id="path6" />
<path
d="m 109.95477,12.715388 h -1.91151 c -0.22141,0 -0.39946,0.178052 -0.39946,0.399458 0,0.221405 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
style="fill:#ffffff;stroke-width:0.296737"
id="path8" />
<path
d="m 109.95477,15.518834 h -1.91151 c -0.22141,0 -0.39946,0.17857 -0.39946,0.399976 0,0.221405 0.17805,0.399458 0.39946,0.399458 h 1.91151 z"
style="fill:#ffffff;stroke-width:0.296737"
id="path10" />
<path
d="m 109.95477,18.322797 h -1.91151 c -0.22141,0 -0.39946,0.178053 -0.39946,0.399459 0,0.221405 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
style="fill:#ffffff;stroke-width:0.296737"
id="path12" />
<path
d="m 109.95477,21.126244 h -1.91151 c -0.22141,0 -0.39946,0.178569 -0.39946,0.399975 0,0.221405 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
style="fill:#ffffff;stroke-width:0.296737"
id="path14" />
<path
d="m 109.95477,23.930207 h -1.91151 c -0.22141,0 -0.39946,0.178054 -0.39946,0.399459 0,0.221406 0.17805,0.399975 0.39946,0.399975 h 1.91151 z"
style="fill:#ffffff;stroke-width:0.296737"
id="path16" />
<path
d="m 109.95477,26.733653 h -1.91151 c -0.22141,0 -0.39946,0.178571 -0.39946,0.399976 0,0.221406 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
style="fill:#ffffff;stroke-width:0.296737"
id="path18" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Before After
Before After

View file

@ -1,85 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="29.989243mm"
height="29.989243mm"
viewBox="0 0 29.989243 29.989242"
version="1.1"
id="svg1"
sodipodi:docname="favicon.svg"
inkscape:version="1.4.3 (0d15f75, 2025-12-25)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showguides="true"
inkscape:zoom="2.0186728"
inkscape:cx="14.365874"
inkscape:cy="58.206559"
inkscape:window-width="2560"
inkscape:window-height="1351"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="g19" />
<defs
id="defs1" />
<g
id="g19"
transform="translate(-6.494133,-6.033493)">
<circle
style="fill:#249bb3;fill-opacity:1;stroke-width:0.264583"
id="path22"
cx="21.488754"
cy="21.028114"
r="14.994621" />
<g
id="g18"
transform="matrix(1.0220008,0,0,1.0220008,4.9074989,-32.198722)"
style="fill:#ffffff">
<path
d="m 10.061962,40.811205 v 21.591448 h 13.81621 l -0.478,-3.432865 -9.06043,-0.03307 v -1.414384 h -1.91151 c -0.22141,0 -0.39946,-0.178053 -0.39946,-0.399459 0,-0.221405 0.17805,-0.399976 0.39946,-0.399976 h 1.91151 v -2.004012 h -1.91151 c -0.22141,0 -0.39946,-0.178569 -0.39946,-0.399975 0,-0.221405 0.17805,-0.399459 0.39946,-0.399459 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178054 -0.39946,-0.399459 0,-0.221406 0.17805,-0.399975 0.39946,-0.399975 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178054 -0.39946,-0.399459 0,-0.221406 0.17805,-0.399459 0.39946,-0.399459 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178053 -0.39946,-0.399458 0,-0.221406 0.17805,-0.399976 0.39946,-0.399976 h 1.91151 v -2.004529 h -1.91151 c -0.22141,0 -0.39946,-0.178054 -0.39946,-0.399459 0,-0.221406 0.17805,-0.399458 0.39946,-0.399458 h 1.91151 v -1.893426 z"
style="font-weight:600;font-size:30.4439px;font-family:'Fira Code';-inkscape-font-specification:'Fira Code, Semi-Bold';fill:#ffffff;fill-opacity:1;stroke-width:2.53699"
id="path6" />
<path
d="m 14.339742,42.704631 h -1.91151 c -0.22141,0 -0.39946,0.178052 -0.39946,0.399458 0,0.221405 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
style="fill:none;stroke-width:0.296737"
id="path8" />
<path
d="m 14.339742,45.508077 h -1.91151 c -0.22141,0 -0.39946,0.17857 -0.39946,0.399976 0,0.221405 0.17805,0.399458 0.39946,0.399458 h 1.91151 z"
style="fill:none;stroke-width:0.296737"
id="path10" />
<path
d="m 14.339742,48.31204 h -1.91151 c -0.22141,0 -0.39946,0.178053 -0.39946,0.399459 0,0.221405 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
style="fill:none;stroke-width:0.296737"
id="path12" />
<path
d="m 14.339742,51.115487 h -1.91151 c -0.22141,0 -0.39946,0.178569 -0.39946,0.399975 0,0.221405 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
style="fill:none;stroke-width:0.296737"
id="path14" />
<path
d="m 14.339742,53.91945 h -1.91151 c -0.22141,0 -0.39946,0.178054 -0.39946,0.399459 0,0.221406 0.17805,0.399975 0.39946,0.399975 h 1.91151 z"
style="fill:none;stroke-width:0.296737"
id="path16" />
<path
d="m 14.339742,56.722896 h -1.91151 c -0.22141,0 -0.39946,0.178571 -0.39946,0.399976 0,0.221406 0.17805,0.399459 0.39946,0.399459 h 1.91151 z"
style="fill:none;stroke-width:0.296737"
id="path18" />
</g>
</g>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1" />
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

View file

@ -1,7 +1,24 @@
Title: Lettre n°1 - 8 Décembre 2025 Title: Lettre n°1 - 8 Décembre 2025
Date: 2025-12-08 10:20 Date: 2025-12-08 10:20
Category: Newsletter Category: Newsletter
JsonLD: { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°1", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Dec 08 2025 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } }
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"name": "Lettre n°1",
"description": "Lettre de veille technologique en développement logiciel",
"image": [
"https://www.craftletter.fr/images/craftletter.svg"
],
"datePublished": "Mon Dec 08 2025 09:00:00 GMT+0200 (Coordinated Universal Time)",
"author": {
"@type": "Person",
"name": "Pascal Le Merrer",
"url": "https://www.linkedin.com/in/pascal-le-merrer/"
}
}
</script>
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg"> <img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">

View file

@ -1,66 +0,0 @@
Title: Lettre n°10 — 09 février 2026
Date: 2026-02-09 09:00
Category: Newsletter
JsonLD: <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°10", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Feb 09 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } </script>
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">
## Swift nest pas le langage que vous croyez
Dans un article qui date de 2023, Naman Goel compare [Swift et Rust](https://nmn.sh/blog/2023-10-02-swift-is-the-more-convenient-rust) 🇬🇧. Selon lui on retrouve des concepts de Rust dans Swift, comme le pattern matching ou la gestion des valeurs nulles, avec une syntaxe plus familière. Les [énumérations en Swift ](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/enumerations)🇬🇧 sont des [types algébriques](https://fr-academic.com/dic.nsf/frwiki/1669687) 🇫🇷, cest-à-dire quils combinent plusieurs autres types, pas seulement des constantes. Cest un autre concept issu de la programmation fonctionnelle.
Swift est un langage multi paradigme : impératif, orienté objet et fonctionnel. La gestion de la mémoire est basée sur le [comptage de références](https://fr.wikipedia.org/wiki/Comptage_de_r%C3%A9f%C3%A9rences)🇫🇷. Il nutilise pas de ramasse-miettes (*garbage collector*) pour libérer la mémoire, ce qui évite les pauses dans lexécution du code. Il est compilé en code machine à laide de LLVM, ce qui lui permet de générer des applications pour toutes les plateformes supportées par ce dernier.
Laffirmation selon laquelle Swift serait un Rust plus simple ne me convainc pas —il y a bien des points communs entre ces langages, mais aussi pas mal de différences. Ce qui ma plus intéressé, et que jai découvert grâce à cet article, cest que Swift nest plus limité à lécosystème Apple. En effet, depuis 2020. Il peut générer des programmes pour Windows ou Linux, et la génération dapplication dAndroid est sur le point darriver.
Dailleurs, [Apple veut étendre son utilisation au cloud](https://www.infoq.com/presentations/swift-apps-services/) 🇬🇧.
## JQ Quest
Jq est un outil bien connu pour manipuler du JSON en ligne de commande. Il peut vous éviter décrire un script qui doit transformer ou filtrer des données. [JQ Quest](https://codeberg.org/gturri/jq-quest) 🇬🇧 est une série dexercice pour apprendre à vous servir de JQ.
## State Of Js 2025
Si vous vous êtes curieux·se de connaître les outils à la mode dans lécosystème JavaScript,
vous pouvez consulter les résultats du sondage [State of JS 2025](https://2025.stateofjs.com/en-US) 🇬🇧. Ils sont en ligne —même si la page daccueil ne lindique pas encore à lheure où je rédige cette neswletter... Oups.
Quelques points qui mont interpelés :
* Angular est toujours aussi peu apprécié : plus dune personne sur deux qui la essayé na pas aimé lexpérience.
* Le taux de satisfaction des utilisateurs de HTMX est en baisse (de 84% en 2016 à 69% en 2025) ; je soupçonne que cela correspond à la découverte des limitations de ce framework quand les applications deviennent plus complexes. Datastar, dont je vous parlais dans [la lettre n°7](http://127.0.0.1:8000/lettre-ndeg7-19-janvier-2026.html), napparait pas dans ce sondage, cest dommage, car jaurais bien aimé découvrir les retours dexpérience à son sujet.
* La satisfaction des utilisateurs de React est également en baisse régulière (de 92% en 2016 à 72% en 2025).
* Cypress (Tests End-to-end), autrefois très populaire, a perdu de sa superbe, puisque à peine plus de la moitié des utilisateurs ont envie de le réutiliser.
* À linverse, Playwright (tests End-to-end), Vitest (tests unitaires), Vite (build), Astro (framework pour créer des sites de contenu), Bun (alternative à NodeJs), Hono et Fastify (frameworks Web) sont appréciés par une large majorité de ceux qui les ont utilisés.
* Solid (Framework Front-end) maintient depuis 2021 un taux de satisfaction autour de 90% ; il mériterait sans doute plus dattention.
## ReliCSS : un outil pour faire de larchéologie dans le Front-End
[ReliCSS](https://www.alwaystwisted.com/articles/introducing-relicss-a-tool-for-front-end-archaeology)🇬🇧 est un nouvel outil qui identifie les directives obsolètes dans les feuilles de style CSS ❤️. Il nest disponible que sous la forme dune application Web pour linstant, mais une version en ligne de commande est prévue.
## Réviser les concepts des API REST
Datacamp a publié une [synthèse sur les API REST](https://www.datacamp.com/blog/rest-api-interview-questions) 🇬🇧. Simple et efficace, jaime beaucoup la forme !
## Turso : une réécriture de SQLite en Rust
[Turso](https://kerkour.com/turso-sqlite)🇬🇧 est une réécriture de SqLite en Rust, mais pas seulement.
En plus des spécificités de Rust, qui devraient permettre déviter les bugs liés à la gestion de la mémoire qui affectent certaines versions de SqlLite, Turso apporte de nouvelles fonctionnalités : le support des connexions via le réseau et les accès concurrents, comme Postgresql.
## Performances de NodeJS
Les [performances de NodeJs](https://www.repoflow.io/blog/node-js-16-to-25-benchmarks-how-performance-evolved-over-time)🇬🇧 ont été améliorées régulièrement de la version 16 à la version 25. Si vous nutilisez pas encore la dernière version, la mettre à jour serait un moyen pas trop coûteux de faire un peu décoconception.
## Oubliez la dette technique
Derrière un titre un brin provocateur, Uwe Friedrichsen déroule [une réflexion intéressante sur la dette technique](https://www.ufried.com/blog/forget_technical_debt/)🇬🇧. Il en donne sa propre définition, qui nest pas celle de Ward Cunningham (linventeur du concept) : pour lui cest tout ce qui augmente la charge cognitive des développeurs. Il essaie didentifier les causes de cette dette, qui sont daprès lui plus souvent organisationnelles que techniques. Il en mentionne aussi ses conséquences : le développement des fonctionnalités est ralenti, et les problèmes en production sont plus nombreux.
Selon lui, réduire la dette sans sattaquer à ses causes racines serait insuffisant, car elle saccumule plus vite quon ne peut la réduire.
À propos de dette technique, je vous suggère de (ré)écouter la conférence dArnaud Lemaire "[Dette technique et entropie du logiciel](https://www.youtube.com/watch?v=VKe9EE4MUxk)"🇫🇷. Il commence par expliquer la notion de dette technique telle que Ward Cunningham la définie, avant den venir à ce que désigne plus communément par ce terme, et quil appelle "pourriture logicielle". Ce talk, qui ensuite aborde bien dautres sujets, reste toujours pertinent et intéressant, malgré son ton provocateur.
## Images docker durcies (bis)
Docker nest pas le seul à proposer des images durcies : le [projet minimal](https://github.com/rtvkiz/minimal) le fait aussi (à une moins grande échelle). Une image durcie est une image Docker dans laquelle tout ce qui nest pas indispensable a été supprimé, dans le but de réduire la surface dattaque (autrement dit les failles de sécurité potentielles).
## Devoxx France 2026
La plus grosse conférence Française consacrée au développement logiciel sera de retour du 22 au 24 Avril. [La billetterie est ouverte](https://reg.devoxx.fr/#w). Conseil dami : ny allez pas pour la nourriture, vous seriez déçu·e 😉.
--------
Voilà, cest toute pour cette semaine !

View file

@ -1,7 +1,25 @@
Title: Lettre n°2 - 15 Décembre 2025 Title: Lettre n°2 - 15 Décembre 2025
Date: 2025-12-15 09:00 Date: 2025-12-15 09:00
Category: Newsletter Category: Newsletter
JsonLD: { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°2", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Dec 08 2025 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } }
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"name": "Lettre n°2",
"description": "Lettre de veille technologique en développement logiciel",
"image": [
"https://www.craftletter.fr/images/craftletter.svg"
],
"datePublished": "Mon Dec 08 2025 09:00:00 GMT+0200 (Coordinated Universal Time)",
"author": {
"@type": "Person",
"name": "Pascal Le Merrer",
"url": "https://www.linkedin.com/in/pascal-le-merrer/"
}
}
</script>
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg"> <img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">

View file

@ -1,7 +1,24 @@
Title: Lettre n°3 - 22 Décembre 2025 Title: Lettre n°3 - 22 Décembre 2025
Date: 2025-12-22 08:20 Date: 2025-12-22 08:20
Category: Newsletter Category: Newsletter
JsonLD: { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°3 - 22 Decembre 2025", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Dec 08 2025 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } }
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"name": "Lettre n°3 - 22 Decembre 2025",
"description": "Lettre de veille technologique en développement logiciel",
"image": [
"https://www.craftletter.fr/images/craftletter.svg"
],
"datePublished": "Mon Dec 08 2025 09:00:00 GMT+0200 (Coordinated Universal Time)",
"author": {
"@type": "Person",
"name": "Pascal Le Merrer",
"url": "https://www.linkedin.com/in/pascal-le-merrer/"
}
}
</script>
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg"> <img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">

View file

@ -1,7 +1,24 @@
Title: Lettre n°4 - 29 Décembre 2025 Title: Lettre n°4 - 29 Décembre 2025
Date: 2025-12-29 09:00 Date: 2025-12-29 09:00
Category: Newsletter Category: Newsletter
JsonLD: { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°4 - 29 Décembre 2025", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Dec 29 2025 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } }
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"name": "Lettre n°4 - 29 Décembre 2025",
"description": "Lettre de veille technologique en développement logiciel",
"image": [
"https://www.craftletter.fr/images/craftletter.svg"
],
"datePublished": "Mon Dec 29 2025 09:00:00 GMT+0200 (Coordinated Universal Time)",
"author": {
"@type": "Person",
"name": "Pascal Le Merrer",
"url": "https://www.linkedin.com/in/pascal-le-merrer/"
}
}
</script>
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg"> <img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">

View file

@ -0,0 +1,94 @@
Title: Lettre n°4 - 29 Décembre 2025
Date: 2025-12-29 09:00
Category: Newsletter
}
# Craft Letter n°4
## Édito
Cette semaine encore, le contenu de cette newsletter est varié. Je vais en effet vous parler d'outillage, de langages fonctionnels, de recrutement, de sécurité, d'apprentissage ou de révision, et, pour finir, d'architecture basée sur des cellules. Concernant les langages fonctionnels, ceux que j'évoquerai sont mes deux langages favoris : ils associent la simplicité à un système de type qui élimine des classes entières d'erreurs. Le tout accompagné d'une expérience développeur particulièrment agréable.
Passez de bonnes fêtes de fin d'année, et bonne lecture !
## ty
Après ruff (https://github.com/astral-sh/ruff) (linter et formateur) et uv (https://github.com/astral-sh/uv) (un gestionnaire de dépendances), Astral (https://astral.sh/) nous propose un troisième outil pour Python : ty (https://docs.astral.sh/ty/), un vérificateur de types (_type checker_) et serveur de langage. Comme ruff et uv, ty est écrit en Rust, et bénéficie de performances bien meilleures que celles des outils concurrents. ruff et uv étant des réussites, ty mérite qu'on le regarde de près.
## Visualiser des logs avec HL
hl (https://github.com/pamburus/hl?tab=readme-ov-file#performing-complex-queries%5D) est un outil de visualisation de log, écrit en Rust —c'est devenu un argument marketing. Il est capable de capable visualiser, filtrer et requêter rapidement des fichiers de plusieurs gigaoctets.
## Une liste d'outils autour de Jujutsu
Jujutsu (https://www.jj-vcs.dev/) —jj— est une alternative à Git, à la fois plus puissant et plus simple dutilisation. Il utilise Git comme back-end, ce qui veut dire que vous pouvez lutiliser de façon transparente sur un projet dont les autres contributeurs utilisent Git. Awesome JJ (https://github.com/Necior/awesome-jj) liste des outils de lécosystème naissant autour de cet outil.
Jutilise Jujutsu depuis 8 mois, sur des projets personnels pour linstant, et je le préfère largement à Git. Le nommage des commandes et options est bien plus clair, ce qui fait quon les retient ou retrouve plus facilement. Le workflow est plus simple —car il y a moins de concepts. Malgré cela, il est plus puissant que Git. Par exemple, il ne requiert de résoudre qu'une seule fois les conflits lors d'un rebase, là où Git peut vous demander de les résoudre à plusieurs reprises.
## Comment trouver des développeurs pour un langage fonctionnel
Dans sa keynote lors des Scala Days 2025 🇬🇧 (https://www.youtube.com/watch?v=9OtN4iiFBsQ), Evan Czaplicki explique comment Elm (https://www.youtube.com/watch?v=9OtN4iiFBsQ), le langage qu'il a créé il y a bientôt 14 ans, peut servir de porte d'entrée pour des langages fonctionnels plus complexes, comme Haskell ou Scala. Elm est volontairement simple : les concepts y sont limités au strict minimum. Malgré une syntaxe qui peut intimider au départ, l'apprentissage est rapide, notamment parce que l'expérience développeur est vraiment agréable. Vous trouvez sympathiques les messages d'erreur de Rust ? Ils sont inspirés de ceux de Elm.
Evan partage dans cette keynote les stratégies de recrutement d'entreprises florissantes qui utilisent Elm. Certaines recrutent les développeurs ou développeuses de modules populaires. D'autres embauchent des débutants et les forment. Les qualités du langage font que ces juniors sont opérationnels et productifs en quelques semaines seulement —n'allez pas croire que c'est exagéré, mon expérience avec Elm me confirme que c'est une réalité. Recruter des débutants disposés à se former est une manière de s'assurer qu'ils ont la culture adéquate : leur volonté d'apprendre sera utile par la suite sur d'autres sujets. Cela répond aussi à l'inquiétude de nombreux managers : comment recruter pour une techno de niche ?
## Gleam attire l'attention des développeurs
À propos de langages fonctionnels, Gleam (https://gleam.run/) est le second langage le plus admiré (https://survey.stackoverflow.co/2025/technology#admired-and-desired) par les répondants au dernier sondage de Stack Overflow, juste derrière Rust. Rust truste le sommet de ce classement depuis plusieurs années, ce n'est donc pas une surprise de le retrouver en tête. Gleam, qui est beaucoup plus récent, entre directement à la seconde place de ce sondage, et c'est une vraie surprise pour moi. En effet, je ne m'attendais pas à ce qu'autant de monde connaisse ce langage. Par contre, ses qualités font que je ne suis pas étonné qu'il soit aussi apprécié. Si vous voulez en savoir plus sur Gleam, je vous renvoie vers la conférence que j'ai donnée (https://www.youtube.com/watch?v=nTzNDM-dvRc) 🇫🇷 l'an dernier à ce sujet (27 minutes).
## Filtrer les candidats en remote
Jose Zarazua utilise une astuce pour distinguer instantanément les candidats 🇬🇧 (https://josezarazua.com/im-a-former-cto-here-is-the-15-sec-coding-test-i-used-to-instantly-filter-out-50-of-unqualified-applicants) qui réfléchissent et les autres, lors d'un test de recrutement à distance.
## Des images docker durcies
Des centaines d'images Docker durcies (https://hub.docker.com/hardened-images/catalog), auparavant payantes, sont dorénavant mises à disposition gratuitement (https://www.docker.com/blog/docker-hardened-images-for-every-developer) 🇬🇧 par Docker Inc. Une image durcie est une image dont la sécurité est renforcée, en éliminant tout ce qui nest pas indispensable, ce qui réduit la surface dattaque.
Les images en question sont basées sur Debian et Alpine. Des charts Helm (https://blog.stephane-robert.info/docs/conteneurs/orchestrateurs/outils/helm/) 🇫🇷 sont également disponibles aux mêmes conditions. Un chart Helm décrit le déploiement et la configuration dune application sous Kubernetes. Les charts, comme les images, sont durcis, et mis à jour en moins dune semaine quand une faille de sécurité est détectée. Ces images et charts sont sous llicense Apache 2, une license bien connue et très permissive, donc il n'y a pas de mauvaise surprise à attendre de ce côté là.
## Exposition involontaire de données avec Supabase
Si vous utilisez Supabase (https://supabase.com/) (Base de données SAAS), vous devriez vérifier que les données des utilisateurs ne sont pas accessibles librement. Supabase ne met pas suffisamment en garde contre ce risque 🇬🇧 (https://skilldeliver.com/your-supabase-is-public).
Cet article me rappelle des problèmes similaires avec Redis (https://www.tenable.com/plugins/nessus/100634) et MongoDB (https://satoricyber.com/mongodb-security/6-mongodb-authentication-features-you-must-know-about/#how-to-enable-authentication-in-mongodb), pour lesquels l'authentification n'est pas activée par défaut.
## Apprendre ou réviser une techno en quelques minutes
Jean-Pierre Liégeois (jeune lecteur du Var) Erwan (https://www.linkedin.com/in/erwannedellec/) m'a rappelé l'existence du site Learn X in Y minutes (https://learnxinyminutes.com).
Plutôt que de s'en servir pour apprendre une nouvelle technologie, il l'utilise pour se rafraichir la mémoire lorsqu'il doit utiliser un langage qu'il n'a pas pratiqué depuis longtemps.
A cette occasion, j'ai découvert que les fiches proposées par ce site ne se limitent pas à des langages de programmation. Certaines concernent en effet des formats de données (JSON, XML, YAML, Cue...), des langages de balisage légers (Markdown, Restructured Text...), des shells (Bash, Fish), des frameworks et bibliothèques (Jquery, OpenCV...), des outils (Git, Docker), etc.
## Architecture basée sur des cellules
Une cellule est un ensemble de microservices et des services dont ils dépendent (cache, base de données, stockage...). Ils forment un ensemble cohérent et (idéalement) autonome —c'est-à-dire qui n'a pas ou peu de dépendances externes.
Dans une architecture basée sur des cellules (_cell based architecture_), chaque cellule est répliquée à l'identique autant de fois que nécessaire pour supporter la charge (scalabilité). Ces cellules sont déployées dans des régions différentes afin d'assurer la résilience du service.
Benjamin Cane (https://bencane.com/about) explique dans Cell Boundaries: Defining the Scope of a Cell in Cell-based Architecture (https://itnext.io/cell-boundaries-defining-the-scope-of-a-cell-f76c5c4a52dc) 🇬🇧 comment définir le contenu d'une cellule.
---
Et voilà, c'est tout pour cette semaine !
Retrouvez les numéros précédents sur le site web Craft Letter (https://www.craftletter.fr) 🇫🇷.
Si vous n'avez pas reçu cette lettre par email, ou si elle vous a été transmise par un tiers, vous pouvez vous abonner sur le site.
Pascal Le Merrer
---
Web Version: [webversion]
Unsubscribe: [unsubscribe]

View file

@ -1,7 +1,24 @@
Title: Lettre n°5 - 5 Janvier 2026 Title: Lettre n°5 - 5 Janvier 2026
Date: 2026-01-05 09:00 Date: 2026-01-05 09:00
Category: Newsletter Category: Newsletter
JsonLD: { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°5 - 5 Janvier 2026", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Jan 05 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } }
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"name": "Lettre n°5 - 5 Janvier 2026",
"description": "Lettre de veille technologique en développement logiciel",
"image": [
"https://www.craftletter.fr/images/craftletter.svg"
],
"datePublished": "Mon Jan 05 2026 09:00:00 GMT+0200 (Coordinated Universal Time)",
"author": {
"@type": "Person",
"name": "Pascal Le Merrer",
"url": "https://www.linkedin.com/in/pascal-le-merrer/"
}
}
</script>
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg"> <img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">
@ -31,7 +48,7 @@ Par exemple, le requêtage des éléments des pages HTML se base essentiellement
## Podcast Code Garage ## Podcast Code Garage
Le [podcast Code Garage](https://code-garage.com/podcast?tab=classic) 🇫🇷 est celui du site du même nom, qui propose des cours en ligne. Le [podcast Code Garage](https://code-garage.com/podcast?tab=classic) 🇫🇷 est celui du site du même nom, qui propose des cours en ligne.
Dans des épisodes dont la plupart sont courts (moins de quinze minutes en général), Nicolas Brondin-Bernard explique les bases d'une techno, ou son historique. Dans des épisodes dont la plupart sont courts (moins de quinze minutes en général), Nicolas Brondin-Bernard explique les bases d'une techno, ou son historique.
Quelques épisodes plus longs sont consacrés à des interviews. Quelques épisodes plus longs sont consacrés à des interviews.
@ -44,7 +61,8 @@ Plus de 150 épisodes sont disponibles à ce jour.
## Le coût caché des buzzwords dans la tech ## Le coût caché des buzzwords dans la tech
Jernej Klancic raconte quelques anecdotes dans lesquelles [l'adoption irréfléchie d'une techno ou d'un principe qui faisait le buzz](https://engineering.leanix.net/blog/trade-offs/) 🇬🇧 lui a jouée de mauvais tours. Il a établi une liste de questions à se poser avant de prendre une décision de ce type. Jernej Klancic raconte quelques anecdotes dans lesquelles [l'adoption irréfléchie d'une techno ou d'un principe qui faisait le buzz](https://engineering.leanix.net/blog/trade-offs/) 🇬🇧 lui a jouée de mauvais tours.
Il a établi une liste de questions à se poser avant de prendre une décision de ce type.
J'ajoute ma propre recommandation : quand ces décisions impactent l'architecture du logiciel que vous développez, je vous invite à les tracer dans un [Architecture Decision Record](https://github.com/joelparkerhenderson/architecture-decision-record?tab=readme-ov-file#what-is-an-architecture-decision-record) (ADR) 🇬🇧, en explicitant les avantages et inconvénients de la techno choisie. C'est un document simple, idéalement au format markdown, qui est suivi sous Git, à côté du code. Dans ce document vous décrivez un problème à résoudre, les solutions que vous avez envisagées, celle que vous avez retenue et pourquoi. Vous notez aussi les conséquences de ce choix, qu'elles soient positives ou négatives. Pourquoi faire ça ? D'une part cela oblige à se poser un minimum de questions lors d'un choix d'architecture, et cela permet de partager ses réflexions avec le reste de l'équipe. D'autre part, cela permet de garder une trace, qui pourra s'avérer utile à l'avenir : quand dans quelques années, quelqu'un se demandera pourquoi telle techno a été choisie, il en trouvera les raisons dans un ADR ; et pourra ainsi juger s'il est pertinent ou pas de remettre en cause ce choix. J'ajoute ma propre recommandation : quand ces décisions impactent l'architecture du logiciel que vous développez, je vous invite à les tracer dans un [Architecture Decision Record](https://github.com/joelparkerhenderson/architecture-decision-record?tab=readme-ov-file#what-is-an-architecture-decision-record) (ADR) 🇬🇧, en explicitant les avantages et inconvénients de la techno choisie. C'est un document simple, idéalement au format markdown, qui est suivi sous Git, à côté du code. Dans ce document vous décrivez un problème à résoudre, les solutions que vous avez envisagées, celle que vous avez retenue et pourquoi. Vous notez aussi les conséquences de ce choix, qu'elles soient positives ou négatives. Pourquoi faire ça ? D'une part cela oblige à se poser un minimum de questions lors d'un choix d'architecture, et cela permet de partager ses réflexions avec le reste de l'équipe. D'autre part, cela permet de garder une trace, qui pourra s'avérer utile à l'avenir : quand dans quelques années, quelqu'un se demandera pourquoi telle techno a été choisie, il en trouvera les raisons dans un ADR ; et pourra ainsi juger s'il est pertinent ou pas de remettre en cause ce choix.

View file

@ -1,88 +0,0 @@
Title: Lettre n°6 - 12 janvier 2026
Date: 2026-01-12 09:00
Category: Newsletter
JsonLD: { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°6 - 12 Janvier 2026", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Jan 12 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } }
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">
## Utiliser des graphiques pour tirer un meilleur parti des métriques DORA
Egor Savochkin explique comment identifier, à l'aide de graphiques, [l'impact des changements de pratiques et d'organisation](https://www.infoq.com/articles/DORA-metrics-PBCs/) 🇬🇧 sur la performance d'une équipe de développement.
La performance est mesurée par [les métriques DORA](https://blog.stephane-robert.info/docs/devops/dora/) 🇫🇷, telles que décrites dans [Accelerate](https://en.wikipedia.org/wiki/DevOps_Research_and_Assessment) 🇬🇧 :
* la durée entre la création d'un _commit_ et sa mise en production
* la fréquence de mise en production ;
* le pourcentage des déploiements qui causent un incident en production ;
* le temps requis pour restaurer le service après un incident.
Suivre l'évolution de ces métriques sur des graphiques "process comportement" (PBC) permet de distinguer les évènements exceptionnels des changements qui ont un impact durable. Cela confirme —ou infirme— l'efficacité des expérimentations menées par les équipes, au lieu de se baser sur des ressentis.
Il rappelle que les métriques sont un instrument de mesure, pas un objectif. L'absence de récompense liées aux métriques assure qu'il n'y aura pas de tricherie.
## Langage C3
Le [langage C3](https://c3-lang.org/) se base sur le C, et peut être mêlé avec du C, comme le Typescript avec du JavaScript. Il apporte de nombreuses fonctionnalités par rapport à son aîné : génériques, programmation par contrats, type Option pour la gestion de valeurs nulles, etc.
## Des livres d'intro à Git, Bash, SQL, Docker, Laravel...
Bobby Iliev a écrit [une série de livres](https://github.com/bobbyiliev) 🇬🇧, dont certains sont disponibles en open source, au format électronique :
- 📖   Introduction to Bash Scripting
- 📗   Introduction to Git and GitHub
- 📕   Introduction to SQL
- 🐳   Introduction to Docker
- 💡   Laravel tips and tricks
Pour les deux premiers, une partie des chapitres est aussi disponible sous forme de vidéo.
Il a aussi publié des livres qui ne sont pas disponibles gratuitement :
- 🌍   Introduction to Terraform
- 🐧   Introduction to Linux
## Les problèmes posés par la relecture de code
L'usage des Pull Requests (PR) de Github ou leur équivalent Gitlab, les Merge Requests, est la norme pour la plupart des équipes de développement. Ces pratiques visent à détecter des bugs et à ce que les standards de l'équipe soient respectés. Elles ont pour conséquence une diffusion de la connaissance du code.
Toutefois elles ne sont pas sans défaut. Un problème fréquent, posé par la dépendance envers les collègues sollicités pour la relecture, est qu'ils/elles mettent parfois plusieurs jours à faire leurs retours. Un autre problème, qui peut être la cause du précédent, c'est la taille trop importante de certaines PR —symptôme révélateur d'une durée de vie trop longue de la branche. Personne n'a envie de relire des PR de plusieurs milliers de lignes. A l'inverse, une PR au contenu trivial ne justifie pas que l'on sollicite des collègues pour une relecture —qui, si elle est rendue obligatoire, n'a pas vraiment de sens dans ce cas. Tous ces problèmes nuisent à la productivité des équipes.
Une première solution est décrite par MartinFowler dans [Ship / Show / Ask](https://martinfowler.com/articles/ship-show-ask.html) 🇬🇧. Il propose d'adopter des processus différents en fonction de la nature de la PR.
Une solution plus radicale consiste à passer au [Trunk Based Development](https://thinkinglabs.io/articles/2025/07/21/on-the-benefits-of-trunk-based-development.html) 🇬🇧, dans lequel les branches ont une durée de vie maximale d'une journée, et sont relues, si besoin, après leur fusion dans la branche principale. C'est une des pratiques employées par les équipes les plus performantes, d'après Accelerate.
## Les chiffres que devraient connaître les développeurs Python
Michael Kennedy a effectué une série de benchmarks, dont il livre [les résultats](https://mkennedy.codes/posts/python-numbers-every-programmer-should-know/) 🇬🇧 de façon synthétique. On y découvre que la consommation mémoire d'un processus Python vide est de 16 Mo, tandis qu'importer FastAPI est 500 fois plus long qu'écrire sur disque un fichier d'un Mo.
## JuJutsu pour les utilisateurs de Git
JJ, dont je vous ai parlé dans [la lettre n° 4](https://www.craftletter.fr/lettre-ndeg4-29-decembre-2025.html), est une alternative à Git, avec qui il est compatible.
[jj cheatsheet for Git users](https://gist.github.com/elithrar/4a09ef750af5624b729a6f1d87a0431c) 🇬🇧 est un aide mémoire qui m'a été utile ces derniers jours.
## JuJutsu, pre-commit et Prek
[pre-commit](https://pre-commit.com/) est un outil qui permet d'exécuter une série de vérifications sur le code avant de le commiter. Les contrôles de base, que vous pouvez choisir d'activer ou pas, sont extensibles au moyen de plugins. Certains peuvent corriger automatiquement les problèmes qu'ils détectent. Il va par exemple vérifier le formatage du code, l'absence d'instructions de debug, le respect de bonnes pratiques du langage, etc. Plus d'une douzaine de langages de programmation sont supportés, ainsi que les Dockerfile.
Il s'enregistre comme un hook Git, ce qui fait qu'il se déclenche automatiquement quand vous tentez de commiter du code. Si certaines de vérifications ne sont pas satisfaites, le commit échoue.
JJ n'est pas compatible, pour l'instant, avec pre-commit. Mais il existe une solution : [jj-pre-push](https://pypi.org/project/jj-pre-push/).
pre-commit est écrit en Python. Malgré cela, son exécution est plutôt rapide, car il ne traite, par défaut, que les fichiers que vous avez modifiés. C'est toutefois une bonne idée de l'exécuter dans les pipelines de CI avec pre-commit run --all, de façon à vérifier l'intégralité du code. Non seulement cela garantit que tout votre code respecte les standards que vous avez définis, mais aussi cela permet de pallier au fait que certains développeurs peuvent ne pas l'exécuter sur leur poste.
Si pre-commit n'est pas assez rapide pour vous, il existe une réécriture en Rust, nommée [Prek](https://prek.j178.dev/).
## L'open source en danger ?
Tailwind Labs, malgré le succès croissant de son framework CSS, a vu ses revenus s'effondrer depuis 2 ans. [Les trois quarts des membres de l'équipe technique viennent d'être été licenciés](https://loud-technology.com/blog/tailwind-labs-ia-menace-modele-economique-open-source/) 🇫🇷. En cause : les LLM, qui ont détruit le modèle économique de l'entreprise. Leur usage massif remet en cause la pérennité de nombreux projets open source.
## Les bases de données en 2025
Andy Pavlo publie sa [rétrospective annuelle sur les bases de données](https://www.cs.cmu.edu/~pavlo/blog/2026/01/2025-databases-retrospective.html) 🇬🇧. Il évoque la domination de Postgresql, le procès intenté par MongoDB .inc à l'encontre de Ferret .inc, les formats des fichiers de données...
## Rétro-ingénierie de jeux vidéo
Fabien Sanglard a écrit plusieurs livres qui sont devenus des références en matière de rétro-ingénierie de jeux vidéo. [Le premier est consacré à Wolfenstein 3D](https://fabiensanglard.net/gebbwolf3d/) 🇬🇧, l'ancêtre de DOOM. [Le second](https://fabiensanglard.net/gebbdoom/) 🇬🇧 décortique le code et les algorithmes de DOOM, qui était une révolution technique en son temps, ainsi que le matériel sur lequel il tournait dans les années 90 (ordinateurs et consoles). [Le dernier](https://fabiensanglard.net/cpsb/) 🇬🇧 couvre le matériel et le logiciel utilisés par CAPCOM pour faire tourner sur des bornes d'arcade des jeux comme Street Fighter II, Ghoulsn Ghosts, ou Final Fight.

View file

@ -1,70 +0,0 @@
Title: Lettre n°7 - 19 janvier 2026
Date: 2026-01-19 09:00
Category: Newsletter
JsonLD: <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°7", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Jan 19 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } </script>
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">
# Lettre N°7
Voici quelques articles qui mont marqué ces derniers jours.
Bonne lecture !
---
## DataStar
Vous avez probablement déjà entendu parler de [HTMX](https://htmx.org/). Cest un framework JS léger, qui vise à fournir une expérience proche de celle des Single Page Applications, mais en écrivant pas ou peu de JavaScript. Les interactions avec lapplication déclenchent lenvoi de fragments HTML par le serveur, de façon à mettre à jour la page. Il ny a pas déchange de JSON comme avec React, Vue, Angular, Elm ou équivalent. Létat de lapplication, et sa logique, sont gérés côté serveur, dans un langage au choix (Java, PHP, Go…)
[DataStar](https://data-star.dev/) a le même objectif, mais corrige les défauts de HTMX. En effet, ce dernier montre ses limites quand les fonctionnalités des applications senrichissent. Il faut ajouter du JavaScript, et la complexité du code HTMX augmente significativement. DataStar résout ces problèmes : le code back-end seul suffit à la réalisation dapplications riches. De plus, en se basant sur les SSE (Server Side Events), il simplifie le développement dapplications collaboratives. Cerise sur le gâteau, il cumule légèreté et performances, ce qui est parfait pour une démarche déco-conception et résulte en une bonne expérience utilisateur.
## Les frameworks Python en production
Dans [ce podcast](https://talkpython.fm/episodes/show/533/web-frameworks-in-prod-by-their-creators), les créateurs de framerworks Python (Flask, Django, FastAPI, Litestat et Quart) partagent leurs recommandations en terme de stack, de performances, dasynchronisme, . dauto-hébergement… Une synthèse écrite est disponible.
Quelques points en particulier ont retenu mon attention :
* [uvloop](https://github.com/MagicStack/uvloop) fournit une boucle dévénements deux fois plus rapide que celle dasyncio ;
* [orjson](https://github.com/ijl/orjson) est plus rapide que le module JSON de la bibliothèque standard de Python, tout en assurant la sérialisation de types non supportés par ce dernier ;
* un unique appel de fonction bloquant suffit à bloquer lintégralité dune application pendant son exécution. En pratique, il ne faut déclarer comme asynchrone que les fonctions dont nous sommes certains quelles ne comportent que des appels non-bloquants.
Les participants mentionnent aussi leur intérêt pour certaines technos dont je vous ai parlé récemment : HTMX, DataStar et [Sqlite](https://www.craftletter.fr/lettre-ndeg2-15-decembre-2025.html).
## SoCraTes Rennes
*Pour être transparent, je me dois de préciser que je suis organisateur de cet évènement.*
La sixième édition de [SoCraTes Rennes](https://socrates-rennes.github.io/) aura lieu le 31 mars 2026. Il sagit de la déclinaison, sur une journée, des non-conférences SoCraTes telles que [SoCraTes France](https://socrates-fr.github.io/). SoCraTes signifie "SOftware Craft and Testing". Le néologisme "non-conférence" retranscrit le fait que ce nest pas léquipe dorganisation qui définit le programme. Ce sont les participant·e·s qui ont la possibilité de proposer des sujets, sur place. Ce que jaime dans ce type dévènement cest la richesse des échanges, bien supérieure à celle des conférences traditionnelles.
Si vous souhaitez donner de la visibilité à votre entreprise, il est encore possible de [sponsoriser cette journée](https://socrates-rennes.frama.space/s/oGgqEkSADLBYaX8). Parlez-en à votre employeur 😉
## Comment fonctionne un terminal ?
Si vous voulez savoir comment fonctionne un terminal, voici [la réponse](https://how-terminals-work.vercel.app/), sous forme interactive.
## Se lancer dans lopen source
[Contrib.FYI](https://k-dash.github.io/contrib-fyi/) liste des tâches à réaliser sur des projets open-source Ces tâches sont adaptées à une première contribution. Elles sont affichées par ordre chronologique, dans le but de faciliter des découvertes par sérendipité.
## Lefficacité du pair-programming
Thierry De Pauw [débunke un post critique à légard du pair-programming](https://thinkinglabs.io/articles/2026/01/13/on-the-effectiveness-of-pair-programming.html). Il explique pourquoi, contrairement à une croyance répandue, il coûte moins cher de travailler à deux plutôt que seul sur les sujets exploratoires. Il évoque aussi des avantages comme la diffusion de la connaissance et limpact positif sur le moral de léquipe. Il conclut en mentionnant que le Software Teaming (aussi appelé Mob Programming ou Ensemble Programming) est encore plus efficace que le Pair Programming.
Ce sujet me parle, puisque jai donné [une conférence](https://devconf.net/talk/pair-programming-et-si-on-gagnait-du-temps-pascal-le-merrer) qui développait des arguments similaires.
## Combien y a-t-il de moteurs JavaScript ?
Le nombre de [moteurs qui permettent dexécuter du code JavaScript](https://zoo.js.org/) est étonnant.
## Stratégie européenne pour un écosystème numérique ouvert
La Commission Européenne commence enfin à prendre conscience de limportance de lOpen Source, et de notre dépendance excessive aux solutions États-Uniennes. Si ces sujets vous préoccupent, vous pouvez [donner votre avis](https://ec.europa.eu/info/law/better-regulation/have-your-say/initiatives/16213-Ecosystemes-numeriques-ouverts-europeens_fr), en espérant quil sera pris en compte dans de futures lois.
## Docker veut simplifier les déploiements en production
Docker Compose est adapté au développement dapplications, pas à leur déploiement en production. Ce dernier passe souvent par des outils complexes, tels que Helm ou Kustomize, configurés à grand renfort de fichiers YAML.
Docker a lancé [un nouvel outil nommé Kanvas](https://www.infoq.com/news/2026/01/docker-kanvas-cloud-deployment/), qui utilise la syntaxe familière de Docker Compose, et revendique une plus grande simplicité que ses concurrents. Il génère aussi une représentation graphique détaillée de larchitecture, qui peut savérer utile aussi bien pour communiquer que pour débugger.
----
Cest tout pour cette semaine !

View file

@ -1,74 +0,0 @@
Title: Lettre n°8 — 26 janvier 2026
Date: 2026-01-26 09:00
Category: Newsletter
JsonLD: <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°8", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Jan 26 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } </script>
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">
# Lettre n° 8
## Tendances de la tech en 2025
InfoQ a rassemblé dans un *ebook* leurs articles de synthèse sur [les tendances de la tech 2025](https://www.infoq.com/minibooks/2025-infoq-trends-reports-emag/) 🇬🇧. Ils y détaillent pour 5 domaines leur vision (subjective) de ladoption de certaines technologies et pratiques :
* Architecture logicielle et conception ;
* Culture et méthodes ;
* AI, ML et Data Engineering ;
* Cloud et Devops ;
* Java (au sens large : cela inclut divers langages qui fonctionnent sur la JVM, comme Kotlin, Scala, Clojure…).
À chaque fois, ils positionnent ladoption de ces technologies et pratiques selon des paliers inspirés de la théorie de la diffusion de linnovation, dEverett Rogers :
* innovateurs,
* primo-adoptants,
* majorité précoce,
* majorité tardive.
Cette classification est établie et commentée par les rédacteurs qui contribuent à InfoQ tout au long de lannée dans ces différents domaines.
## Plakar
Tar est un format darchivage qui date de 1979. À cette époque, les données étaient enregistrées sur bande magnétique. Cest un format simple, qui se contente de concaténer le contenu de plusieurs fichiers, sans même les compresser.
[Plakar](https://github.com/PlakarKorp/plakar) 🇬🇧 est un format récent, qui se veut un remplaçant de Tar. Par rapport à ce dernier, il ajoute de la compression, de la déduplication, du chiffrement, du versionnement… De plus, les données sont consultables sans être extraites entièrement, et il est beaucoup plus rapide grâce à la parallélisation.
## Pourquoi Zig est-il si cool ?
Nilo Stolte est _très_ expérimenté. Il explique pourquoi [Zig est un langage dont certaines fonctionnalités limpressionnent](https://nilostolte.github.io/tech/articles/ZigCool.html)🇬🇧. En particulier des fonctionnalités quil pensait réservées aux langages interprétés, qu'il présente dans un tutoriel d'introduction au langage.
## JQuery nest pas mort !
JQuery fête ses vingt ans en publiant une [nouvelle version majeure](https://blog.jquery.com/2026/01/17/jquery-4-0-0/)🇬🇧 ! Cest une surprise, car, avec les *Single Page Applications* et les progrès des navigateurs, il faut avouer que cette bibliothèque omniprésente dans les projets Web du début des années 2000 a pris un gros coup de vieux.
## Détection de fuite mémoire dans les navigateurs avec Memlab
Facebook a publié en open source [MemLab](https://github.com/facebook/memlab)🇬🇧, un outil pour détecter les fuites de mémoire causées par du code JavaScript exécuté par un navigateur. Il sappuie sur Puppeteer, un outil dautomatisation des tests. Il est utilisé ici pour décrire les scénarios à exécuter dans le navigateur, et pour lesquels MemLab va rechercher déventuelles fuites de mémoire.
## Les challenges du Soft Delete
Au lieu deffacer des données dune base, vous pouvez ajouter une colonne qui indique quand elles ont été archivées, afin de pouvoir annuler cet "effacement", ou à des fins de traçabilité. Cest ce quon appelle un *soft delete*. Cette approche peut avoir des conséquences gênantes, mais [il existe des alternatives](https://atlas9.dev/blog/soft-delete.html)🇬🇧.
## Pourquoi est-il difficile dêtre fainéant ?
SpeakEZ Technology explique comment sont gérées, dans différents langages, [les variables ou expressions *lazy*](https://speakez.tech/blog/why-lazy-is-hard/)🇬🇧. *Lazy* signifie ici quelles ne sont évaluées que lorsquon y accède pour la première fois. Le terme employé en français, *initialisation tardive*, est bien plus clair.
## Supprimer Rust pour améliorer les performances
Souvent, pour améliorer les performances, une réécriture de la totalité ou dune partie du code en Rust est une bonne piste. Mais chez Prisma, qui développe un ORM en TypeScript, cest linverse qui sest produit : la [réécriture dun module Rust en TypeScript](https://www.prisma.io/blog/announcing-prisma-orm-7-0-0#moving-away-from-rust)🇬🇧 a rendu les requêtes trois fois plus rapides !
## Serendipitech
Anne-Laure Gros vient de lancer [Serendipitech](https://www.serendipitech.fr/)🇫🇷, un site qui recense des conférences Agiles, Craft et Tech, et vous informe des ouvertures / fermetures de CFP.
## Le CFP du Breizhcamp est ouvert
Le [CFP du Breizhcamp](https://sessionize.com/breizhcamp-2026)🇫🇷, la conférence tech Rennaise qui aura lieu du 24 au 26 juin prochains, est ouvert.
## Rennes Tech
Pour continuer dans lactualité tech Rennaise, le site [Rennes Tech](https://rennes.tech/)🇫🇷, qui recense lactualité des communautés techniques de la ville, renait de ses cendres.
----
Cest tout pour cette semaine !

View file

@ -1,72 +0,0 @@
Title: Lettre n°9 - 02 février 2026
Date: 2026-02-02 09:00
Category: Newsletter
JsonLD: <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°9", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Feb 02 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } </script>
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">
## Écoute le vieux sage…
Addy Osmany nest pas si vieux, mais partage sa sagesse à travers [des leçons quil a tirées de son expérience chez Google](https://addyosmani.com/blog/21-lessons/)🇬🇧. Elles me paraissent pertinentes, même si bien entendu tout nest pas nouveau dans ce quil écrit. Comme la [loi de Goodhart](https://fr.wikipedia.org/wiki/Loi_de_Goodhart)🇫🇷, quil cite sans la nommer.
## Choisir des icônes
Stéphanie Walter donne une série de recommandations sur la façon de [choisir des icônes](https://stephaniewalter.design/blog/tips-on-how-to-pick-the-right-icons-for-your-website-with-icons8) 🇫🇷. Elle sadresse à des personnes qui nont pas ou peu de notions de design.
## Git bisect
Si je devais classer les commandes Git par utilité, [git bisect](https://engineering.leanix.net/blog/git-bisect/)🇬🇧 serait probablement dans le trio de tête. Elle permet de retrouver rapidement le commit à lorigine dun bug. Mais pour quelle soit efficace, il est indispensable de faire de petits commits. Savoir quun problème a été introduit par une modification de mille lignes de code ne serait pas très utile.
## Outils de développement et tests dAPI
Vous connaissez probablement [Postman](https://www.postman.com/), un outil pour stocker et jouer des requêtes HTTP, très utile quand on développe une API. Cet outil open source populaire [sest dégradé](https://readmedium.com/enshittification-of-a-beloved-open-source-tool-postman-24e0837bcff7)🇬🇧 au fil du temps. Le stockage des requêtes, depuis quil se fait sur les serveurs de lentreprise derrière Postman, pose des problèmes de confidentialité.
Jai utilisé [Bruno](https://www.usebruno.com/), un outil similaire. Je viens de découvrir quil était maintenant au centre dune offre payante. Je nai rien contre le principe, il me parait normal dessayer de vivre de son travail. Jespère juste que cela ne se traduira pas par une évolution comparable à celle de Postman —ce nest pas le cas pour linstant.
[Posting](https://posting.sh/) : qui propose des fonctionnalités similaires, mais dans le terminal. La roadmap, définie par la communauté, est toutefois un peu surprenante : avoir un fond de fenêtre transparent y est plus urgent que pouvoir modifier les paramètres ou en-têtes des requêtes 🤔
Il existe dautres outils de ce type, comme [Hoppscotch](https://docs.hoppscotch.io/), qui est proposé en SAAS, mais aussi en auto-hébergement.
## {JSON} Placeholder
[{JSON} Placeholder](https://jsonplaceholder.typicode.com/) expose une API que vous pouvez utiliser quand vous avez besoin dune API rapidement, mais qui na finalement que peu dimportance pour vous. Elle peut servir dans le cadre dune formation, dun kata de code, dune démo, dune présentation… Elle expose des endpoints pour gérer des posts, des commentaires, des albums, des photos, des listes de tâches, et des utilisateurs.
## Les logs, ça craint
Beaucoup de logs sont inutiles, parce quils manquent de contexte. Le problème nest pas nouveau, loin de là, mais il est encore dactualité. De plus, rechercher lorigine dun bug dans les logs dun site à fort trafic sapparente à chercher une aiguille dans une botte de foin. Boris Tane explique [comment les Wide Events aident à résoudre ces problèmes](https://loggingsucks.com/).
## Un livre gratuit sur laccessibilité
[Accessibility for Everyone](https://accessibilityforeveryone.site/) de Laura Kalbag nest pas récent, il date de 2017, mais nest pas complètement obsolète non plus. Si les outils ont changé, les principes quil décrit restent valides. Il est dorénavant disponible gratuitement.
## Forum Ruby
Un nouveau [forum](https://www.rubyforum.org)🇬🇧 pour la communauté Ruby est en ligne. Il est dédié aux échanges entre développeurs/développeuses, quel que soit leur niveau ; de façon surprenante pour moi, les offres demploi ny sont pas les bienvenues.
## Comment les LLM sabotent les pratiques de programmation en privatisant un bien public
Michiel Buddingh explique comment les entreprises qui créent des LLM sont en train de nous faire [revenir à la situation qui prévalait avant lavènement du Web](https://michiel.buddingh.eu/enclosure-feedback-loop)🇬🇧 : laccès à la connaissance était payant.
## Quand refactorer votre code ?
Nick Cosentino liste des signes révélateurs de la [nécessité de refactorer votre code](https://www.devleader.ca/2023/11/24/when-to-refactor-code-how-to-maximize-efficiency-and-minimizing-tech-debt/)🇬🇧.
Il cite aussi quelques techniques de refactoring. Jai regretté, à la lecture de cet article, quil recommande de définir des métriques pour mesurer lefficacité du refactoring, sans en mentionner.
## Créer des applications Python pour le terminal
[Rich](https://rich.readthedocs.io/en/stable/introduction.html) est une bibliothèque bien connue du monde Python, pour améliorer laffichage des données dans le terminal. [Textual](https://www.textualize.io/) va plus loin, car il sagit dun framework pour créer de véritables applications. [Typer](https://typer.tiangolo.com/), bien quil se présente comme un équivalent, me semble moins riche fonctionnellement. Par contre son haut niveau dabstraction fait quil peut être intéressant pour ce qui est de parser les arguments de la ligne de commande.
## Elm serait-il un bon choix pour votre équipe ?
Brian Dukes détaille les raisons qui font quune techno de niche comme Elm peut [être, ou ne pas être, un bon choix](https://engagesoftware.com/posts/is-elm-the-right-choice-for-your-team/)🇬🇧 pour votre équipe. Elm est un langage fonctionnel dédié à la création de *Single Page Applications*.
## Alpes Craft 2026
[Alpes Craft](https://www.alpescraft.fr/)🇫🇷 aura lieu les 4 et 5 juin prochain. Cet évènement cumule une conférence classique, le premier jour, avec une non-conférence, le lendemain. Si vous ne connaissez pas les non-conférences, je vous invite à relire la courte description que jen ai faite dans [la lettre N°7](https://www.craftletter.fr/lettre-ndeg7-19-janvier-2026.html)🇫🇷, dans la partie consacrée à [SoCraTes Rennes](https://socrates-rennes.github.io/)🇫🇷.
Comme lindique son nom, Alpes Craft est consacré à la tech, mais pas à une technologie particulière.
---
Cest tout pour cette semaine !

View file

@ -1,9 +1,26 @@
Title: Accueil Title: Accueil
Date: 2026-02-09 09:00 Date: 2025-01-05 09:00
URL: URL:
save_as: index.html save_as: index.html
Category: Home Category: Home
JsonLD: { "@context": "https://schema.org", "@type": "WebPage", "name": "Accueil", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Feb 09 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } }
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "Accueil",
"description": "Lettre de veille technologique en développement logiciel",
"image": [
"https://www.craftletter.fr/images/craftletter.svg"
],
"datePublished": "Mon Jan 05 2026 09:00:00 GMT+0200 (Coordinated Universal Time)",
"author": {
"@type": "Person",
"name": "Pascal Le Merrer",
"url": "https://www.linkedin.com/in/pascal-le-merrer/"
}
}
</script>
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg"> <img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">
@ -34,11 +51,6 @@ Pour savoir qui je suis, ou pourquoi j'écris cette lettre, je vous invite à vo
# Archives # Archives
* [Lettre n°10]({filename}/newsletter/craft-letter-10.md)
* [Lettre n°9]({filename}/newsletter/craft-letter-9.md)
* [Lettre n°8]({filename}/newsletter/craft-letter-8.md)
* [Lettre n°7]({filename}/newsletter/craft-letter-7.md)
* [Lettre n°6]({filename}/newsletter/craft-letter-6.md)
* [Lettre n°5]({filename}/newsletter/craft-letter-5.md) * [Lettre n°5]({filename}/newsletter/craft-letter-5.md)
* [Lettre n°4]({filename}/newsletter/craft-letter-4.md) * [Lettre n°4]({filename}/newsletter/craft-letter-4.md)
* [Lettre n°3]({filename}/newsletter/craft-letter-3.md) * [Lettre n°3]({filename}/newsletter/craft-letter-3.md)

View file

@ -1,59 +0,0 @@
CONFFILE := "pelicanconf.py"
PUBLISHCONF := "publishconf.py"
PELICANOPTS := ""
SERVER := "localhost"
default:
just --list
help:
@echo 'Set the DEBUG variable to 1 to enable debugging, e.g. make DEBUG=1 html '
@echo 'Set the RELATIVE variable to 1 to enable relative urls '
# (re)generate the web site
html:
pelican content -o output -s "{{CONFFILE}}" {{PELICANOPTS}}
# remove the generated files
clean:
[ ! -d "output" ] || rm -rf output
# regenerate files upon modification
regenerate:
pelican -r content -o output -s "{{CONFFILE}}" {{PELICANOPTS}}
# serve site at http://localhost:8000
serve:
pelican -l content -o output -s "{{CONFFILE}}" {{PELICANOPTS}}
# serve (as root) to {{SERVER}}:80
serve-global:
pelican -l content -o output -s "{{CONFFILE}}" {{PELICANOPTS}} -b {{SERVER}}
# serve and regenerate together
devserver:
pelican -lr content -o output -s "{{CONFFILE}}" {{PELICANOPTS}}
# regenerate and serve on 0.0.0.0
devserver-global:
pelican -lr content -o output -s "{{CONFFILE}}" {{PELICANOPTS}} -b 0.0.0.0
# generate using production settings
publish:
pelican content -o output -s "{{PUBLISHCONF}}" {{PELICANOPTS}}
rsync -e ssh -av --delete-after /Users/pascal/Documents/craft-letter/output/ craftletter@ssh-craftletter.alwaysdata.net:/home/craftletter/www
# connect to production server
ssh:
ssh craftletter@ssh-craftletter.alwaysdata.net
# Create the skeleton for a new issue of the newsletter, and reference it into the home page
new number:
PYTHONPATH=PWD venv/bin/python ./scripts/create_newsletter.py --number={{number}}
# generate HTML email
mail file:
echo {{file}}
PYTHONPATH=PWD venv/bin/python ./scripts/prepare_email.py {{file}}

Binary file not shown.

Binary file not shown.

View file

@ -238,8 +238,3 @@ i {
display: block; display: block;
} }
hr {
color: #CCCCCC;
margin-top: 40px;
margin-bottom: 40px;
}

View file

@ -1,72 +0,0 @@
import argparse
import locale
from pathlib import Path
from datetime import datetime, timedelta
MONDAY = 0 # 0 = Monday, 1=Tuesday, 2=Wednesday...
def get_next_weekday(d, weekday):
days_ahead = weekday - d.weekday()
if days_ahead <= 0: # Target day already happened this week
days_ahead += 7
return d + timedelta(days_ahead)
def set_publication_date_for_humans(text: str, publication_date: datetime) -> str:
locale.setlocale(locale.LC_TIME, "fr_FR")
date = publication_date.strftime("%d %B %Y")
return text.replace("{DATE}", date)
def set_publication_date_for_pelican(text: str, publication_date: datetime) -> str:
date_digits = publication_date.isoformat()[0:10]
return text.replace("{DATE_DIGITS}", date_digits)
def set_publication_date_for_seo(text: str, publication_date: datetime) -> str:
locale.setlocale(locale.LC_TIME, "en_US")
date_utc = publication_date.strftime("%a %b %d %Y")
return text.replace("{DATE_UTC}", date_utc)
# Parse the command line arguments
parser = argparse.ArgumentParser()
parser.add_argument("-n", "--number", required=True, type=int, help="Newsletter number")
args = parser.parse_args()
# Load the newsletter template
template = Path("./template/newsletter.md")
content = template.read_text()
new_content = content.replace("{LETTER_NUMBER}", str(args.number))
today = datetime.today()
next_monday = get_next_weekday(today, MONDAY)
new_content = set_publication_date_for_humans(new_content, next_monday)
new_content = set_publication_date_for_pelican(new_content, next_monday)
new_content = set_publication_date_for_seo(new_content, next_monday)
# Create the new file
destination = Path(f"./content/newsletter/craft-letter-{args.number}.md")
destination.write_text(new_content)
# Load the homepage template
template = Path("./template/index.md")
content = template.read_text()
new_content = set_publication_date_for_pelican(content, next_monday)
new_content = set_publication_date_for_seo(new_content, next_monday)
for i in reversed(range(args.number)):
link = f"* [Lettre n°{i + 1}]({{filename}}/newsletter/craft-letter-{i + 1}.md)\n"
new_content += link
# Update the index page
destination = Path("./content/pages/index.md")
destination.write_text(new_content)

View file

@ -1,36 +0,0 @@
Title: Accueil
Date: {DATE_DIGITS} 09:00
URL:
save_as: index.html
Category: Home
JsonLD: { "@context": "https://schema.org", "@type": "WebPage", "name": "Accueil", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "{DATE_UTC} 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } }
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">
La Craft Letter est une newsletter hebdomadaire dans laquelle je partage des articles
issues de ma veille technologique. Vous y trouverez des articles relatifs au développement logiciel d'une façon générale, qu'il soit front-end, back-end ou autre. Mais aussi des articles consacrés à l'architecture logicielle, la méthodologie, les outils, des projets open source, des conférences...
Pour savoir qui je suis, ou pourquoi j'écris cette lettre, je vous invite à vous lire l'édito du [premier numéro]({filename}/newsletter/craft-letter-1.md).
<script>
(function (s, e, n, d, er) {
s['Sender'] = er;
s[er] = s[er] || function () {
(s[er].q = s[er].q || []).push(arguments)
}, s[er].l = 1 * new Date();
var a = e.createElement(n),
m = e.getElementsByTagName(n)[0];
a.async = 1;
a.src = d;
m.parentNode.insertBefore(a, m)
})(window, document, 'script', 'https://cdn.sender.net/accounts_resources/universal.js', 'sender');
sender('7ce69975e53330')
</script>
<div style="text-align: center" class="sender-form-field" data-sender-form-id="av2kqL"></div>
---
# Archives

View file

@ -1,5 +1,25 @@
Title: Lettre n°{LETTER_NUMBER} - {DATE} Title: Lettre n°{LETTER_NUMBER} - {DATE}
Date: {DATE_DIGITS} 09:00 Date: {DATETIME}
Category: Newsletter Category: Newsletter
JsonLD: <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°{LETTER_NUMBER}", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "{DATE_UTC} 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } </script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"name": "Lettre n°{LETTER_NUMBER}",
"description": "Lettre de veille technologique en développement logiciel",
"image": [
"https://www.craftletter.fr/images/craftletter.svg"
],
"datePublished": "{DATETIME_UTC} (Coordinated Universal Time)",
"author": {
"@type": "Person",
"name": "Pascal Le Merrer",
"url": "https://www.linkedin.com/in/pascal-le-merrer/"
}
}
</script>
<img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg"> <img class="logo" alt="Logo Craft Letter" src="{static}/images/craftletter.svg">