@majordigital/create-acorn 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/create-acorn.mjs +424 -19
- package/package.json +1 -1
package/bin/create-acorn.mjs
CHANGED
|
@@ -345,7 +345,7 @@ async function setupDato(projectName) {
|
|
|
345
345
|
// Install DatoCMS dependencies
|
|
346
346
|
console.log('Installing DatoCMS dependencies...');
|
|
347
347
|
await runCommand('npm', ['install', '--legacy-peer-deps',
|
|
348
|
-
'@datocms/cda-client', 'react-datocms',
|
|
348
|
+
'@datocms/cda-client', '@datocms/cma-client-node', 'react-datocms',
|
|
349
349
|
'datocms-structured-text-to-plain-text', 'datocms-structured-text-utils',
|
|
350
350
|
'graphql', 'graphql-request', 'dotenv'
|
|
351
351
|
]);
|
|
@@ -356,6 +356,79 @@ async function setupDato(projectName) {
|
|
|
356
356
|
]);
|
|
357
357
|
console.log('');
|
|
358
358
|
|
|
359
|
+
// --- DatoCMS Project Connection & Model Scaffolding ---
|
|
360
|
+
const hasExisting = await ask('Do you already have a DatoCMS project? (y/n)', 'n');
|
|
361
|
+
const isExisting = hasExisting.toLowerCase() === 'y' || hasExisting.toLowerCase() === 'yes';
|
|
362
|
+
|
|
363
|
+
if (!isExisting) {
|
|
364
|
+
console.log('');
|
|
365
|
+
console.log('Please create a new project in the DatoCMS dashboard:');
|
|
366
|
+
console.log(' https://www.datocms.com/dashboard');
|
|
367
|
+
console.log('');
|
|
368
|
+
console.log('Once created, grab your Full-access API token from:');
|
|
369
|
+
console.log(' Settings > API Tokens > Full-access API token');
|
|
370
|
+
console.log('');
|
|
371
|
+
} else {
|
|
372
|
+
console.log('');
|
|
373
|
+
console.log('Great! Grab your Full-access API token from your DatoCMS project:');
|
|
374
|
+
console.log(' Settings > API Tokens > Full-access API token');
|
|
375
|
+
console.log('');
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const apiToken = await ask('Paste your Full-access API token (or press Enter to skip)');
|
|
379
|
+
|
|
380
|
+
if (apiToken) {
|
|
381
|
+
console.log('');
|
|
382
|
+
console.log('Scaffolding DatoCMS models...');
|
|
383
|
+
console.log('');
|
|
384
|
+
|
|
385
|
+
try {
|
|
386
|
+
await scaffoldDatoModels(apiToken);
|
|
387
|
+
console.log('');
|
|
388
|
+
console.log('DatoCMS models created successfully!');
|
|
389
|
+
console.log('');
|
|
390
|
+
|
|
391
|
+
// Fetch the read-only CDA token for .env.local
|
|
392
|
+
let cdaToken = '';
|
|
393
|
+
try {
|
|
394
|
+
const { buildClient } = await import('@datocms/cma-client-node');
|
|
395
|
+
const client = buildClient({ apiToken });
|
|
396
|
+
const tokens = await client.accessTokens.list();
|
|
397
|
+
const readOnly = tokens.find(t => t.name === 'Read-only API token');
|
|
398
|
+
if (readOnly && readOnly.token) {
|
|
399
|
+
cdaToken = readOnly.token;
|
|
400
|
+
}
|
|
401
|
+
} catch {
|
|
402
|
+
// Could not fetch CDA token — user will add manually
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Write .env.local with tokens
|
|
406
|
+
const envLocalPath = join(process.cwd(), '.env.local');
|
|
407
|
+
writeFileSync(envLocalPath, `NEXT_DATOCMS_API_TOKEN=${cdaToken}
|
|
408
|
+
DATO_API_TOKEN=${apiToken}
|
|
409
|
+
NEXT_DATOCMS_ENVIRONMENT=draft
|
|
410
|
+
`);
|
|
411
|
+
if (cdaToken) {
|
|
412
|
+
console.log('Created .env.local with your API tokens.');
|
|
413
|
+
} else {
|
|
414
|
+
console.log('Created .env.local — add your Read-only API token to NEXT_DATOCMS_API_TOKEN.');
|
|
415
|
+
console.log('You can find it in Settings > API Tokens > Read-only API token.');
|
|
416
|
+
}
|
|
417
|
+
} catch (err) {
|
|
418
|
+
console.log('');
|
|
419
|
+
console.log('Warning: Could not scaffold DatoCMS models automatically.');
|
|
420
|
+
console.log(` Error: ${err.message}`);
|
|
421
|
+
console.log('');
|
|
422
|
+
console.log('You can create models manually in the DatoCMS dashboard.');
|
|
423
|
+
console.log('The GraphQL queries expect: Page, Hero (block), Button (block),');
|
|
424
|
+
console.log('Layout (singleton), MenuItem (block), CaseStudy, LegalPage, Post,');
|
|
425
|
+
console.log('CaseStudiesListing (singleton), PostListing (singleton).');
|
|
426
|
+
}
|
|
427
|
+
} else {
|
|
428
|
+
console.log('');
|
|
429
|
+
console.log('Skipping model scaffolding — you can set up models manually later.');
|
|
430
|
+
}
|
|
431
|
+
|
|
359
432
|
// Update next.config.ts — replace Prismic image patterns with DatoCMS
|
|
360
433
|
const nextConfigPath = join(process.cwd(), 'next.config.ts');
|
|
361
434
|
try {
|
|
@@ -444,7 +517,6 @@ async function setupDato(projectName) {
|
|
|
444
517
|
writeFileSync(envExamplePath, `NEXT_DATOCMS_API_TOKEN=
|
|
445
518
|
DATO_API_TOKEN=
|
|
446
519
|
NEXT_DATOCMS_ENVIRONMENT=draft
|
|
447
|
-
NEXT_PUBLIC_SITE_URL=
|
|
448
520
|
`);
|
|
449
521
|
console.log('Updated .env.example with DatoCMS variables.');
|
|
450
522
|
} catch {
|
|
@@ -456,24 +528,357 @@ NEXT_PUBLIC_SITE_URL=
|
|
|
456
528
|
console.log('');
|
|
457
529
|
console.log('=== Next Steps ===');
|
|
458
530
|
console.log('');
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
531
|
+
if (!apiToken) {
|
|
532
|
+
console.log(' 1. Create a DatoCMS project at https://www.datocms.com/dashboard');
|
|
533
|
+
console.log('');
|
|
534
|
+
console.log(' 2. Get your API token from Settings > API Tokens');
|
|
535
|
+
console.log('');
|
|
536
|
+
console.log(' 3. Add your token to .env.local:');
|
|
537
|
+
console.log(' NEXT_DATOCMS_API_TOKEN=your_read_only_token');
|
|
538
|
+
console.log(' NEXT_DATOCMS_ENVIRONMENT=draft');
|
|
539
|
+
console.log('');
|
|
540
|
+
console.log(' 4. Create your models in the DatoCMS dashboard');
|
|
541
|
+
console.log('');
|
|
542
|
+
console.log(' 5. Generate TypeScript types from your schema:');
|
|
543
|
+
console.log(' npm run generate-types');
|
|
544
|
+
console.log('');
|
|
545
|
+
} else {
|
|
546
|
+
console.log(' 1. Generate TypeScript types from your schema:');
|
|
547
|
+
console.log(' npm run generate-types');
|
|
548
|
+
console.log('');
|
|
549
|
+
console.log(' 2. Start your dev server:');
|
|
550
|
+
console.log(' npm run dev');
|
|
551
|
+
console.log('');
|
|
552
|
+
console.log(' 3. Open your DatoCMS dashboard to add content to your models.');
|
|
553
|
+
console.log('');
|
|
554
|
+
}
|
|
555
|
+
console.log(' Start your dev server:');
|
|
473
556
|
console.log(' npm run dev');
|
|
474
557
|
console.log('');
|
|
475
558
|
}
|
|
476
559
|
|
|
560
|
+
/**
|
|
561
|
+
* Scaffold default DatoCMS models using the Management API.
|
|
562
|
+
* Creates models that match the GraphQL queries in the dato-api layer.
|
|
563
|
+
*/
|
|
564
|
+
async function scaffoldDatoModels(apiToken) {
|
|
565
|
+
const { buildClient } = await import('@datocms/cma-client-node');
|
|
566
|
+
const client = buildClient({ apiToken });
|
|
567
|
+
|
|
568
|
+
// --- Block models (must be created first so we can reference them) ---
|
|
569
|
+
|
|
570
|
+
// Button block
|
|
571
|
+
console.log(' Creating Button block...');
|
|
572
|
+
const buttonBlock = await client.itemTypes.create({
|
|
573
|
+
name: 'Button',
|
|
574
|
+
api_key: 'button',
|
|
575
|
+
modular_block: true,
|
|
576
|
+
});
|
|
577
|
+
await client.fields.create(buttonBlock.id, {
|
|
578
|
+
label: 'Text',
|
|
579
|
+
field_type: 'string',
|
|
580
|
+
api_key: 'text',
|
|
581
|
+
validators: { required: {} },
|
|
582
|
+
});
|
|
583
|
+
await client.fields.create(buttonBlock.id, {
|
|
584
|
+
label: 'Variant',
|
|
585
|
+
field_type: 'string',
|
|
586
|
+
api_key: 'variant',
|
|
587
|
+
validators: { enum: { values: ['primary', 'secondary', 'outline'] } },
|
|
588
|
+
appearance: {
|
|
589
|
+
addons: [],
|
|
590
|
+
editor: 'string_select',
|
|
591
|
+
parameters: { options: [
|
|
592
|
+
{ hint: '', label: 'Primary', value: 'primary' },
|
|
593
|
+
{ hint: '', label: 'Secondary', value: 'secondary' },
|
|
594
|
+
{ hint: '', label: 'Outline', value: 'outline' },
|
|
595
|
+
]},
|
|
596
|
+
},
|
|
597
|
+
});
|
|
598
|
+
await client.fields.create(buttonBlock.id, {
|
|
599
|
+
label: 'Link',
|
|
600
|
+
field_type: 'json',
|
|
601
|
+
api_key: 'link',
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
// Hero block
|
|
605
|
+
console.log(' Creating Hero block...');
|
|
606
|
+
const heroBlock = await client.itemTypes.create({
|
|
607
|
+
name: 'Hero',
|
|
608
|
+
api_key: 'hero',
|
|
609
|
+
modular_block: true,
|
|
610
|
+
});
|
|
611
|
+
await client.fields.create(heroBlock.id, {
|
|
612
|
+
label: 'Heading',
|
|
613
|
+
field_type: 'string',
|
|
614
|
+
api_key: 'heading',
|
|
615
|
+
validators: { required: {} },
|
|
616
|
+
});
|
|
617
|
+
await client.fields.create(heroBlock.id, {
|
|
618
|
+
label: 'Eyebrow',
|
|
619
|
+
field_type: 'string',
|
|
620
|
+
api_key: 'eyebrow',
|
|
621
|
+
});
|
|
622
|
+
await client.fields.create(heroBlock.id, {
|
|
623
|
+
label: 'Content',
|
|
624
|
+
field_type: 'text',
|
|
625
|
+
api_key: 'content',
|
|
626
|
+
appearance: {
|
|
627
|
+
addons: [],
|
|
628
|
+
editor: 'textarea',
|
|
629
|
+
parameters: {},
|
|
630
|
+
},
|
|
631
|
+
});
|
|
632
|
+
await client.fields.create(heroBlock.id, {
|
|
633
|
+
label: 'Layout',
|
|
634
|
+
field_type: 'string',
|
|
635
|
+
api_key: 'layout',
|
|
636
|
+
validators: { enum: { values: ['default', 'centered', 'split'] } },
|
|
637
|
+
appearance: {
|
|
638
|
+
addons: [],
|
|
639
|
+
editor: 'string_select',
|
|
640
|
+
parameters: { options: [
|
|
641
|
+
{ hint: '', label: 'Default', value: 'default' },
|
|
642
|
+
{ hint: '', label: 'Centered', value: 'centered' },
|
|
643
|
+
{ hint: '', label: 'Split', value: 'split' },
|
|
644
|
+
]},
|
|
645
|
+
},
|
|
646
|
+
});
|
|
647
|
+
await client.fields.create(heroBlock.id, {
|
|
648
|
+
label: 'Theme',
|
|
649
|
+
field_type: 'string',
|
|
650
|
+
api_key: 'theme',
|
|
651
|
+
validators: { enum: { values: ['light', 'dark'] } },
|
|
652
|
+
appearance: {
|
|
653
|
+
addons: [],
|
|
654
|
+
editor: 'string_select',
|
|
655
|
+
parameters: { options: [
|
|
656
|
+
{ hint: '', label: 'Light', value: 'light' },
|
|
657
|
+
{ hint: '', label: 'Dark', value: 'dark' },
|
|
658
|
+
]},
|
|
659
|
+
},
|
|
660
|
+
});
|
|
661
|
+
await client.fields.create(heroBlock.id, {
|
|
662
|
+
label: 'Image',
|
|
663
|
+
field_type: 'file',
|
|
664
|
+
api_key: 'image',
|
|
665
|
+
});
|
|
666
|
+
await client.fields.create(heroBlock.id, {
|
|
667
|
+
label: 'Actions',
|
|
668
|
+
field_type: 'rich_text',
|
|
669
|
+
api_key: 'actions',
|
|
670
|
+
validators: {
|
|
671
|
+
rich_text_blocks: { item_types: [buttonBlock.id] },
|
|
672
|
+
},
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
// MenuItem block
|
|
676
|
+
console.log(' Creating MenuItem block...');
|
|
677
|
+
const menuItemBlock = await client.itemTypes.create({
|
|
678
|
+
name: 'Menu Item',
|
|
679
|
+
api_key: 'menu_item',
|
|
680
|
+
modular_block: true,
|
|
681
|
+
});
|
|
682
|
+
await client.fields.create(menuItemBlock.id, {
|
|
683
|
+
label: 'Heading',
|
|
684
|
+
field_type: 'string',
|
|
685
|
+
api_key: 'heading',
|
|
686
|
+
validators: { required: {} },
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
// --- Regular models ---
|
|
690
|
+
|
|
691
|
+
// Page model
|
|
692
|
+
console.log(' Creating Page model...');
|
|
693
|
+
const pageModel = await client.itemTypes.create({
|
|
694
|
+
name: 'Page',
|
|
695
|
+
api_key: 'page',
|
|
696
|
+
draft_mode_active: true,
|
|
697
|
+
});
|
|
698
|
+
await client.fields.create(pageModel.id, {
|
|
699
|
+
label: 'Heading',
|
|
700
|
+
field_type: 'string',
|
|
701
|
+
api_key: 'heading',
|
|
702
|
+
validators: { required: {} },
|
|
703
|
+
});
|
|
704
|
+
await client.fields.create(pageModel.id, {
|
|
705
|
+
label: 'Description',
|
|
706
|
+
field_type: 'text',
|
|
707
|
+
api_key: 'description',
|
|
708
|
+
});
|
|
709
|
+
await client.fields.create(pageModel.id, {
|
|
710
|
+
label: 'Slug',
|
|
711
|
+
field_type: 'slug',
|
|
712
|
+
api_key: 'slug',
|
|
713
|
+
validators: {
|
|
714
|
+
required: {},
|
|
715
|
+
slug_title_field: { title_field_id: (await client.fields.list(pageModel.id)).find(f => f.api_key === 'heading').id },
|
|
716
|
+
},
|
|
717
|
+
});
|
|
718
|
+
await client.fields.create(pageModel.id, {
|
|
719
|
+
label: 'Parent Page',
|
|
720
|
+
field_type: 'link',
|
|
721
|
+
api_key: 'parent_page',
|
|
722
|
+
validators: {
|
|
723
|
+
item_item_type: { on_publish_with_unpublished_references_strategy: 'fail', on_reference_unpublish_strategy: 'fail', on_reference_delete_strategy: 'set_null', item_types: [pageModel.id] },
|
|
724
|
+
},
|
|
725
|
+
});
|
|
726
|
+
await client.fields.create(pageModel.id, {
|
|
727
|
+
label: 'Body',
|
|
728
|
+
field_type: 'rich_text',
|
|
729
|
+
api_key: 'body',
|
|
730
|
+
validators: {
|
|
731
|
+
rich_text_blocks: { item_types: [heroBlock.id] },
|
|
732
|
+
},
|
|
733
|
+
});
|
|
734
|
+
|
|
735
|
+
// Add target link to MenuItem (now that Page exists)
|
|
736
|
+
await client.fields.create(menuItemBlock.id, {
|
|
737
|
+
label: 'Target',
|
|
738
|
+
field_type: 'link',
|
|
739
|
+
api_key: 'target',
|
|
740
|
+
validators: {
|
|
741
|
+
item_item_type: { on_publish_with_unpublished_references_strategy: 'fail', on_reference_unpublish_strategy: 'fail', on_reference_delete_strategy: 'set_null', item_types: [pageModel.id] },
|
|
742
|
+
},
|
|
743
|
+
});
|
|
744
|
+
|
|
745
|
+
// Case Study model
|
|
746
|
+
console.log(' Creating Case Study model...');
|
|
747
|
+
const caseStudyModel = await client.itemTypes.create({
|
|
748
|
+
name: 'Case Study',
|
|
749
|
+
api_key: 'case_study',
|
|
750
|
+
draft_mode_active: true,
|
|
751
|
+
});
|
|
752
|
+
await client.fields.create(caseStudyModel.id, {
|
|
753
|
+
label: 'Title',
|
|
754
|
+
field_type: 'string',
|
|
755
|
+
api_key: 'title',
|
|
756
|
+
validators: { required: {} },
|
|
757
|
+
});
|
|
758
|
+
await client.fields.create(caseStudyModel.id, {
|
|
759
|
+
label: 'Slug',
|
|
760
|
+
field_type: 'slug',
|
|
761
|
+
api_key: 'slug',
|
|
762
|
+
validators: {
|
|
763
|
+
required: {},
|
|
764
|
+
slug_title_field: { title_field_id: (await client.fields.list(caseStudyModel.id)).find(f => f.api_key === 'title').id },
|
|
765
|
+
},
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
// Legal Page model
|
|
769
|
+
console.log(' Creating Legal Page model...');
|
|
770
|
+
const legalPageModel = await client.itemTypes.create({
|
|
771
|
+
name: 'Legal Page',
|
|
772
|
+
api_key: 'legal_page',
|
|
773
|
+
draft_mode_active: true,
|
|
774
|
+
});
|
|
775
|
+
await client.fields.create(legalPageModel.id, {
|
|
776
|
+
label: 'Title',
|
|
777
|
+
field_type: 'string',
|
|
778
|
+
api_key: 'title',
|
|
779
|
+
validators: { required: {} },
|
|
780
|
+
});
|
|
781
|
+
await client.fields.create(legalPageModel.id, {
|
|
782
|
+
label: 'Slug',
|
|
783
|
+
field_type: 'slug',
|
|
784
|
+
api_key: 'slug',
|
|
785
|
+
validators: {
|
|
786
|
+
required: {},
|
|
787
|
+
slug_title_field: { title_field_id: (await client.fields.list(legalPageModel.id)).find(f => f.api_key === 'title').id },
|
|
788
|
+
},
|
|
789
|
+
});
|
|
790
|
+
await client.fields.create(legalPageModel.id, {
|
|
791
|
+
label: 'Download',
|
|
792
|
+
field_type: 'file',
|
|
793
|
+
api_key: 'download',
|
|
794
|
+
});
|
|
795
|
+
|
|
796
|
+
// Post model
|
|
797
|
+
console.log(' Creating Post model...');
|
|
798
|
+
const postModel = await client.itemTypes.create({
|
|
799
|
+
name: 'Post',
|
|
800
|
+
api_key: 'post',
|
|
801
|
+
draft_mode_active: true,
|
|
802
|
+
});
|
|
803
|
+
await client.fields.create(postModel.id, {
|
|
804
|
+
label: 'Title',
|
|
805
|
+
field_type: 'string',
|
|
806
|
+
api_key: 'title',
|
|
807
|
+
validators: { required: {} },
|
|
808
|
+
});
|
|
809
|
+
await client.fields.create(postModel.id, {
|
|
810
|
+
label: 'Slug',
|
|
811
|
+
field_type: 'slug',
|
|
812
|
+
api_key: 'slug',
|
|
813
|
+
validators: {
|
|
814
|
+
required: {},
|
|
815
|
+
slug_title_field: { title_field_id: (await client.fields.list(postModel.id)).find(f => f.api_key === 'title').id },
|
|
816
|
+
},
|
|
817
|
+
});
|
|
818
|
+
|
|
819
|
+
// Case Studies Listing (singleton)
|
|
820
|
+
console.log(' Creating Case Studies Listing singleton...');
|
|
821
|
+
const caseStudiesListing = await client.itemTypes.create({
|
|
822
|
+
name: 'Case Studies Listing',
|
|
823
|
+
api_key: 'case_studies_listing',
|
|
824
|
+
singleton: true,
|
|
825
|
+
});
|
|
826
|
+
await client.fields.create(caseStudiesListing.id, {
|
|
827
|
+
label: 'Slug',
|
|
828
|
+
field_type: 'string',
|
|
829
|
+
api_key: 'slug',
|
|
830
|
+
validators: { required: {} },
|
|
831
|
+
});
|
|
832
|
+
|
|
833
|
+
// Post Listing (singleton)
|
|
834
|
+
console.log(' Creating Post Listing singleton...');
|
|
835
|
+
const postListing = await client.itemTypes.create({
|
|
836
|
+
name: 'Post Listing',
|
|
837
|
+
api_key: 'post_listing',
|
|
838
|
+
singleton: true,
|
|
839
|
+
});
|
|
840
|
+
await client.fields.create(postListing.id, {
|
|
841
|
+
label: 'Slug',
|
|
842
|
+
field_type: 'string',
|
|
843
|
+
api_key: 'slug',
|
|
844
|
+
validators: { required: {} },
|
|
845
|
+
});
|
|
846
|
+
|
|
847
|
+
// Layout (singleton)
|
|
848
|
+
console.log(' Creating Layout singleton...');
|
|
849
|
+
const layoutModel = await client.itemTypes.create({
|
|
850
|
+
name: 'Layout',
|
|
851
|
+
api_key: 'layout',
|
|
852
|
+
singleton: true,
|
|
853
|
+
});
|
|
854
|
+
await client.fields.create(layoutModel.id, {
|
|
855
|
+
label: 'Navigation',
|
|
856
|
+
field_type: 'rich_text',
|
|
857
|
+
api_key: 'navigation',
|
|
858
|
+
validators: {
|
|
859
|
+
rich_text_blocks: { item_types: [menuItemBlock.id] },
|
|
860
|
+
},
|
|
861
|
+
});
|
|
862
|
+
await client.fields.create(layoutModel.id, {
|
|
863
|
+
label: 'Footer Navigation',
|
|
864
|
+
field_type: 'rich_text',
|
|
865
|
+
api_key: 'footer_navigation',
|
|
866
|
+
validators: {
|
|
867
|
+
rich_text_blocks: { item_types: [menuItemBlock.id] },
|
|
868
|
+
},
|
|
869
|
+
});
|
|
870
|
+
await client.fields.create(layoutModel.id, {
|
|
871
|
+
label: 'Copyright',
|
|
872
|
+
field_type: 'string',
|
|
873
|
+
api_key: 'copyright',
|
|
874
|
+
});
|
|
875
|
+
|
|
876
|
+
console.log('');
|
|
877
|
+
console.log(' Models created: Page, Case Study, Legal Page, Post');
|
|
878
|
+
console.log(' Singletons created: Layout, Case Studies Listing, Post Listing');
|
|
879
|
+
console.log(' Blocks created: Hero, Button, Menu Item');
|
|
880
|
+
}
|
|
881
|
+
|
|
477
882
|
function generateReadme(projectName, cms) {
|
|
478
883
|
const title = projectName || 'Project Title';
|
|
479
884
|
|
|
@@ -598,9 +1003,9 @@ This website is built using the [NextJS](https://nextjs.org/) framework, utilisi
|
|
|
598
1003
|
Create \`.env.local\` file in the root directory:
|
|
599
1004
|
|
|
600
1005
|
\`\`\`env
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
1006
|
+
NEXT_DATOCMS_API_TOKEN=your_graphql_token
|
|
1007
|
+
DATO_API_TOKEN=your_readonly_token
|
|
1008
|
+
NEXT_DATOCMS_ENVIRONMENT="draft"
|
|
604
1009
|
\`\`\`
|
|
605
1010
|
|
|
606
1011
|
3. **Start the development server**
|
package/package.json
CHANGED